Python GUI 中的实时绘图

4
我正在尝试编写一个Python图形用户界面,并需要进行实时绘图。我目前有一个从机器接收数据的程序,希望能够在接收到时绘制出机器输出的值。我一直在研究,根据我目前所了解的,似乎tkinter或任何库都无法在GUI中完成这项任务。是否有人知道tkinter是否可以完成此操作,或者是否有其他库可实现此实时绘图?
另外,当我接收数据时,如何将数据写入文件?
非常感谢您的帮助。

wxPython会更适合这个任务吗? - Sachin Weerasooriya
你的程序目前是如何接收数据的? - Simon
@SachinWeerasooriya:wxPython更适合吗?可能不是。也许同样适合。 - Bryan Oakley
这里是实际代码的链接 https://github.com/PowerAndEnergySystemsUIUC/ServoStar_python/blob/master/ServoStar.py ,但基本上有一个“ServoDrive”类,其中包含不同的方法来获取速度和扭矩,我希望能够随时间绘制它们。 - Sachin Weerasooriya
2个回答

8

看起来你是通过轮询获取数据,这意味着你不需要线程或多个进程。只需在所选接口轮询设备并绘制单个点即可。

以下是一个使用一些模拟数据来说明一般思路的示例。它每100ms更新一次屏幕。

import Tkinter as tk
import random

class ServoDrive(object):
    # simulate values
    def getVelocity(self): return random.randint(0,50)
    def getTorque(self): return random.randint(50,100)

class Example(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        self.servo = ServoDrive()
        self.canvas = tk.Canvas(self, background="black")
        self.canvas.pack(side="top", fill="both", expand=True)

        # create lines for velocity and torque
        self.velocity_line = self.canvas.create_line(0,0,0,0, fill="red")
        self.torque_line = self.canvas.create_line(0,0,0,0, fill="blue")

        # start the update process
        self.update_plot()

    def update_plot(self):
        v = self.servo.getVelocity()
        t = self.servo.getTorque()
        self.add_point(self.velocity_line, v)
        self.add_point(self.torque_line, t)
        self.canvas.xview_moveto(1.0)
        self.after(100, self.update_plot)

    def add_point(self, line, y):
        coords = self.canvas.coords(line)
        x = coords[-2] + 1
        coords.append(x)
        coords.append(y)
        coords = coords[-200:] # keep # of points to a manageable size
        self.canvas.coords(line, *coords)
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

哇,我觉得这个完美地符合我想做的事情。非常感谢! - Sachin Weerasooriya
如果你将“Tkinter”改为“tkinter”,它也适用于Python 3! - Aoki Ahishatsu

0

谢谢提供的链接,它们很有帮助。但是抱歉,我对Python和GUI编程都很新,所以我只想确保我理解了问题。人们在将实时数据绘制到GUI上遇到困难的原因是因为虽然新点被绘制出来了,但图形没有重新调整大小以显示添加的点吗? - Sachin Weerasooriya
1
如果获取数据需要相当长的时间,那么说你必须使用多线程有点过了。如果获取数据很便宜,单个线程就足够了,因为GUI通常有大约99%的空闲时间。 - Bryan Oakley
如果您不需要图形调整大小,则使用blitting到Tkinter GUI将通过GUI显示数据(点,线等)的更新,因此它就足够了。这取决于您要做什么(是为大量人员或个人使用,还是需要扩展等)。另外,我可能不应该包括整个社区,我相信有很多人知道如何轻松地做到这一点。我只是知道有很多非计算机专业的人对此有疑问,因此我认为这是一个更复杂的想法。 - chase
好的,太棒了,谢谢大家!另外,如果我想打印一个不断变化的变量的值,你们知道在tkinter中哪个小部件最适合我使用,它会自动更新并显示变量的当前值吗? - Sachin Weerasooriya
一个Tkinter标签是我会开始使用的,虽然我不确定它是否是最适合的小部件。另外,既然你似乎正在走我曾经走过的路,我应该提到我最初使用Tkinter,后来转向Qt,因为它看起来更加花哨。他们还有很好的多线程程序示例,并且似乎被大型社区所使用。 如果你认为我可以帮助你的具体项目,请随时查看我的问题并提出任何问题。 - chase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接