【问题标题】:Tkinter threading for socket receiving data用于套接字接收数据的 Tkinter 线程
【发布时间】:2018-08-11 20:33:39
【问题描述】:

我正在为我的网络课程开发一个项目,该项目是一个客户端,用于与托管我们教授编写的基于文本的游戏的服务器进行交互。

我几乎把所有事情都弄清楚了,但我有一个主要问题,我不太了解 python,并且很难实现线程以连续接收来自服务器的数据。

RuntimeError: 主线程不在主循环中

这是我得到的错误,我相信这是因为 tkinter 必须始终在主线程中,并且它与我的接收函数冲突。我已经看到队列可能是解决这个问题的方法,但我无法理解如何在我的代码中实现这一点,任何帮助都将非常感谢。

from tkinter import *
import tkinter.simpledialog
from sys import exit
from struct import *
from socket import *
import threading
import tkinter.scrolledtext as tkst

skt = socket(AF_INET, SOCK_STREAM)
skt.connect(("domainname.com", 5191))
root = Tk()




def main():
    thread = threading.Thread(target = recieve)

    thread.start()



    thread.join()
    root.mainloop()

def start_func():
    m = 6

def create_func():
    m = 10

def change_func():
    m = 2
    print(m)

def fight_func():
    m = 3
    print(m)

def pvp_func():
    m = 4
    print(m)

def loot_func():
    m = 5
    skt.send(m)
    print(m)

def leave_func():
    m = 12
    print(m)

def submit_value():
    global userEntry
    length = len(userEntry.get())
    e1.delete(0, END)

class TestClient(Frame):
    def __init__(self, master):
        global userEntry
        Frame.__init__(self, master)
        self.pack()

        for n in range(3):
            self.grid_rowconfigure(n, weight=1)

        for n in range(8):
            self.grid_columnconfigure(n, weight=1)

        self.Messg_text = tkst.ScrolledText(self,wrap = WORD, width=80)
        self.Messg_text.grid(row=0, column=0, columnspan=8)

        la1 = Label(self, text="Value entry:")
        la1.grid(row=1, column=0)

        userEntry = StringVar()
        global e1
        e1 = Entry(self, width=40, textvariable=userEntry)
        e1.grid(row=1, column=1, columnspan=6)

        e2 = Button(self, text="Enter", command=submit_value)
        e1.delete(0, END)
        e2.grid(row=1, column=5, columnspan=10)


        b1 = Button(self, text="Start", width=10,padx=10,pady=10, command=start_func)
        b1.grid(row=2, column=0)

        b0 = Button(self, text="Create Character", width=10,padx=10,pady=10, command=create_func)
        b0.grid(row=2, column=1)

        b2 = Button(self, text="Change Room", width=10,padx=10,pady=10, command=change_func)
        b2.grid(row=2, column=3)

        b3 = Button(self, text="FIGHT", width=10,padx=10,pady=10, command=fight_func)
        b3.grid(row=2, column=4)

        b4 = Button(self, text="PvP FIGHT", width=10,padx=10,pady=10, command=pvp_func)
        b4.grid(row=2, column=5)

        b5 = Button(self, text="Loot", width=10,padx=10,pady=10, command=loot_func)
        b5.grid(row=2, column=6)

        b6 = Button(self, text="Leave", width=10,padx=10,pady=10, command=leave_func)
        b6.grid(row=2, column=7)

tw = TestClient(root)
def recieve():
    while(True):
        mesg_type = skt.recv(1)
        if(mesg_type == b'\x01'):
            msg_Len = skt.recv(2)
            msg_int_Len = struct.unpack('h',msg_Len)
            Recip_Name = skt.recv(32)
            sender_Name = skt.recv(32)
            mesg = skt.recv(msg_int_Len)
            PostMessage(Recip_Name,sender_Name,mesg)

        elif(mesg_type == b'\x0b'):
            init_Points = skt.recv(2)
            statLim = skt.recv(2)
            descriptLen = skt.recv(2)
            descriptLen = unpack('h',descriptLen)
            gameDiscript = skt.recv(descriptLen[0])
            print(gameDiscript.decode("utf-8"))
            Post11Message(str(gameDiscript)[0:-2])


def PostMessage(name, senderName, Message):
    tw.Messg_text.insert(INSERT,Message)
def Post11Message(gameDiscript):
    tw.Messg_text.insert(INSERT,gameDiscript)


main()

【问题讨论】:

    标签: multithreading python-3.x sockets networking tkinter


    【解决方案1】:

    我很确定您遇到问题的原因是因为thread.join 等到线程完成后再执行下一步操作。所以,在你的情况下,你从来没有真正打电话给root.mainloop()。解决方案就是在 main 中取出 thread.join 行。

    此外,在您的情况下,队列是必要的,因为您无法在另一个线程中更改 Tkinter 小部件。

    无需过多编辑,您的代码将如下所示。

    from tkinter import *
    import tkinter.simpledialog
    from sys import exit
    from struct import *
    from socket import *
    import Queue
    import threading
    import tkinter.scrolledtext as tkst
    
    skt = socket(AF_INET, SOCK_STREAM)
    skt.connect(("domainname.com", 5191))
    root = Tk()
    
    def main():
        thread = threading.Thread(target = recieve)
    
        thread.start()
    
        root.mainloop()
    
    def start_func():
        m = 6
    
    def create_func():
        m = 10
    
    def change_func():
        m = 2
        print(m)
    
    def fight_func():
        m = 3
        print(m)
    
    def pvp_func():
        m = 4
        print(m)
    
    def loot_func():
        m = 5
        skt.send(m)
        print(m)
    
    def leave_func():
        m = 12
        print(m)
    
    def submit_value():
        global userEntry
        length = len(userEntry.get())
        e1.delete(0, END)
    
    class TestClient(Frame):
        def __init__(self, master):
            global userEntry
            Frame.__init__(self, master)
            self.pack()
    
            for n in range(3):
                self.grid_rowconfigure(n, weight=1)
    
            for n in range(8):
                self.grid_columnconfigure(n, weight=1)
    
            self.Messg_text = tkst.ScrolledText(self,wrap = WORD, width=80)
            self.Messg_text.grid(row=0, column=0, columnspan=8)
    
            la1 = Label(self, text="Value entry:")
            la1.grid(row=1, column=0)
    
            userEntry = StringVar()
            global e1
            e1 = Entry(self, width=40, textvariable=userEntry)
            e1.grid(row=1, column=1, columnspan=6)
    
            e2 = Button(self, text="Enter", command=submit_value)
            e1.delete(0, END)
            e2.grid(row=1, column=5, columnspan=10)
    
    
            b1 = Button(self, text="Start", width=10,padx=10,pady=10, command=start_func)
            b1.grid(row=2, column=0)
    
            b0 = Button(self, text="Create Character", width=10,padx=10,pady=10, command=create_func)
            b0.grid(row=2, column=1)
    
            b2 = Button(self, text="Change Room", width=10,padx=10,pady=10, command=change_func)
            b2.grid(row=2, column=3)
    
            b3 = Button(self, text="FIGHT", width=10,padx=10,pady=10, command=fight_func)
            b3.grid(row=2, column=4)
    
            b4 = Button(self, text="PvP FIGHT", width=10,padx=10,pady=10, command=pvp_func)
            b4.grid(row=2, column=5)
    
            b5 = Button(self, text="Loot", width=10,padx=10,pady=10, command=loot_func)
            b5.grid(row=2, column=6)
    
            b6 = Button(self, text="Leave", width=10,padx=10,pady=10, command=leave_func)
            b6.grid(row=2, column=7)
    
            #Data Queue
            self.queue = Queue.Queue()
            self.queue_check()
        def queue_check(self):
            try:
                #Inserts Data
                text = self.queue.get_nowait(0)
                self.Messg_text.insert(INSERT, text)
            #If Nothing In Queue
            except Queue.Empty:
                #Repeats Itself After 100 ms
                self.after(100, self.queue_check)
    
    tw = TestClient(root)
    def recieve():
        while(True):
            mesg_type = skt.recv(1)
            if(mesg_type == b'\x01'):
                msg_Len = skt.recv(2)
                msg_int_Len = struct.unpack('h',msg_Len)
                Recip_Name = skt.recv(32)
                sender_Name = skt.recv(32)
                mesg = skt.recv(msg_int_Len)
                PostMessage(Recip_Name,sender_Name,mesg)
    
            elif(mesg_type == b'\x0b'):
                init_Points = skt.recv(2)
                statLim = skt.recv(2)
                descriptLen = skt.recv(2)
                descriptLen = unpack('h',descriptLen)
                gameDiscript = skt.recv(descriptLen[0])
                print(gameDiscript.decode("utf-8"))
                Post11Message(str(gameDiscript)[0:-2])
    
    
    def PostMessage(name, senderName, Message):
        #Adds Message To Queue
        tw.queue.put(Message)
    def Post11Message(gameDiscript):
        #Adds gameDiscript to Queue
        tw.queue.put(gameDiscript)
    
    
    main()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-19
      • 2013-09-08
      • 2021-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多