简体   繁体   English

使用 python websocket 客户端与 tkinter

[英]Using python websocket client with tkinter

I'm trying to make use a websocket client in python 2.7.我正在尝试在 python 2.7 中使用 websocket 客户端。 The client works fine when running with IDLE, as in the received messages are shown.客户端在使用 IDLE 运行时工作正常,如接收到的消息所示。 However trying to insert the websocket messages in a tkinter text widget is not working.但是,尝试在 tkinter 文本小部件中插入 websocket 消息无效。 Messages are still being displayed in IDLE, but the tkinter window is not being displayed at all. IDLE 中还在显示消息,但是 tkinter window 根本没有显示。

The package I'm using is called websocket-client 0.32.0 and I dowloaded it from here .我正在使用的 package 称为 websocket-client 0.32.0,我从这里下载了它。 I followed the instructions on how to make a javascript like api and somewhat adapted the code.我按照有关如何制作 javascript(如 api)的说明进行操作,并对代码进行了一些调整。

Here is my code:这是我的代码:

from Tkinter import *
from websocket import *

master = Tk()
master.wm_title("Websocket Test")
minwidth = master.winfo_screenwidth()/4*3
minheight = master.winfo_screenheight()/4*3
master.minsize(width=minwidth, height=minheight)
master.resizable(0,0)

text = Text(master)
text.pack(expand=True,fill=BOTH)

def on_message(ws, message):
   text.insert(END, message+"\n")
   print "Received: "+message
   return

def on_error(ws, error):
   text.insert(END, error+"\n")
   print error
   return

def on_close(ws):
   text.insert(END, "### closed ###\n")
   print "### closed ###"
   return

def on_open(ws):
   ws.send("hi")
   ws.send("test")
   return

enableTrace(True)
ws = WebSocketApp("ws://echo.websocket.org/", on_message = on_message, on_error = on_error, on_close = on_close)
ws.on_open = on_open

ws.run_forever()

master.mainloop()

Here is what is shown in IDLE if that is also helpful:以下是 IDLE 中显示的内容,如果这也有帮助的话:

--- request header ---
GET / HTTP/1.1

Upgrade: websocket

Connection: Upgrade

Host: echo.websocket.org

Origin: http://echo.websocket.org

Sec-WebSocket-Key: tXWAVVlaRoq2S4+p/z12gg==

Sec-WebSocket-Version: 13




-----------------------
--- response header ---
HTTP/1.1 101 Web Socket Protocol Handshake
Connection: Upgrade
Date: Fri, 21 Aug 2015 05:16:54 GMT
Sec-WebSocket-Accept: LH12LFLFaek6HgCnGIugF0sg9lA=
Server: Kaazing Gateway
Upgrade: websocket
-----------------------
send: '\x81\x82{b\x97\xfc\x13\x0b'
send: '\x81\x84\xa5J\xecf\xd1/\x9f\x12'
Received: hi
Received: test

I've been stuck on this for a while and I cannot find any solutions to this sort of problem.我已经坚持了一段时间,但找不到解决此类问题的任何方法。 Any help is appreciated as I'm a newbie.任何帮助表示赞赏,因为我是新手。

Well, I do not use websocket, but the issue seems to be that, when you do -好吧,我不使用 websocket,但问题似乎是,当你使用 -

ws.run_forever()

The application goes into an infinite loop, so the control never reaches master.mainloop() , which is required for the tkinter to show up, and which is again another infinite loop, which is only exited when you close the gui.应用程序进入无限循环,因此控件永远不会到达master.mainloop() ,这是 tkinter 显示所必需的,这又是另一个无限循环,只有在关闭 gui 时才会退出。

What you really want is to run two infinite loop simultaneously, which would require you to run them in two different threads, currently both of them are defined on the same thread, so one would only run after the other has exited.你真正想要的是同时运行两个无限循环,这需要你在两个不同的线程中运行它们,目前它们都定义在同一个线程上,所以一个只会在另一个退出后运行。

A quick fix would be to use master.after() with a certain delay and giving a function, and then in the function start a new thread for a function in which websocket connects to the server.一个快速的解决方法是使用master.after()并有一定的延迟并给出 function,然后在 function 中为 function 启动一个新线程,其中 websocket 连接到服务器。 so that both the infinite loops are in different threads.这样两个无限循环都在不同的线程中。

But the best fix would be to use a button, lets call it 'Connect' .但最好的解决办法是使用一个按钮,我们称之为'Connect' Then the callback for that button would be a function like on_connect() below, which starts the function to connect -那么该按钮的回调将是一个 function,就像下面的on_connect()一样,它启动 function 进行连接 -

def connect_to_socket():
    enableTrace(True)
    ws = WebSocketApp("ws://echo.websocket.org/", on_message = on_message, on_error = on_error, on_close = on_close)
    ws.on_open = on_open

    ws.run_forever()

def on_connect():
    import threading
    t = threading.Thread(target=connect_to_socket)
    t.start()

The button would be something like -该按钮类似于 -

button = Button(master, text="Connect", command=on_connect)

Then you can place the button as you wish.然后您可以根据需要放置按钮。

Thanks to Anand's response, I was able to figure out the problem.多亏了阿南德的回应,我才能够找出问题所在。 The working and updated code is posted below:工作和更新的代码发布在下面:

from Tkinter import *
from websocket import *
from threading import *

master = Tk()
master.wm_title("Team Black Client")
master.withdraw()
minwidth = master.winfo_screenwidth()/4*3
minheight = master.winfo_screenheight()/4*3
master.minsize(width=minwidth, height=minheight)
x = (master.winfo_screenwidth() - minwidth)/2
y = (master.winfo_screenheight() - minheight)/2
master.geometry("+"+str(x)+"+"+str(y))
master.deiconify()
master.resizable(0,0)

text = Text(master)
text.pack(expand=True,fill=BOTH)

def on_message(ws, message):
   text.insert(END, message+"\n")
   print "Received: "+message
   return

def on_error(ws, error):
   text.insert(END, error+"\n")
   print error
   return

def on_close(ws):
   text.insert(END, "### closed ###\n")
   print "### closed ###"
   return

def on_open(ws):
   ws.send("hi")
   ws.send("test")
   return

def connection():
   enableTrace(True)
   ws = WebSocketApp("ws://echo.websocket.org/", on_message = on_message, on_error = on_error, on_close = on_close)
   ws.on_open = on_open

   ws.run_forever()
   return

t = Thread(target=connection)
t.start()

master.mainloop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM