weixin_53420152 2021-07-05 16:37 采纳率: 100%
浏览 71
已采纳

tkinter判断button状态偶尔报错?



# -*- coding: utf-8 -*-
"""
#导入库
import tkinter as tk 
import os
import time
import serial.tools.list_ports
import threading

def Selection():
    pass
def Savefile(dd):
    OutputText.delete(1.0,tk.END)
    OutputText.insert(tk.END, dd)
    filepath = filePath.get()
    filename = time.strftime("%Y-%m-%d", time.localtime())
    wholename = os.path.join(filepath, filename) #完整的路径+文件名(无后缀)
    if os.path.exists(filepath) == False:
        os.mkdir(filepath) 
    with open(wholename+'.txt', 'a') as f1:
        ls = dd +' '+ time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) +'\n'#\t表示4个空格
        f1.writelines(ls)

def Readser1():
    #global data1 作为参数传给savefile函数,savefile函数不调用data1了,所以不用声明全局变量了
    while t1_flag:
        try:
            data1=ser1.readline()#readall如果sleep时间太短可能会发生数据截断,使用readline按行读取用初始化的timeout控制读取时限
            #ser1.flushInput()缓冲区清理基本用不上
            data1 = data1.decode('ASCII')
            if len(data1)>0:
                Savefile(data1.rstrip())
                ddaa=[]
                data=data1.split(' ')
                for i in data:
                    if len(i)>0:
                        ddaa.append(i)
                
                labelyali1.configure(text=ddaa[len(ddaa)-3])#原始数据后边空格接了回车符,多了一个len数,所以减去23
                labeljieguo1.configure(text=ddaa[len(ddaa)-2])
            time.sleep(0.5)
        except Exception as e:
            print("错误: ", e)
def Readser2():
    #global data2
    while t2_flag:
        try:
            data2=ser2.readline()
            #ser2.flushInput()
            data2 = data2.decode('ASCII')
            if len(data2)>0:
                Savefile(data2.rstrip())
                ddaa=[]
                data=data2.split(' ')
                for i in data:
                    if len(i)>0:
                        ddaa.append(i)
                labelyali2.configure(text=ddaa[len(ddaa)-3])
                labeljieguo2.configure(text=ddaa[len(ddaa)-2])
            time.sleep(0.5)
        except Exception as e:
            print("错误: ", e)
def Start():
    global t1_flag
    t1_flag=True
    global t2_flag
    t2_flag=True
    
    l1.config(state='disable')
    l2.config(state='disable')
    l3.config(state='disable')
    btnStop['state']= 'normal'
    btnStart['state'] = 'disabled'
    entryfilePath.configure(state = 'disabled')
    Serlist()
    if plcflag.get() == 1:   
            print('plc')
    if serflag_1.get() == 1:#串口初始化并启动串口线程
        try:#防止串口报错退出主程序,使用try结构忽略报错
            ser1.port = 'COM12'   #端口号
            ser1.baudrate = 9600  #波特率
            ser1.bytesize=serial.EIGHTBITS
            ser1.timeout = 3     #超时设置,1s未读取到数据则返回结果
            ser1.stopbits=serial.STOPBITS_ONE#1停止位
            ser1.parity=serial.PARITY_NONE#无校验
            ser1.open()   #打开串口
        except Exception as e:
            print("错误: ", e)
        t1=threading.Thread(target=Readser1)#线程指向readser1
        t1.start()
        
    if serflag_2.get() == 1:  
        try:
            
            ser2.port = 'COM12'   #端口号
            ser2.baudrate = 9600  #波特率
            ser2.bytesize=serial.EIGHTBITS
            ser2.timeout = 3     #超时设置,1s未读取到数据则返回结果
            ser2.stopbits=serial.STOPBITS_ONE#1停止位
            ser2.parity=serial.PARITY_NONE#无校验
            ser2.open()   #打开串口   
        except Exception as e:
            print("错误: ", e)
        t2=threading.Thread(target=Readser2)
        t2.start()
    
def Stop():
    global t1_flag
    global t2_flag
    l1.config(state='normal')
    l2.config(state='normal')
    l3.config(state='normal')
    btnStop['state'] ='disabled'
    btnStart['state'] = 'normal'
    if serflag_1.get() == 1:
        t1_flag=False
        if ser1.is_open:
            ser1.close()
    if serflag_2.get() == 1: 
        t2_flag=False
        if ser2.is_open:
            ser2.close()
    print('lllllllllllllllllllllllllllllllllllllll')
    
def Serlist():
    port_list = list(serial.tools.list_ports.comports())
    port_serial = []

        #*******提取COM口的端口号*******
    if len(port_list) <= 0:
        RunInf.set("未找到端口!")    
    else:
        for i in range(len(port_list)):
            port_serial.append(list(port_list[i])[0])
        
        RunInf.set(port_serial)
        #btnStart['state'] = 'normal'
    

def Showtime():
        while time_flag:
            tt=time.strftime("%Y-%m-%d \n %H:%M:%S", time.localtime())
            labeltime.configure(text=tt)
            if btnStop['state'] == 'disabled':
                if plcflag.get() == 0 and serflag_1.get() == 0 and serflag_2.get() == 0:
                    btnStart['state'] = 'disabled'
                else:
                    btnStart['state'] = 'normal'
            time.sleep(0.2)

window = tk.Tk()#窗体变量定义
window.title('试漏工控机')#定义窗体名称
window.geometry('900x600')#定义主窗体尺寸
 
l = tk.Label(window, width=15,bg='red',text='实验室',font = ('楷体', 20))
l.place(x=400,y=0,width=200,heigh=40)
         
plcflag = tk.IntVar()  # 定义plcflag和serflag_1整型变量用来存放选择行为返回值0或者1
serflag_1 = tk.IntVar()
serflag_2 = tk.IntVar()

plcflag.set(0)  # 设置三个复选框的默认状态,1为选中,0为未选中
serflag_1.set(1)
serflag_2.set(0)

l1 = tk.Checkbutton(window, text='PLC抓取零件号',font = ('楷体', 12),variable=plcflag)   
l1.place(x=10,y=60,width=130,heigh=20)
l1.config(state='normal')
l2 = tk.Checkbutton(window, text='串口1抓取测量数据',font = ('楷体', 12),variable=serflag_1)
l2.place(x=10,y=90,width=160,heigh=20)
l2.config(state='normal')
l3 = tk.Checkbutton(window, text='串口2抓取测量数据',font = ('楷体', 12),variable=serflag_2)
l3.place(x=10,y=120,width=160,heigh=20)
l3.config(state='normal')

btnStart = tk.Button(window, text = "开始采集", command = Start)
btnStart.place(x=10,y=200,width=80,heigh=30)
btnStop = tk.Button(window, text = "停止采集", state = 'disabled',command = Stop)
btnStop.place(x=110,y=200,width=80,heigh=30)


filePath = tk.StringVar(value = os.getcwd())
labelfilePath = tk.Label(window,text = '保存路径:')
labelfilePath.place(x=10,y=500,width=80,heigh=20)
entryfilePath = tk.Entry(window,width = 35, textvariable = filePath)
entryfilePath.place(x=100,y=500,width=300,heigh=20)

labelRunInf = tk.Label(window,font = ('楷体', 15), text="串口列表:")
RunInf = tk.StringVar(value = '请勾选通信方式')   #定义TK字符变量,储存提示信息
labelInf = tk.Label(window,font = ('楷体', 15),textvariable = RunInf)
labelRunInf.place(x=0,y=10,width=100,heigh=20)
labelInf.place(x=100,y=10,width=150,heigh=20)
labeloil = tk.Label(window,font = ('楷体', 15), text = '油道(串口1)')
labeloil.place(x=10,y=340,width=120,heigh=30)
labelwater = tk.Label(window,font = ('楷体', 15), text = '水道(串口2)')
labelwater.place(x=10,y=380,width=120,heigh=30)
labelyali = tk.Label(window,font = ('楷体', 15), text = '测试压力')
labelyali.place(x=350,y=300,width=120,heigh=30)
labeljieguo = tk.Label(window,font = ('楷体', 15), text = '测量结果')
labeljieguo.place(x=550,y=300,width=120,heigh=30)
labelyali1=tk.Label(window,font = ('楷体', 15), text = '测试压力')
labelyali1.place(x=350,y=340,width=120,heigh=30)
labelyali2 = tk.Label(window,font = ('楷体', 15), text = '测试压力')
labelyali2.place(x=350,y=380,width=120,heigh=30)
labeljieguo1 = tk.Label(window,font = ('楷体', 15), text = '测量结果')
labeljieguo1.place(x=550,y=340,width=120,heigh=30)
labeljieguo2 = tk.Label(window,font = ('楷体', 15), text = '测量结果')
labeljieguo2.place(x=550,y=380,width=120,heigh=30)
OutputText = tk.Text(window, wrap = tk.WORD, width = 800, height = 40, font = ('TimesNewRoman',10))
OutputText.place(x=10,y=540,width=800,heigh=40)

ser1 = serial.Serial()#定义两个串口变量
ser2 = serial.Serial()

labeltime = tk.Label(window,text = '')#定义时间标签
labeltime.place(x=800,y=0,width=100,heigh=40)#定义时间标签位置

time_flag=True#时间显示随窗口初始化就产生了,所以定义在主线程里面
t=threading.Thread(target=Showtime)#定义时间线程
t.start()#启动时间线程

def S_time(event):
    print(btnStop['state'])
def Killtime(event):
    global time_flag#如果函数内部 修改 外部变量必须先声明为全局变量
    global t1_flag
    global t2_flag
    t1_flag=False#这里发生修改动作,如果只是引用外部变量就不用声明全局变量
    t2_flag=False
    time_flag = False
window.bind('<Button-3>',S_time)#在tk窗口绑定鼠标右键激发事件s-time

window.bind('<Destroy>',Killtime)#在tk窗口绑定鼠标右键激发事件killtime
window.mainloop()#窗体呈现,需要注意的是窗体循环执行的只有关键事件,例如按钮变量等等

程序运行时偶尔会报错如下:

Exception in thread Thread-26:
Traceback (most recent call last):
  File "C:\Users\ni799\AppData\Local\Continuum\anaconda3\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "C:\Users\ni799\AppData\Local\Continuum\anaconda3\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "C:/Users/ni799/.spyder-py3/tongxun.py", line 148, in Showtime
    if btnStop['state'] == 'disabled':
  File "C:\Users\ni799\AppData\Local\Continuum\anaconda3\lib\tkinter\__init__.py", line 1489, in cget
    return self.tk.call(self._w, 'cget', '-' + key)
_tkinter.TclError: invalid command name ".!button2"

如果屏蔽对按钮状态的判断则不会报错,请问哪里有错误?请帮忙指正,十分感谢!
屏蔽如下字段程序则不会报错:

if btnStop['state'] == 'disabled':
   if plcflag.get() == 0 and serflag_1.get() == 0 and serflag_2.get() == 0:
        btnStart['state'] = 'disabled'
   else:
        btnStart['state'] = 'normal'
  • 写回答

1条回答 默认 最新

  • weixin_53420152 2021-07-06 12:36
    关注

    此问题已经解决,使用checkbutton的command命令承载button的normal或diasbled功能即可。
    不在时间线程判断button状态。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置