Gtk 和 Python:使用 set_label 和线程时出现问题

Gtk and Python: Problem using set_label and threads

我有一个线程 运行 函数 uidReader() 使用 read_uid() 读取 NFC 卡。当我从卡中获得 UID 时,我想将其写在标签中。然后,当我按下清除按钮时,我想从标签中删除 UID 和 运行 一个新线程以便能够读取新卡。问题是有时(我无法识别任何模式,它似乎是随机的)UID 卡在标签中,我无法按清除按钮更改值。

import time

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, GObject, Gdk

from rfid import Rfid

def uidReader():
    uid = rf.read_uid()
    print(uid)
    LogWin.label.set_text("uid: " + uid)

class LoginWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="Login")
        Gtk.Window.set_default_size(self, 600, 200)

        self.box = Gtk.VBox(spacing=0)
        self.add(self.box)

        self.label = Gtk.Label(label="Please, login with your university card")
        self.label.width_chars = 100

        self.button = Gtk.Button(label="Clear")
        self.button.set_margin_start(20)
        self.button.set_margin_top(20)
        self.button.set_margin_end(20)
        self.button.set_margin_bottom(20)
        self.button.connect("clicked", self.clearButton)

        self.box.add(self.label)
        self.box.add(self.button)

    def clearButton(self, button):
        self.label.set_text("Please, login with your university card")
        global uid_thread
        if uid_thread.is_alive() is False:
            uid_thread = threading.Thread(target=uidReader, daemon=True)
            uid_thread.start()


if __name__ == "__main__":

    uid = False

    rf = Rfid()
    uid_thread = threading.Thread(target=uidReader, daemon=True)
    uid_thread.start()

    LogWin = LoginWindow()
    LogWin.connect("destroy", Gtk.main_quit)
    LogWin.show_all()
    Gtk.main()

根据 https://developer.gnome.org/gdk3/stable/gdk3-Threads.html,您应该只使用线程 gtk_init() 和 gtk_main() 中调用的 GTK+ 和 GDK。

将对 GTK+ 的调用包装在 GLib.idle_add 中,因此替换

LogWin.label.set_text("uid: " + uid)

# from functools import partial
GLib.idle_add(partial(LogWin.label.set_text, "uid: " + uid))