Python 3 使用 Tkinter 的多线程
Python 3 Multi-Threading with Tkinter
我一直在编写一些代码,这些代码最终会从远程和本地(在代码本身内)源获取命令,然后执行并使用 tkinter 显示结果。
我目前遇到的问题是,当我 运行 使用线程和队列的代码出现此错误时,我尝试将 gui 代码放在线程的 for 循环下方的底部,但这有发生另一个错误。
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python34\lib\threading.py", line 921, in _bootstrap_inner
self.run()
File "C:\Python34\lib\threading.py", line 869, in run
self._target(*self._args, **self._kwargs)
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 60, in threader
t_visuals()
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 49, in t_visuals
label = Label(root, width=70, height=30,relief=RIDGE,bd=5,bg="white",textvariable=v,anchor=NW,justify= LEFT,font=("Times New Roman", 12)).grid(row=1,column=0)
File "C:\Python34\lib\tkinter\__init__.py", line 2604, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "C:\Python34\lib\tkinter\__init__.py", line 2122, in __init__
(widgetName, self._w) + extra + self._options(cnf))
RuntimeError: main thread is not in main loop
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Python34\lib\threading.py", line 921, in _bootstrap_inner
self.run()
File "C:\Python34\lib\threading.py", line 869, in run
self._target(*self._args, **self._kwargs)
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 58, in threader
t_connections()
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 43, in t_connections
sLog_update("waiting for connection...")
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 40, in sLog_update
v.set(g)
File "C:\Python34\lib\tkinter\__init__.py", line 263, in set
return self._tk.globalsetvar(self._name, value)
RuntimeError: main thread is not in main loop
这是代码:
from socket import *
import time
from tkinter import *
import threading
from queue import Queue
#server setup
HOST = ''
PORT = 24601
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
#Window Setup
HEIGHT = 720
WIDTH = 1280
root = Tk()
root.title("Server Controler")
root.geometry("1280x720")
#Variables needed
v =StringVar()
f =StringVar()
g = "" #Server update log
#locked variables
sLog_lock = threading.Lock()
#t_ means threaded
def sLog_update(self):
with sLog_lock:
global g
currentTime = str("["+time.ctime()+"] ")
g+=str(currentTime)
g+=str(self)
g+=str("\n")
v.set(g)
def t_connections():
sLog_update("waiting for connection...")
tcpCliSock, addr = tcpSerSock.accept()
avr = "connected from: " + str(addr)
sLog_update(avr)
def t_visuals():
label = Label(root, width=70, height=30,relief=RIDGE,bd=5,bg="white",textvariable=v,anchor=NW,justify= LEFT,font=("Times New Roman", 12)).grid(row=1,column=0)
entry = Entry(root, width=105,relief=RIDGE,bd=5,textvariable=f).grid(row=2,column=0)
button = Button(root,command= lambda:sLog_update(f.get()),text="send").grid(row=3,column=0)
mainloop()
def threader():
worker = q.get()
print(worker)
if worker == 1:
t_connections()
elif worker == 0:
t_visuals()
q =Queue()
for x in range(2):
t = threading.Thread(target=threader)
t.daemon = True
t.start()
for worker in range(20):
q.put(worker)
q.join()
您可以通过将所有 GUI 代码保留在主线程中来解决此问题。
我一直在编写一些代码,这些代码最终会从远程和本地(在代码本身内)源获取命令,然后执行并使用 tkinter 显示结果。
我目前遇到的问题是,当我 运行 使用线程和队列的代码出现此错误时,我尝试将 gui 代码放在线程的 for 循环下方的底部,但这有发生另一个错误。
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python34\lib\threading.py", line 921, in _bootstrap_inner
self.run()
File "C:\Python34\lib\threading.py", line 869, in run
self._target(*self._args, **self._kwargs)
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 60, in threader
t_visuals()
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 49, in t_visuals
label = Label(root, width=70, height=30,relief=RIDGE,bd=5,bg="white",textvariable=v,anchor=NW,justify= LEFT,font=("Times New Roman", 12)).grid(row=1,column=0)
File "C:\Python34\lib\tkinter\__init__.py", line 2604, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "C:\Python34\lib\tkinter\__init__.py", line 2122, in __init__
(widgetName, self._w) + extra + self._options(cnf))
RuntimeError: main thread is not in main loop
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Python34\lib\threading.py", line 921, in _bootstrap_inner
self.run()
File "C:\Python34\lib\threading.py", line 869, in run
self._target(*self._args, **self._kwargs)
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 58, in threader
t_connections()
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 43, in t_connections
sLog_update("waiting for connection...")
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 40, in sLog_update
v.set(g)
File "C:\Python34\lib\tkinter\__init__.py", line 263, in set
return self._tk.globalsetvar(self._name, value)
RuntimeError: main thread is not in main loop
这是代码:
from socket import *
import time
from tkinter import *
import threading
from queue import Queue
#server setup
HOST = ''
PORT = 24601
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
#Window Setup
HEIGHT = 720
WIDTH = 1280
root = Tk()
root.title("Server Controler")
root.geometry("1280x720")
#Variables needed
v =StringVar()
f =StringVar()
g = "" #Server update log
#locked variables
sLog_lock = threading.Lock()
#t_ means threaded
def sLog_update(self):
with sLog_lock:
global g
currentTime = str("["+time.ctime()+"] ")
g+=str(currentTime)
g+=str(self)
g+=str("\n")
v.set(g)
def t_connections():
sLog_update("waiting for connection...")
tcpCliSock, addr = tcpSerSock.accept()
avr = "connected from: " + str(addr)
sLog_update(avr)
def t_visuals():
label = Label(root, width=70, height=30,relief=RIDGE,bd=5,bg="white",textvariable=v,anchor=NW,justify= LEFT,font=("Times New Roman", 12)).grid(row=1,column=0)
entry = Entry(root, width=105,relief=RIDGE,bd=5,textvariable=f).grid(row=2,column=0)
button = Button(root,command= lambda:sLog_update(f.get()),text="send").grid(row=3,column=0)
mainloop()
def threader():
worker = q.get()
print(worker)
if worker == 1:
t_connections()
elif worker == 0:
t_visuals()
q =Queue()
for x in range(2):
t = threading.Thread(target=threader)
t.daemon = True
t.start()
for worker in range(20):
q.put(worker)
q.join()
您可以通过将所有 GUI 代码保留在主线程中来解决此问题。