我正在开发一个带有GUI的子警报系统,我遇到的问题是GUI冻结,因为我正在运行一个检查聊天的循环。
我该如何将现有的GUI和聊天代码合并到一个系统中,在这个系统中,GUI不会冻结,文本字段将根据控制台的内容进行更新。
# Import Resources #
import re
import socket
import importlib
from Tkinter import *
from modules.IRCCommands import *
recentSub= 'N/A'
# Close application #
def Close_Window():
frmMain.destroy()
# Main application #
def Start():
# List info in the shell #
terminal.insert('1.0', 'Subscriber Alert ver. 1.5 | Created & Modified by RubbixCube' + "n")
terminal.insert("end", 'Important Information:' + "n")
terminal.insert("end", 'HOST = ' + HOST + "n")
terminal.insert("end", 'PORT = ' + str(PORT) + "n")
for c in CHAN:
terminal.insert("end", 'CHAN = ' + c + "n")
terminal.insert("end", 'n' + "n")
terminal.insert("end", 'Chat:' + "n")
frmMain.update_idletasks
## Define basic Functions ##
def get_sender(msg):
result = ""
for char in msg:
if (char == "!"):
break
if (char != ":"):
result += char
return result
def get_message(msg):
result = ""
i = 3
length = len(msg)
while i < length:
result += msg[i] + " "
i += 1
result = result.lstrip(':')
return result
## End Helper Functions ##
def parse_message(channel, user, msg):
if len(msg) >= 1:
msg = msg.split(' ')
frmMain.update_idletasks
con = socket.socket()
con.connect((HOST, PORT))
send_pass(con, PASS)
send_nick(con, NICK)
for c in CHAN:
join_channel(con, c)
data = ""
while True:
try:
data = data+con.recv(1024)
data_split = re.split("rn", data)
data = data_split.pop()
for line in data_split:
#print(line)
#line = str.rstrip(line)
line = str.split(line)
# Stay connected to the server #
if (len(line) >= 1):
if (line[0] == 'PING'):
send_pong(con, line[1])
if (line[1] == 'PRIVMSG'):
sender = get_sender(line[0])
message = get_message(line)
channel = line[2]
terminal.insert("end", sender + ": " + message + "n")
frmMain.update_idletasks
# Welcome new subs #
if (sender == "rubbixcube"):
def excuteCommand(con, channel, user, message, isMod, isSub):
msg = str.split(message)
if re.match('w* subscribed for w* months in a row!', message):
recentSub = msg[0]
print(recentSub)
send_message(con, channel, 'Thanks for your continued contribution %s!' % msg[0])
elif re.match('w* just subscribed!', message):
recentSub = msg[0]
print(recentSub)
send_message(con, channel, str.format('Welcome to the channel %s. Enjoy your stay!' % msg[0]))
elif (re.match('w* viewers resubscribed while you were away!', message)):
send_message(con, channel, 'Thanks for subscribing!')
excuteCommand(con, channel, sender, message, False, False)
parse_message(channel, sender, message)
except socket.error:
print("Socket died")
except socket.timeout:
print("Socket timeout")
## GUI ##
# Start loop of program
frmMain = Tk()
app = Frame(frmMain)
app.grid()
# Configure GUI
frmMain.title('Subscriber Alert ver. 2.0')
frmMain.geometry('455x357')
frmMain.resizable(0,0)
# Button
start = Button(app, text=' Start ')
start['command'] = Start
start.grid(row=0, column=0, pady=5)
close = Button(app, text=' Exit ')
close['command'] = Close_Window
close.grid(row=0, column=2, pady=5)
# Label
sub_lbl = Label(app, text='Most Recent Subscriber:')
sub_lbl.grid(row=1, column=0, columnspan=2, pady=10, padx=5)
sub_lbl2 = Label(app, text=recentSub)
sub_lbl2.grid(row=1, column=1, columnspan=3, pady=10, padx=5)
# Console
terminal = Text(app, width=56, height=17, wrap=WORD)
terminal.grid(row=3, column=0, columnspan=3)
# End loop of Program
frmMain.mainloop()
感谢
"GUI冻结问题"是Python中网络应用程序的常见问题。通常,您的网络套接字或流被称为阻塞,或者超时被设置为长,管道和io流没有完成刷新,或者GUI的reactor没有设置为与网络io reactor(mainloop)一起工作。
典型的解决方案是使用队列对网络io进行线程处理。Queues(),或者使用支持事件的网络包,因为GUI是事件驱动的。Twisted和asyncio提供事件驱动的io。或者,正如现在经常提供的那样,一些GUI包和网络包有"reactor"(主循环),可以用来与其他特定的包一起工作。Twisted有TKinter和wx的反应器。