【问题标题】:Marker position without pixel decision?没有像素决定的标记位置?
【发布时间】:2022-01-16 12:39:45
【问题描述】:

如果我设置小 matplotlib 标记的位置,他们必须“决定”选择哪个像素。我认为在 Matlab 中不是这种情况,标记可以位于像素之间,两个像素共享亮度。

在附加的示例中,我屏幕上的标记不会执行平滑的圆圈,而是会在像素之间跳转。在 Matlab 中,这个圆圈看起来很平滑。我可以使用 matplotlib 达到同样的效果吗?

import tkinter as tk
import os
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import time

class Plotwindow():
    def __init__(self, root, size):
        self.root = root
        self.fig = Figure(size, constrained_layout=True)
        self.ax = self.fig.add_subplot(111)
        self.canvas = FigureCanvasTkAgg(self.fig, master=root.plot_frame)
        self.canvas.get_tk_widget().pack()

    def clear(self):
        self.ax.cla()

    def plot(self, x, y):
        self.ax.scatter(x, y, marker='o', s=2, color='black', snap=False)
        self.ax.set_xlim(20*np.array([-1, 1]))
        self.ax.set_ylim(20*np.array([-1, 1]))
        self.canvas.draw()
        self.canvas.flush_events()
        
class NewGUI():
    def __init__(self):
        self.root = tk.Tk()
        self.root.resizable(False, False)
        self.root.geometry("405x405+400+200")

        self.button = tk.Button(self.root, text="Move", command=self.move)
        self.button.pack(side='top', fill='x')
        self.button = tk.Button(self.root, text="Hold", command=self.hold)
        self.button.pack(side='top', fill='x')

        self.plot_frame = tk.Frame()
        self.plot_frame.pack(side='bottom', fill='x')
        self.plot_window = Plotwindow(self, (15,15))
        self.plot_window.plot(1,0)

        self.root.mainloop()

    def move(self):
        for i in range(20):
            self.plot_window.clear()
            time.sleep(0.01)
            phi = 2*np.pi*i/20
            x = np.cos(phi)
            y = np.sin(phi)
            self.plot_window.plot(x,y)

    def hold(self):
        for i in range(20):
            phi = 2*np.pi*i/20
            x = np.cos(phi)
            y = np.sin(phi)
            self.plot_window.plot(x,y)

if __name__ == '__main__':
    new = NewGUI()

【问题讨论】:

  • 设置 snap=False。
  • 这确实是我遇到的问题,但它没有帮助......仍然抢购? (编辑代码)
  • 这个问题的第一个答案的最后评论说2018年的抢购问题还没有解决,2021年还不可能吗? stackoverflow.com/questions/39183658/…
  • github.com/matplotlib/matplotlib/issues/8746 可以在那里评论吗?我怀疑如果您尝试 mpl-Cairo 这不是问题。当然增加 dpi 通常是一个很好的解决方案
  • 将此作为答案发布,非常感谢!使用 cairo 后端看起来好多了!

标签: python matplotlib


【解决方案1】:

根据 Jody Klymak 的评论,即使没有 snap=False,我也可以通过 cairo 后端得到我想要的,请参阅附件。

import tkinter as tk
import os
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkCairo')
from matplotlib.backends.backend_tkcairo import FigureCanvasTkCairo
from matplotlib.figure import Figure
import time

class Plotwindow():
    def __init__(self, root, size):
        self.root = root
        self.fig = Figure(size, constrained_layout=True)
        self.ax = self.fig.add_subplot(111)
        self.canvas = FigureCanvasTkCairo(self.fig, master=root.plot_frame)
        self.canvas.get_tk_widget().pack()

    def clear(self):
        self.ax.cla()

    def plot(self, x, y):
        self.ax.scatter(x, y, marker='o', s=2, color='black')
        self.ax.set_xlim(20*np.array([-1, 1]))
        self.ax.set_ylim(20*np.array([-1, 1]))
        self.canvas.draw()
        self.canvas.flush_events()
        
class NewGUI():
    def __init__(self):
        self.root = tk.Tk()
        self.root.resizable(False, False)
        self.root.geometry("405x405+400+200")

        self.button = tk.Button(self.root, text="Move", command=self.move)
        self.button.pack(side='top', fill='x')
        self.button = tk.Button(self.root, text="Hold", command=self.hold)
        self.button.pack(side='top', fill='x')

        self.plot_frame = tk.Frame()
        self.plot_frame.pack(side='bottom', fill='x')
        self.plot_window = Plotwindow(self, (15,15))
        self.plot_window.plot(1,0)

        self.root.mainloop()

    def move(self):
        for i in range(20):
            self.plot_window.clear()
            time.sleep(0.01)
            phi = 2*np.pi*i/20
            x = np.cos(phi)
            y = np.sin(phi)
            self.plot_window.plot(x,y)

    def hold(self):
        for i in range(20):
            phi = 2*np.pi*i/20
            x = np.cos(phi)
            y = np.sin(phi)
            self.plot_window.plot(x,y)

if __name__ == '__main__':
    new = NewGUI()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-31
    • 2016-09-07
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 2012-01-04
    相关资源
    最近更新 更多