在Python中使用select.select()
方法时,有没有办法使用GUI输入(Tkinter Entry)从套接字发送数据?
select()的输入列表接受来自服务器的sys.stdin或接收的数据,但是无论如何从GUI获取数据并将其发送出去?或者选择不适用于GUI?
我已经进行了广泛的搜索,但是如果你有一个指向另一个帖子的链接,我也会很感激。
import socket, select, threading, Queue, cPickle
from Tkinter import *
from Message import *
class GUI(Frame):
def __init__(self, host="localhost",port=5678, root="Tk()"):
Frame.__init__(self,root)
self.nickname = raw_input("What is your screen name? ")
self.inqueue = Queue.Queue()
self.outqueue = Queue.Queue()
self.root = root
self.text = Text(self,height=10,width=40)
self.scroll=Scrollbar(self)
self.text.configure(yscrollcommand=self.scroll.set)
self.scroll.grid(row=0, column=1, sticky=N+S)
self.scroll.config(command=self.text.yview)
self.text.grid(row=0,column=0)
self.entry = Entry(self)
self.entry.grid(row=1,column=0)
self.pack()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((host, port))
self.sock.send(self.nickname)
self.thread1=threading.Thread(target=self.cmdloop)
self.thread1.start()
self.entry.bind("<Return>",self.enter)
self.call()
def enter(self,event):
msg = Message(self.nickname,0,self.entry.get())
self.entry.delete(0, END)
msg = cPickle.dumps(msg)
self.inqueue.put(msg)
self.sock.send(msg)
def call(self):
self.processData()
self.after(100,self.call)
def cmdloop(self):
while 1:
sys.stdout.flush()
# Wait for input from stdin & socket
inputs, outputs, excepts = select.select([0,self.sock],[],[])
for i in inputs:
if i == 0:
data = sys.stdin.readline()
msg = Message(self.nickname,0,data)
msg = cPickle.dumps(msg)
self.inqueue.put(msg)
self.sock.send(msg)
elif i == self.sock:
data = self.sock.recv(1024)
self.inqueue.put(data)
def processData(self):
while self.inqueue.qsize():
try:
msg = self.inqueue.get(0)
msg = cPickle.loads(msg)
self.text.insert(END, msg.getusr()+": "+msg.getmsg())
self.text.yview(END)
except Queue.Empty:
pass
if __name__ == "__main__":
root = Tk()
root.title("textarea")
client = GUI(sys.argv[1],int(sys.argv[2]),root)
root.mainloop()
答案 0 :(得分:0)
选择()和GUI完全不相关。您可以从GUI小部件中获取文本,并且可以通过套接字发送文本,因此您可以从GUI获取文本并通过套接字发送它,就像任何其他字符串一样。
您是否知道条目小部件和文本小部件都有get
方法来获取文本?您是否尝试过提取文本,然后像调用readline
而不是self.text.get
一样发送文本?
答案 1 :(得分:0)
如果要将操作绑定到条目修改,stdin或套接字,则有一种更简单的方法,即事件不使用线程。我们的想法是通过Tkinter将操作绑定到文件处理程序,而不是尝试为您自己的主循环提供选择和检索Tkinter事件。
您可以依靠Tkinter mainloop通过createfilehandler(fd,mask,callback)
将函数绑定到文件描述符事件,例如root.createfilehandler(sys.stdin,READABLE,callback)
。
这是一个演示应用
from Tkinter import *
import socket
master = Tk()
entry = Entry(master)
entry.pack()
def process(data):
print "processing: {0}".format(data)
def stdin_callback(fd, mask):
print "stdin"
data = sys.stdin.readline()
process(data[:-1])
def socket_callback(fd, mask):
print "socket"
try:
data= sock.recv(1024)
if data:
process (data)
else:
close_socket ()
except socket.error as ex:
close_socket ()
def close_socket():
#closing socket without removing filehandler may hurt
sock.close()
master.deletefilehandler(fileno)
def entry_callback(event):
print "entry"
process(event.widget.get())
entry.bind("<Return>", entry_callback)
master.createfilehandler(sys.stdin,READABLE, stdin_callback)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 5678))
fileno = sock.fileno()
master.createfilehandler(fileno, READABLE, socket_callback)
master.mainloop()
答案 2 :(得分:0)
我想我问的问题很糟糕,感谢那些尽管我的措词不好而试图回答的人。我刚开始使用Python。无论哪种方式,这是我的小组成员找到的问题的答案,我正在尝试询问。我不知道他是自己写的还是在网站上发现的,但它基本上只是使用了TKinter after()
电话。
我们的主循环如下:
def cmdloop():
(sread, swrite, sexc) = select.select( [sock], [], [], 0)
for s in sread:
...
...
...
app.after(500,cmdloop)
半秒休息允许文本框调用inputBox.bind('<Return>', sendMsg)
(以及等待在套接字中发送的消息)正常工作。 sendMsg()
然后只需拨打sock.send()
。
def sendMsg(event=''):
message = inputBox.get()
message += "\n"
msg = Message(nickname,0,message,None) #Custom Class
sock.send(pickle.dumps(msg))
inputBox.delete(0,END)
return