首先,我不得不说我不是Python的专家。我从例子中收集到的大部分代码。从tkinter小部件中启动线程
我做的研究公平一点,并一直没能找到一个代码配置就是喜欢什么,我试图做的:从自定义窗口小部件类中启动一个线程。我知道tkinter有多个线程尝试与单个窗口小部件进行通信的问题,但我没有在这里看到这种情况。
我想这样做的原因是,每个插件可以启动/停止和更新它自己。通过这种方式,我可以在同一根窗口内查看来自多个来源的数据,并且可以随意添加/删除每个来源。我知道我可以用不同的方式进行编码(全部在一个班级中),但我想用这种方式尝试。我认为这会让事情变得更清洁。在这个
我的思维过程如下:
- 创建一个可重复使用的自定义部件类。
- 能够将多个小部件添加到根窗口(并且能够将其删除)
- 每个小部件都将获取数据并独立于其他部件更新数据。
- 使用线程,以便每个小部件都将在后台执行所需的操作。这样所有的小部件将同时更新。
我的代码示例显示了什么,我试图完成的基本知识。在完成的程序中,每个小部件将有一个文本框定义在哪里获取数据。
此测试代码在WindowsXP中使用Python3可以正常工作。每个小部件都可以添加和删除,并将独立于其他部件进行更新。
当我在Fedora20中使用Python3运行相同的代码时,按下开始按钮时会崩溃。唯一的例外是:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.3/threading.py", line 637, in _bootstrap_inner
self.run()
File "/usr/lib/python3.3/threading.py", line 594, in run
self._target(*self._args, **self._kwargs)
File "dummy.py", line 44, in updlabel
self.label.config(text=number)
File "/usr/lib/python3.3/tkinter/__init__.py", line 1263, in configure
return self._configure('configure', cnf, kw)
File "/usr/lib/python3.3/tkinter/__init__.py", line 1254, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: None
所以,最后,我有2个问题:
- 为什么不是在Linux下工作,而它在WindowsXP呢?
- 我的方法是否有效?如果是,我的代码在哪里?
代码示例:
from threading import Thread
import tkinter as tk
import numpy as np
import time
class Widget(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.running = False
self.abort = True
labelfont = ('times', 20, 'bold')
self.label = tk.Label(self, text="---", font=labelfont)
self.startb = tk.Button(self, text="START", command=lambda: self.sbpressed())
self.remove = tk.Button(self, text="-", command=lambda: self.rbpressed())
self.startb.grid(row=0, column=0)
self.label.grid(row=0, column=1)
self.remove.grid(row=0, column=2)
def rbpressed(self):
self.abort = True
while self.running:
self.update()
self.destroy()
def sbpressed(self):
if self.running:
self.abort = True
self.update()
else:
self.startb["text"] = "ABORT"
self.running = True
self.abort = False
self.update()
self.t = Thread(target=self.updlabel, args=())
self.t.start()
def updlabel(self):
while self.abort == False:
number = str(np.random.random_integers(100))
self.label.config(text=number)
time.sleep(1)
self.startb["text"] = "START"
self.running = False
self.abort = False
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.pack()
self.addb = tk.Button(self, text="+", command=lambda: self.addwidget())
self.addb.pack()
Widget(self).pack()
def addwidget(self):
Widget(self).pack()
root = tk.Tk()
app = Application(master=root)
app.mainloop()
对Arch Linux,Python 3.4.2适合我工作 – matsjoyce 2015-01-15 18:02:31
你是什么意思“我可以查看来自多个来源的数据”?这些来源是什么?你的例子显示了随机的调用,你绝对不需要线程。你在轮询其他设备或端口吗? – 2015-01-15 18:41:42
其他来源我的意思是来自互联网的数据。示例代码最简单,只是为了说明我在Fedora20中遇到的异常。 – Zalpho 2015-01-15 19:02:59