2015-08-21 69 views
2

我想在python 2.7中使用websocket客戶端。在使用IDLE運行時,客戶端工作正常,因爲在收到的消息中顯示。然而,嘗試在tkinter文本小部件中插入websocket消息不起作用。消息仍在IDLE中顯示,但tkinter窗口根本沒有顯示。使用python websocket客戶端tkinter

我使用的軟件包叫做websocket-client 0.32.0,我將它從here下載。我遵循關於如何製作像api這樣的javascript並稍微修改代碼的說明。

這裏是我的代碼:

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() 

這裏是在空閒狀態顯示,如果這也是有幫助的:

--- 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 

我一直停留在這一段時間,我無法找到任何解決這類問題的方法。任何幫助表示讚賞,因爲我是一個新手。

+0

我猜tkinter窗口甚至不顯示? –

+0

不是窗口不顯示。我非常想要收到的東西被添加到文本小部件。 –

+0

你可以使用[這個答案]中顯示的'errorwindow'模塊(http://stackoverflow.com/questions/18089506/writing-to-easygui-textbox-as-function-is-running-python/18091356#18091356)我的,只是讓你的websocket處理函數'print()'到另一個窗口。這可以避免在每個文件中調用'text.insert()'。實際上,你需要在兩個無限循環之間進行多任務處理 - wbsocket和tkinter。 – martineau

回答

0

好吧,我不使用的WebSocket,但問題似乎是,當你做 -

ws.run_forever() 

應用程序進入一個無限循環,所以控制從未達到master.mainloop(),這是需要tkinter將出現,而這又是另一個無限循環,只有在關閉gui時纔會退出。

你真正想要的是同時運行兩個無限循環,這將需要你在兩個不同的線程中運行它們,目前它們都是在同一個線程中定義的,所以一個只能在另一個線程退出後運行。

一個快速解決方法是使用master.after()以一定的延遲並給出一個函數,然後在該函數中爲websocket連接到服務器的函數啓動一個新線程。因此無限循環都在不同的線程中。

但最好的解決辦法是使用一個按鈕,讓我們叫它'Connect'。然後,該按鈕的回調會像下面on_connect()的功能,這將啓動函數連接 -

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() 

按鈕會是這樣的 -

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

然後你就可以將按鈕的同時,希望。

0

感謝Anand的迴應,我能夠找出問題所在。工作和更新代碼張貼如下:

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()