当前位置: 首页 > 知识库问答 >
问题:

Tkinter GUI和读取串行

朱和惬
2023-03-14

我是python和tkinter的新手。。。我使用Tkinter显示仪表并通过串行com接收信息。我已经准备好GUI,现在需要读取序列值。

我面临的问题是我不能连续读取串行COM。我遇到了self.after,但它仍然不起作用。基本上它不会在控制台上显示任何值。知道可能出了什么问题吗?

这是主要代码。我还有一个文件meter.py

import tkinter as tk
import meter as m
import serial

class Mainframe(tk.Frame):

   def __init__(self,master,*args,**kwargs):
      super(Mainframe,self).__init__(master,*args,**kwargs)

      self.meter = m.Meter(self,height = 400,width = 400)
      self.meter.setrange(20,90)
      self.meter.pack()

      tk.Scale(self,width = 15 ,from_ = 20, to = 90
      ,orient = tk.HORIZONTAL
      ,command = self.setmeter).pack()

      tk.Button(self,text = 'Quit',width = 15,command = master.destroy).pack()
      tk.Button(self,text = 'Zoom',width = 15).pack()

   def setmeter(self,value):
      value = int(value)
      self.meter.set(value)   

class App(tk.Tk):

    def __init__(self):
        super(App,self).__init__()

        self.title('Try Meter')

        Mainframe(self).pack()

    def serie():
        ser = serial.Serial('COM2', 2400, timeout=1)
        line = ser.readline()   # read a '\n' terminated line
        print (line)
        self.after(100,serie) 


App().mainloop()

共有2个答案

富念
2023-03-14

代码不能按预期工作的原因是您从未调用App类的serie()方法。如果您修改代码以添加此调用,也许在__init__()方法的末尾,您应该会看到串行数据被打印到控制台。

然而,在同一个线程中处理串行IO和用户界面不是一个好主意。如果没有任何数据要从串行端口读取,readline()将阻塞长达1秒(初始化串行端口时设置的超时值)。这将阻塞tk主循环,并且您的用户界面将完全没有响应。在我看来,解决这个问题的最好方法是使用一个异步IO库。我喜欢Twisted,因为它内置了对tk(示例)和串行通信的支持,但还有其他几个选项。如果这感觉有点过分,您还可以分别使用线程多重处理模块将串行轮询代码移动到自己的线程或进程。

回答问题的第二部分:

readSerial()中,您创建了Mainframe()的一个新实例,但我认为您实际想要做的是使用在应用程序类的初始化()方法中创建的实例。您需要使用类似于self的代码将其存储为属性。main\u frame=Mainframe(self),然后在readSerial()中,您可以使用根目录访问它。主框架。设置计(50)

尉迟正奇
2023-03-14

让它工作起来。这是密码

class Mainframe(tk.Frame):

    def __init__(self,master,*args,**kwargs):
        super(Mainframe,self).__init__(master,*args,**kwargs)

        self.meter = Meter(self,height = 400,width = 400)
        self.meter.setrange(20,90)
        self.meter.pack()

        tk.Scale(self, width = 15, from_ = 20, to = 90, orient = tk.HORIZONTAL, 
                 command = self.setmeter).pack()

        tk.Button(self,text = 'Quit',width = 15,command = master.destroy).pack()
        tk.Button(self,text = 'Zoom',width = 15).pack()

        self.setmeter(15)

    def setmeter(self,value):
        value = int(value)
        self.meter.set(value)

class App(tk.Tk):

    def __init__(self):
        super(App,self).__init__()
        self.title('My Meter')     
        Mainframe(self).pack() 

root = App()       

serBuffer =b"" 
aux=""

def readSerial():
    serBuffer=b""
    while True:
        c = ser.read() # attempt to read a character from Serial

        #was anything read?
        if len(c) == 0:
            #print("cero")
            break
        #else:
            #print (len(c))

        if c == b'\n' :
            #we have all the info
            aux = serBuffer.split(b" ")
            print (aux[0]," ",aux[1])

            miinstance= Mainframe()
            miinstance.setmeter(50)

            #root.update()

            serBuffer = "" # empty the buffer
        else:
            serBuffer+=c# add to the buffer

        #aux= str(serBuffer, 'utf-8')


    root.after(700, readSerial) # check serial again soon

root.after(1000, readSerial)

root.mainloop()

顺便说一句,我知道我正在努力更新仪表。当我收到一个完整的字符串(由\n检测)我想传递该值的小部件来更新仪表。设置值的函数是seteter,但是用我的代码

miinstance= Mainframe()
miinstance.setmeter(50) <--put this value as test

我得到这个错误。第一行是接收到的串行字符(正确)

b'90'   b'0'
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Program Files\Python 3.5\lib\tkinter\__init__.py", line 1535, in __call__
return self.func(*args)
  File "C:\Program Files\Python 3.5\lib\tkinter\__init__.py", line 582, in callit
    func(*args)
  File "C:/Users/MARTIN/Documents/Personal/phyton/Nuevo anemometer/read_serie_v2.py", line 258, in readSerial
    miinstance= Mainframe()
TypeError: __init__() missing 1 required positional argument: 'master'

我试图把“master”作为一个参数,但它说“master”没有定义。

我的代码(最初是从web上获得的)在GUI中有一个比例,

tk.Scale(self,width = 15 ,from_ = 20, to = 90
  ,orient = tk.HORIZONTAL
  ,command = self.setmeter).pack()

当我移动它时,它会更新仪表,但我不需要它。仪表应根据收到的序列信息进行更新。

你知道哪里不对吗?

 类似资料:
  • 我试图读取3温度设备使用WinForm和Modbus 485协议。基本上,我必须定期向每个设备写入命令,等待响应,当我得到响应时,处理它。每个设备都有一个唯一的通信地址。为了定期发送命令,我使用了计时器。这就是我发送命令的方式和处理响应的地方: 对于每个设备,等等。这是我的serialport数据接收事件: 所以我的沟通应该是: 然后再次发送命令device1。问题是,我有时得到通信超时错误,我知

  • 我无法通过串行连接读取来自arduino的串行数据。为了解决串行和gui需要同时运行的问题,我使用了。函数后,每100ms调用一次更新序列。然而,当我运行这段代码时,没有弹出窗口,并且我得到一个错误,说我已经超过了最大递归深度。这是我的密码:

  • 这是http://www.gravitech.us/7segmentshield.html给出的代码。 那么怎样才能逐行阅读呢?

  • 我正在尝试使用shell和java的组合来读取和写入串行端口。目标是能够使用PrintWriter和BufferedReader从连接到串行端口的设备发送和接收命令。我知道这可以用不同的方式来实现(不使用shell),但这不是我想要的。我希望能够使用shell和java实现这一点。 这是我的代码: 有了这段代码,我特别尝试从串行端口读取数据。我使用java运行shell命令来访问串行端口,然后读取

  • 问题内容: 给定一个不太长的字符串,逐行读取字符串的最佳方法是什么? 我知道你可以做: 另一种方法是在eol上获取子字符串: 还有其他更简单的方法吗?我对上述方法没有任何问题,只是想知道你们中是否有人知道一些看起来更简单,更有效的方法? 问题答案: 您也可以使用String方法: 这使您可以方便地将所有行排列在一起。 我不知道拆分的性能。它使用正则表达式。

  • 我试图在一些python代码和arduino代码之间来回“乒乓”信息。我想定期向arduino代码发送两个设定点(例如,在分钟内),在arduino上读取它们 现在,我无法获得可靠的信息来来回跳转。我在搜索中没有找到任何与此类似的内容,我试图修改的所有内容都不起作用。最接近我的是这个(实际上它并没有在发送和接收之间来回切换): python 阿杜伊诺: 我最终得到的只是重复的相同值(不是实际发送的