无法将数据从另一个 class 写入 tkinter table
Could not write data to a tkinter table from the other class
我正在尝试添加我的 GUI 并从 python 中的简单扫描仪演示应用程序获取数据。此扫描仪演示应用程序处理各种事件,如扫描事件、scanner_connected、scanner_disconnected 等
最初我在演示应用程序中调用 GUI class 来启动 GUI。
当扫描事件引发时,我获取数据并将数据传递给 Bridge class。
之后我调用一个名为 write_data 的 GUI 函数,它负责将数据打印到 table。
此 write_table 函数调用 Bridge class 以获取更新的扫描数据
#app_example.py
import myGUI
class Bridge: # a class to store the data from the scan_event
var1 = "data"
def __init__(self):
# does
nothing
def update_data(self, user_info):
global var1
var1 = user_info
def get_data(self):
global var1
return var1
# function from the APi to get the scan data
def on_scan(client: Client, event: ScanEvent) -> None:
user_name = response_text["user"]
b = Bridge()
b.update_data(user_name) # saving the scan data to a function from Bridge class
mygui = mainGUI()
mygui.write_table() # calling the GUI function to write data to a table
# function from the APi
def app_example():
handler = GatewayMessageHandler(
on_scanner_connected=on_connected,
on_scanner_disconnected=on_disconnected,
on_scan=on_scan,
on_error=on_error,
on_button_pressed=on_button_pressed_event
)
logger.info('application started, press Ctrl-C to exit')
mygui = mainGUI()
mygui.build_gui() # calling the GUI
try:
while True:
time.sleep(1000)
except KeyboardInterrupt:
gateway.stop()
# myGUI.py
class mainGUI:
def __init__(self):
# does
nothing
def build_gui(self):
window = tk.Tk()
window.title("Barcode Scanner 1.0")
frame_COMinf = tk.Frame(window)
frame_COMinf.grid(row=1, column=1)
# initating a thread to the function write_table
self.thread = Thread(target=self.write_table)
self.thread.start()
style = ttk.Style()
style.theme_use("clam")
style.element_create("Custom.Treeheading.border", "from", "default")
style.layout("Custom.Treeview.Heading", [
("Custom.Treeheading.cell", {'sticky': 'nswe'}),
("Custom.Treeheading.border", {'sticky': 'nswe', 'children': [
("Custom.Treeheading.padding", {'sticky': 'nswe', 'children': [
("Custom.Treeheading.image", {'side': 'right', 'sticky': ''}),
("Custom.Treeheading.text", {'sticky': 'we'})
]})
]}),
])
frame = tk.Frame(window)
style.theme_use("clam")
frame.grid(row=3, column=1)
self.tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5), height=20, show="headings",
style="Custom.Treeview")
self.tree.pack(side='left')
style.configure("Custom.Treeview.Heading",
background="blue", foreground="white", relief="flat")
style.map("Custom.Treeview.Heading",
relief=[('active', 'groove'), ('pressed', 'sunken')])
self.tree.heading(1, text="Ser.No")
self.tree.heading(2, text="user")
self.tree.column(1, width=50, anchor='center')
self.tree.column(2, width=100, anchor='center')
self.scroll = tk.Scrollbar(frame, orient="vertical", command=self.tree.yview)
self.scroll.pack(side='right', fill=tk.Y)
self.tree.configure(yscrollcommand=self.scroll.set)
window.mainloop()
def write_table(self):
# this function calls the Bridge class and get the scan data
global serNo
bridge = Bridge()
user_data = bridge.get_data()
data = [[serNo, user_data]]
for val in data:
self.tree.insert('', 'end', values=(val[0], val[1]), tags=('gr',))
serNo += 1
self.tree.tag_configure('gr', background='green')
我得到的错误是
self.tree.insert('', 'end', values = (val[0], val[1]), tags=('gr',))
AttributeError: 'mainGUI' object has no attribute 'tree'
我对使用 python 的面向对象编程了解不多。有人可以帮忙写这个 table 的数据吗?
write_data 函数没有缩进并且不是 class mainGUI 的方法。 (已修复)
您尝试在 self.tree 变量初始化之前访问它。
您拨打self.tree的线路:
self.thread = Thread(target=self.write_table)
你正在进一步初始化它:
self.tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5), height=20, show="headings",
style="Custom.Treeview")
__init__() 中的默认 self.tree 会对您有所帮助。
如果你不能在 class 的 init 方法中设置它,那么也许这样的事情可以帮助:
for val in data:
try:
self.tree.insert('', 'end', values=(val[0], val[1]), tags=('gr',))
except AttributeError: # And do the initialization here. Pretty ugly though.
self.tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5), height=20, show="headings", style="Custom.Treeview")
# ... do all other stuff with the Treeview widget.
# ...
# do as normal
但我不知道您首先需要在何处进行初始化。这将是您初始化它所需的绝对最新版本。
在创建 self.tree
之前,您在 build_gui()
中启动了一个到 运行 write_data()
的线程:
class mainGUI:
def __init__(self):
# does nothing
pass
def build_gui(self):
window = tk.Tk()
window.title("Barcode Scanner 1.0")
frame_COMinf = tk.Frame(window)
frame_COMinf.grid(row=1, column=1)
# initating a thread to the function write_table
self.thread = Thread(target=self.write_table)
self.thread.start()
### the above code will execute `write_table()` before `self.tree` is created
...
frame = tk.Frame(window)
style.theme_use("clam")
frame.grid(row=3, column=1)
self.tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5), height=20, show="headings",
style="Custom.Treeview")
self.tree.pack(side='left')
...
window.mainloop()
所以最好在 window.mainloop()
:
之前创建并启动线程
class mainGUI:
...
def build_gui(self):
window = tk.Tk()
window.title("Barcode Scanner 1.0")
frame_COMinf = tk.Frame(window)
frame_COMinf.grid(row=1, column=1)
...
frame = tk.Frame(window)
style.theme_use("clam")
frame.grid(row=3, column=1)
self.tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5), height=20, show="headings",
style="Custom.Treeview")
self.tree.pack(side='left')
...
# initating a thread to the function write_table
self.thread = Thread(target=self.write_table)
self.thread.start()
window.mainloop()
另一个可疑原因:
# function from the APi to get the scan data
def on_scan(client: Client, event: ScanEvent) -> None:
user_name = response_text["user"]
b = Bridge()
b.update_data(user_name) # saving the scan data to a function from Bridge class
mygui = mainGUI()
### as mygui.build_gui() is not called
### below line will raise the error
mygui.write_table() # calling the GUI function to write data to a table
创建 class 单例解决了这个问题。
class mainGUI:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(mainGUI, cls).__new__(
cls, *args, **kwargs)
return cls._instance
def __init__(self):
self.check = False
def build_gui(self):
window = tk.Tk()
global x,y
x = window.winfo_x()
y = window.winfo_y()
#rest of the code
我正在尝试添加我的 GUI 并从 python 中的简单扫描仪演示应用程序获取数据。此扫描仪演示应用程序处理各种事件,如扫描事件、scanner_connected、scanner_disconnected 等
最初我在演示应用程序中调用 GUI class 来启动 GUI。 当扫描事件引发时,我获取数据并将数据传递给 Bridge class。 之后我调用一个名为 write_data 的 GUI 函数,它负责将数据打印到 table。 此 write_table 函数调用 Bridge class 以获取更新的扫描数据
#app_example.py
import myGUI
class Bridge: # a class to store the data from the scan_event
var1 = "data"
def __init__(self):
# does
nothing
def update_data(self, user_info):
global var1
var1 = user_info
def get_data(self):
global var1
return var1
# function from the APi to get the scan data
def on_scan(client: Client, event: ScanEvent) -> None:
user_name = response_text["user"]
b = Bridge()
b.update_data(user_name) # saving the scan data to a function from Bridge class
mygui = mainGUI()
mygui.write_table() # calling the GUI function to write data to a table
# function from the APi
def app_example():
handler = GatewayMessageHandler(
on_scanner_connected=on_connected,
on_scanner_disconnected=on_disconnected,
on_scan=on_scan,
on_error=on_error,
on_button_pressed=on_button_pressed_event
)
logger.info('application started, press Ctrl-C to exit')
mygui = mainGUI()
mygui.build_gui() # calling the GUI
try:
while True:
time.sleep(1000)
except KeyboardInterrupt:
gateway.stop()
# myGUI.py
class mainGUI:
def __init__(self):
# does
nothing
def build_gui(self):
window = tk.Tk()
window.title("Barcode Scanner 1.0")
frame_COMinf = tk.Frame(window)
frame_COMinf.grid(row=1, column=1)
# initating a thread to the function write_table
self.thread = Thread(target=self.write_table)
self.thread.start()
style = ttk.Style()
style.theme_use("clam")
style.element_create("Custom.Treeheading.border", "from", "default")
style.layout("Custom.Treeview.Heading", [
("Custom.Treeheading.cell", {'sticky': 'nswe'}),
("Custom.Treeheading.border", {'sticky': 'nswe', 'children': [
("Custom.Treeheading.padding", {'sticky': 'nswe', 'children': [
("Custom.Treeheading.image", {'side': 'right', 'sticky': ''}),
("Custom.Treeheading.text", {'sticky': 'we'})
]})
]}),
])
frame = tk.Frame(window)
style.theme_use("clam")
frame.grid(row=3, column=1)
self.tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5), height=20, show="headings",
style="Custom.Treeview")
self.tree.pack(side='left')
style.configure("Custom.Treeview.Heading",
background="blue", foreground="white", relief="flat")
style.map("Custom.Treeview.Heading",
relief=[('active', 'groove'), ('pressed', 'sunken')])
self.tree.heading(1, text="Ser.No")
self.tree.heading(2, text="user")
self.tree.column(1, width=50, anchor='center')
self.tree.column(2, width=100, anchor='center')
self.scroll = tk.Scrollbar(frame, orient="vertical", command=self.tree.yview)
self.scroll.pack(side='right', fill=tk.Y)
self.tree.configure(yscrollcommand=self.scroll.set)
window.mainloop()
def write_table(self):
# this function calls the Bridge class and get the scan data
global serNo
bridge = Bridge()
user_data = bridge.get_data()
data = [[serNo, user_data]]
for val in data:
self.tree.insert('', 'end', values=(val[0], val[1]), tags=('gr',))
serNo += 1
self.tree.tag_configure('gr', background='green')
我得到的错误是
self.tree.insert('', 'end', values = (val[0], val[1]), tags=('gr',))
AttributeError: 'mainGUI' object has no attribute 'tree'
我对使用 python 的面向对象编程了解不多。有人可以帮忙写这个 table 的数据吗?
write_data 函数没有缩进并且不是 class mainGUI 的方法。 (已修复)
您尝试在 self.tree 变量初始化之前访问它。
您拨打self.tree的线路:
self.thread = Thread(target=self.write_table)
你正在进一步初始化它:
self.tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5), height=20, show="headings",
style="Custom.Treeview")
__init__() 中的默认 self.tree 会对您有所帮助。
如果你不能在 class 的 init 方法中设置它,那么也许这样的事情可以帮助:
for val in data:
try:
self.tree.insert('', 'end', values=(val[0], val[1]), tags=('gr',))
except AttributeError: # And do the initialization here. Pretty ugly though.
self.tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5), height=20, show="headings", style="Custom.Treeview")
# ... do all other stuff with the Treeview widget.
# ...
# do as normal
但我不知道您首先需要在何处进行初始化。这将是您初始化它所需的绝对最新版本。
在创建 self.tree
之前,您在 build_gui()
中启动了一个到 运行 write_data()
的线程:
class mainGUI:
def __init__(self):
# does nothing
pass
def build_gui(self):
window = tk.Tk()
window.title("Barcode Scanner 1.0")
frame_COMinf = tk.Frame(window)
frame_COMinf.grid(row=1, column=1)
# initating a thread to the function write_table
self.thread = Thread(target=self.write_table)
self.thread.start()
### the above code will execute `write_table()` before `self.tree` is created
...
frame = tk.Frame(window)
style.theme_use("clam")
frame.grid(row=3, column=1)
self.tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5), height=20, show="headings",
style="Custom.Treeview")
self.tree.pack(side='left')
...
window.mainloop()
所以最好在 window.mainloop()
:
class mainGUI:
...
def build_gui(self):
window = tk.Tk()
window.title("Barcode Scanner 1.0")
frame_COMinf = tk.Frame(window)
frame_COMinf.grid(row=1, column=1)
...
frame = tk.Frame(window)
style.theme_use("clam")
frame.grid(row=3, column=1)
self.tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5), height=20, show="headings",
style="Custom.Treeview")
self.tree.pack(side='left')
...
# initating a thread to the function write_table
self.thread = Thread(target=self.write_table)
self.thread.start()
window.mainloop()
另一个可疑原因:
# function from the APi to get the scan data
def on_scan(client: Client, event: ScanEvent) -> None:
user_name = response_text["user"]
b = Bridge()
b.update_data(user_name) # saving the scan data to a function from Bridge class
mygui = mainGUI()
### as mygui.build_gui() is not called
### below line will raise the error
mygui.write_table() # calling the GUI function to write data to a table
创建 class 单例解决了这个问题。
class mainGUI:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(mainGUI, cls).__new__(
cls, *args, **kwargs)
return cls._instance
def __init__(self):
self.check = False
def build_gui(self):
window = tk.Tk()
global x,y
x = window.winfo_x()
y = window.winfo_y()
#rest of the code