2014-02-20 182 views
1

製作聊天服務器的客戶端部分。線程正常工作,就像接收數據一樣,但是我得到一個屬性錯誤,試圖將數據從「receive_data」函數放入chatlog。我哪裏錯了?Python - 屬性錯誤

from tkinter import * 
import socket 
import threading 
import time 

host = socket.gethostname() 
port = 8000 

s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

class Application(Frame): 
    def __init__(self, master=None): 
     #Create master frame 
     Frame.__init__(self,master) 
     self.grid() 
     self.master.title("Test 1") 
     self.conn=False #State of connection to server 


     #Configure main frame 
     for r in range (4): 
      self.master.rowconfigure(r, weight=1) 
     for c in range (2): 
      self.master.columnconfigure(c) 

     #Create sub frames 
     TopFrame=Frame(master, bg="red") 
     TopFrame.grid(row=0, column=0, rowspan=3) 
     BottomFrame=Frame(master, bg="blue") 
     BottomFrame.grid(row=4, column=0) 
     SideFrame=Frame(master, bg="green") 
     SideFrame.grid(column=1, row=0, rowspan=4) 

     #Create Chat log 
     self.chatlog=Text(TopFrame) 
     self.chatlog.pack(padx=5, pady=5) 

     #Create entry field 
     self.e1=StringVar() 
     self.e1=Entry(BottomFrame) 
     self.e1.pack(pady=5, padx=5) 

     #Create buttons 
     b1=Button(SideFrame, text="Connect", command=self.connect) 
     b1.grid(row=0, column=0, padx=5, pady=5) 
     b2=Button(SideFrame, text="Disconnect", command=self.disconnect) 
     b2.grid(row=1, column=0, padx=5, pady=5) 
     b3=Button(SideFrame, text="Send", command=self.sendmessage) 
     b3.grid(row=2, column=0, padx=5, pady=5) 

    def connect(self): #Connect to server 
     self.chatlog['state'] = NORMAL 
     self.chatlog.insert(END, ("===ATTEMPTING TO CONNECT TO SERVER\n")) 
     self.chatlog['state'] = DISABLED 
     self.chatlog.yview(END) 
     try: 
      s.connect((host,port)) 
      self.chatlog['state'] = NORMAL 
      self.chatlog.insert(END, ("===CONNECTED TO SERVER\n")) 
      self.chatlog['state'] = DISABLED 
      self.chatlog.yview(END) 
      self.conn=True 
      print("Connected") #Connection successful 
      t1=RecvThreadClass() 
      t1.start() 

     except ConnectionRefusedError: #Can't find server 
      self.chatlog['state'] = NORMAL 
      self.chatlog.insert(END, ("===SERVER COULD NOT BE FOUND\n" + "===PLEASE MAKE SURE THE SERVER IS ON, AND YOU'RE CONNECTED TO THE NETWORK\n")) 
      self.chatlog['state'] = DISABLED 
      self.chatlog.yview(END) 
     except: #Other errors 
      self.chatlog['state'] = NORMAL 
      self.chatlog.insert(END, ("===THERE'S AN ERROR WITH THE PROGRAM\n" + "===PLEASE TURN IT OFF AND ON AGAIN\n")) 
      self.chatlog['state'] = DISABLED 
      self.chatlog.yview(END) 

     # When attempting to connect a second time, produces OS error: an operation was attempted on something that is not a socket 

    def disconnect(self): 
     if self.conn: #Tests to see if client is connected 
      s.close() 
      self.chatlog['state'] = NORMAL 
      self.chatlog.insert(END, ("===DISCONNECTED FROM SERVER.\n")) 
      self.chatlog['state'] = DISABLED 
      self.chatlog.yview(END) 
      self.conn=False 
     else: #Prevents attempting to disconnect when already disconnected 
      self.chatlog['state'] = NORMAL 
      self.chatlog.insert(END, ("===YOU AREN'T CURRENTLY CONNECTED.\n")) 
      self.chatlog['state'] = DISABLED 
      self.chatlog.yview(END) 


    def sendmessage(self): 
     if self.conn: #Prevents sending if not connected 
      self.msg=self.e1.get() 
      if self.msg == "": #Empty message catcher 
       self.chatlog['state'] = NORMAL 
       self.chatlog.insert(END, ("===YOU CANNOT SEND AN EMPTY MESSAGE.\n")) 
       self.chatlog['state'] = DISABLED 
       self.chatlog.yview(END) 
      else: 
       self.chatlog['state'] = NORMAL 
       self.chatlog.insert(END, ('You: ' + self.msg + '\n')) 
       self.chatlog['state'] = DISABLED 
       self.chatlog.yview(END) 
       self.send_data(self.msg) #Sends message 
     else: 
       self.chatlog['state'] = NORMAL 
       self.chatlog.insert(END, ("===YOU ARE NOT CONNECTED TO A SERVER. YOU CANNOT SEND A MESSAGE.\n")) 
       self.chatlog['state'] = DISABLED 
       self.chatlog.yview(END) 


    def send_data(self, message): 
     try: 
      s.send(message.encode('UTF-8')) 
     except: 
       self.chatlog['state'] = NORMAL 
       self.chatlog.insert(END, ("===THE PREVIOUS MESSAGE DIDN'T SEND. THIS IS POSSIBLY DUE TO A SERVER ERROR.\n===Disconnect and reconnect.")) 
       self.chatlog['state'] = DISABLED 
       self.chatlog.yview(END) 


class RecvThreadClass(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 

    def run(self): 
     receive_data() 


def receive_data(): 
    print("Preparing to receive") 
    while 1: 
     data=s.recv(1024) 
     print("Data received") 
     decoded_data=data.decode('UTF-8') 
     print(decoded_data) 
     Application.chatlog['state'] = NORMAL 
     Application.chatlog.insert(END, ('Server: ' + decoded_data + '\n')) 
     Application.chatlog['state'] = DISABLED 
     Application.chatlog.yview(END) 

root = Tk() 
app = Application(root) 
app.mainloop 
+2

什麼是異常的(完整)回溯? –

+0

此代碼可能無法可靠地工作 - 您不應該從非GUI線程調用GUI方法。 Tkinter的設計不是可以從多個線程調用的。 –

回答

1

您嘗試在的類,而不是app實例訪問chatlog。將所有Application引用app

def receive_data(): 
    print("Preparing to receive") 
    while 1: 
     data=s.recv(1024) 
     print("Data received") 
     decoded_data=data.decode('UTF-8') 
     print(decoded_data) 
     app.chatlog['state'] = NORMAL 
     app.chatlog.insert(END, ('Server: ' + decoded_data + '\n')) 
     app.chatlog['state'] = DISABLED 
     app.chatlog.yview(END) 

只有實例都有一個chatlog屬性(在Application.__init__()創建)。

+0

我知道我會錯過這樣簡單的事情。謝謝。 – QuarterGeekster