按下按钮 tkinter 会阻止部分软件的执行

pressing button tkinter blocks execution of a part of the software

我在 python 中有一个程序可以读取我的串口数据。我正在写一个新的部分,在同一个串行端口上单击一个按钮,我发送特定的数据。

下面是我正在使用的部分代码

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):

        # def sch_plus_callback():
        #     self.ser.reset_input_buffer()
        #     self.ser.reset_output_buffer()
        #     self.ser.write(b'\x02\x56\x81\x80\x80\x80\x80\x80\x42\x33\x04')
        #     logging.info("write on serial")
        #     self.ser.reset_input_buffer()
        #     self.ser.reset_output_buffer()

        tk.Tk.__init__(self, *args, **kwargs)
        # self.insert_lengh_text_label = tk.Label(self, text="Max Packet Length")
        # self.insert_lengh_text_label.pack()
        # self.insert_lengh_text = tk.Entry(self, width=2)
        # self.insert_lengh_text.pack()
        self.serial_text_label = tk.Label(self, text="String")
        self.serial_text_label.pack()
        self.serial_text = tk.Text(self, height=1, width=50)
        self.serial_text.pack()

        self.port = 'COM3'
        self.baud = 38400

        self.ser = serial.Serial(self.port, self.baud, timeout=None)
        if self.ser.isOpen():
            self.ser.close()
            self.ser.open()

        self.ser.reset_input_buffer()
        self.ser.reset_output_buffer()

        logging.info("created serial port")

        # self.sch_plus_button = tk.Button(self, text="S+", command=sch_plus_callback)
        # self.sch_plus_button.pack()

        # start the serial_text_label "ticking"
        self._update_scheduled = threading.Condition()
        self._terminating = threading.Event()
        self.update_screen()

    def mainloop(self):
        with ThreadPoolExecutor() as executor:
            future = executor.submit(self._do_update_screen_loop)
            try:
                return super().mainloop()
            finally:
                # letting the thread to know we're done
                self._terminating.set()
                with self._update_scheduled:
                    self._update_scheduled.notify_all()

    def update_screen(self):
        with self._update_scheduled:
            self._update_scheduled.notify_all()
        self.after(500, self.update_screen)

    def _do_update_screen_loop(self):
        while True:
            with self._update_scheduled:
                self._update_scheduled.wait()
            if self._terminating.is_set():
                return
            self._do_data_screen()

    def _do_data_screen(self):
        self.serial_text.delete('1.0', tk.END)
        # dimension = self.insert_lengh_text.get()
        # if dimension == "":
        #     dimension = 1

    data = ""
    data_raw = self.ser.read(1)
    if data_raw == b'\x02':
        data_raw = self.ser.read_until(b'\x03')
        data = "02-" + str(data_raw.hex('-'))
        self.ser.reset_input_buffer()
        self.ser.reset_output_buffer()

    hex_list = [int(x, 16) for x in data.split('-')]

    check = checksum_calculation(hex_list)
    if hex_list[4] == check[0] and hex_list[5] == check[1]:
        logging.debug("Checksum correct")
    logging.debug(str(hex_list))

    self.serial_text.insert(tk.END, data)
    # self.serial_text_label.configure(text=data)

我正在使用按钮写入串口

self.sch_plus_button = tk.Button(self, text="S+", command=sch_plus_callback)
self.sch_plus_button.pack()

调用

        def sch_plus_callback():
            self.ser.reset_input_buffer()
            self.ser.reset_output_buffer()
            self.ser.write(b'\x02\x56\x81\x80\x80\x80\x80\x80\x42\x33\x04')
            logging.info("write on serial")
            self.ser.reset_input_buffer()
            self.ser.reset_output_buffer()

当数据发送到串口时,它就起作用了。唯一的问题是,在某个随机时刻,至少按一次按钮后,程序停止读取端口。

知道为什么吗?

似乎解决方案是将 sch_plus_callback 带到 init 之外并调用

self.sch_plus_button = tk.Button(self, text="S+", command=self.sch_plus_callback)

init 之外的函数

def __init__(self, *args, **kwargs):

    tk.Tk.__init__(self, *args, **kwargs)
    # all my other code

def sch_plus_callback(self):
    self.ser.reset_input_buffer()
    self.ser.reset_output_buffer()
    self.ser.write(b'\x02\x56\x81\x80\x80\x80\x80\x80\x39\x35\x04')
    logging.info("write on serial")
    self.ser.reset_input_buffer()
    self.ser.reset_output_buffer()