【问题标题】:Python tkinter making serial work with buttonsPython tkinter 使用按钮进行串行工作
【发布时间】:2018-10-20 16:52:29
【问题描述】:

我是 OOP 的新手,我正在尝试为自己制作一个 GUI。 我想做一个模拟器程序。我正在用 Arduino 读取串行数据。

我的问题是:

  1. 为什么当我获取串行数据时按钮消失了? 显示串行数据时,启动按钮的一半消失。
  2. 如何在代码中使“开始”和“停止”按钮工作? Application() 将始终运行,当我按下开始按钮时,Application.run() 函数将运行,直到我按下停止按钮。

示例代码:

from tkinter import *
import serial
import serial.tools.list_ports as ports

switch=False
class Application(Frame):


    def __init__(self,master,*args,**kwargs):
        Frame.__init__(self,*args,**kwargs)
        ratios=self.GetScreenRatio()
        self.CreateCanvas()
        self.PackWidgets()

    def updateGui(self): 
        self.update()

    def CreateCanvas(self):

        self.canvas=Canvas(root,width=self.winfo_screenwidth(),height=self.winfo_screenheight())
        self.canvas.pack()

    def GetScreenRatio(self):

        self.screen_width = self.winfo_screenwidth()/1920
        self.screen_height = self.winfo_screenheight()/1080

    def PackWidgets(self):

        x_ratio=self.screen_width
        y_ratio=self.screen_height
        letter_ratio=(x_ratio+y_ratio)/2


        self.start_button=Button(root,text='Start',command=self.Start,activeforeground='white',
               bg='green',activebackground='green',fg='white',width=21,height=2,font='bold')
        self.start_button.place(x=120*x_ratio,y=800*y_ratio)

        self.stop_button=Button(root,text='Stop',command=self.Stop,activeforeground='white',
               bg='red',activebackground='red',fg='white',width=21,height=2,font='bold')
        self.stop_button.place(x=760*x_ratio,y=800*y_ratio)

        self.quit_button=Button(root,text='Quit',bg='black',activebackground='black',command=root.destroy,
                                fg='white',activeforeground='white',width=21,height=2,font='bold')
        self.quit_button.place(x=1400*x_ratio,y=800*y_ratio)


        self.bridge_pointer=Label(root,text='Híd neve:',font=("Courier",round(50*letter_ratio)),fg='#0078ef')
        self.bridge_pointer.place(x=1*x_ratio,y=1*y_ratio)
        self.bridge_name=Label(root,font=("Courier",round(50*letter_ratio)),fg='#0078ef')
        self.bridge_name.place(x=400*x_ratio,y=1*y_ratio)
        self.bridge_value=Label(root,text='0.0',font=("Courier",round(200*letter_ratio)),fg='#0078ef')
        self.bridge_value.place(x=200*x_ratio,y=200*y_ratio)
        self.value_prefix=Label(root,text='Kg',fg='#0078ef',font=("Courier", round(100*letter_ratio)))
        self.value_prefix.place(x=390*x_ratio,y=480*y_ratio)

        teglalap=self.canvas.create_rectangle(1*x_ratio,1*y_ratio,50*x_ratio,
                50*y_ratio,fill="#0078ef",width=2)

        teglalap2=self.canvas.create_rectangle(987*x_ratio,612*y_ratio,1165*x_ratio,
                                  602*y_ratio,fill="#909090",width=2)

        teglalap3=self.canvas.create_rectangle(1215*x_ratio,612*y_ratio,1360*x_ratio,
                                  602*y_ratio,fill="#909090",width=2)
    def Start(self):
        self.run()


    def Stop(self):
        #Stop serial connection(stop the Application.run() func)
        pass
    def run(self):
        self.MakeSerial()
        self.Update()
        root.mainloop()

    def MakeSerial(self):
        try:
            for ee in list(ports.comports()):
                if ee.serial_number=='55639313633351A07142':
                    usb=ee.device
            self.ser=serial.Serial(usb,baudrate=57600,timeout=2)
        except UnboundLocalError:
            root.destroy()
            print('Nincs csatlakoztatva az Arduino! ')


    def Update(self):
        try:
            if self.ser.isOpen():
                data = self.ser.readline(self.ser.inWaiting())
                self.bridge_value['text']=data
                self.after(10,self.Update)
                print(data)
            else:
                print('Portot nem lehet megnyitni!')
        except serial.serialutil.SerialException:
            print("Soros kapcsolat megszakadt")
        except AttributeError:
            pass


root=Tk()
root.state('zoomed')
window=Application(root)

有什么好的建议吗?

这是错误:

for c in list(self.children.values()): c.destroy() 
File "C:XXXXX\GUI proba.py", line 77, in destroy 
self.Stop() RecursionError: maximum recursion depth exceeded

【问题讨论】:

  • Edit 你的问题并解释为什么你在所有 Buttons上使用command=root.destroy
  • 编辑代码!
  • 大部分情况下是的,但我还需要一件事,如何使用停止按钮停止 run() 函数?

标签: python button tkinter


【解决方案1】:

评论:当我按下退出按钮时,我的窗口冻结,无法执行任何操作

我重载了从root.destroy() 调用的Application.destroy()。我们在那里调用root.destroy(),这会导致无限循环。
def destroy(... 更改为def quit(...


问题:如何使用停止按钮停止 run() 函数

使用标志变量,例如self.stopUpdate如下:

def __init__(self,master,*args,**kwargs):
   ...
    self.stopUpdate = None
    self.MakeSerial()

def PackWidgets(self):
    ...
    self.quit_button=Button(..., command=self.quit, ...

def quit(self):
    self.Stop()
    # Wait until Update returns
    while self.stopUpdate:
        time.sleep(1)
    root.destroy()

def Start(self):
    self.stopUpdate = False
    self.Update()

def Stop(self):
    self.stopUpdate = True

def Update(self):
    if self.stopUpdate:
        # Indicates Update returns, for self.destroy(...
        self.stopUpdate = False
        return
    try:
        ...

全部删除

#def run(self):
#    self.MakeSerial()
#    self.Update()
#    root.mainloop()
  • self.MakeSerial() 移至__init__(...
  • self.Update() 移至self.Start(...
  • root.mainloop() 移动到脚本底部。

注意
one try: ... except: 块捕获多个异常是很糟糕的。
使用 one 表示 .ser.readline(...,使用 one 表示 =data

【讨论】:

  • 停止按钮现在可以正常工作,但是有一个小问题,当我按下退出按钮时,我的窗口冻结了,无法执行任何操作。
  • 这是错误:for c in list(self.children.values()): c.destroy() File "C:XXXXX\GU​​I proba.py", line 77, in destroy self .Stop() RecursionError: 超出最大递归深度
猜你喜欢
  • 2023-03-29
  • 1970-01-01
  • 2018-01-28
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
相关资源
最近更新 更多