0

Python でメソッドを使用する場合select.select()、GUI (Tkinter Entry) からの入力を使用してソケットからデータを送信する方法はありますか?

select() の入力リストは sys.stdin またはサーバーから受信したデータを受け入れますが、GUI からデータを取得して送信する方法はありますか? または、select は 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()
4

3 に答える 3

0

Select() と GUI はまったく無関係です。GUI ウィジェットからテキストを取得でき、ソケットを介してテキストを送信できます。したがって、GUI からテキストを取得し、他の文字列と同様にソケットを介して送信できます。

入力ウィジェットとテキスト ウィジェットの両方に、getテキストを取得するメソッドがあることをご存知ですか? readlineの代わりに呼び出した場合と同じように、テキストをフェッチして送信しようとしましたself.text.getか?

于 2012-04-10T23:28:47.830 に答える
0

質問が下手だったと思います。下手な言い回しにもかかわらず、答えようとした人に感謝します。私はPythonを使い始めたばかりでした。いずれにせよ、これは私が尋ねようとしていた質問に対して私のグループメンバーが見つけた答えです. 彼が自分で書いたのか、Web サイトで見つけたのかはわかりませんが、基本的には TKinterafter()呼び出しを使用しただけです。

メイン ループは次のようになります。

def cmdloop():
    (sread, swrite, sexc) = select.select( [sock], [], [], 0)
    for s in sread:
        ...
        ...
        ...
    app.after(500,cmdloop)

その 0.5 秒の中断により、テキストボックスの呼び出し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
于 2012-06-15T06:44:55.597 に答える
0

アクションをエントリ変更、標準入力またはソケットの両方にバインドする場合は、イベント使用スレッドを使用しないより簡単な方法があります。アイデアは、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()
于 2012-04-12T16:02:24.313 に答える