2015-06-23 77 views
0

我正在尝试构建一个基本的消息传递系统,但我在这个过程中遇到了一个主要障碍。如果没有响应,我无法关闭窗口,我必须在任务管理器中关闭它。从我在线阅读的内容来看,听起来好像我需要关闭sys.exit(0)以退出所有线程和连接。我一直被困在这个问题上好几天,所以我真的很感激为什么它不起作用的答案和解释!问题的关键在close_window()函数中。它可以运行,只要你有一个接受连接的基本服务器。谢谢!为什么我的wxFrame不能正确关闭?

import wx 
import socket 
import threading 
import sys 

class oranges(wx.Frame): 
    def __init__(self,parent,id): 

     ##Unimportant stuff 
     wx.Frame.__init__(self,parent,id," Retro Message",size=(500,500)) 
     self.frame=wx.Panel(self) 
     self.input_box=wx.TextCtrl(self.frame, -1,pos=(15,350),size=(455,120),style=wx.NO_BORDER| wx.TE_MULTILINE) 
     self.messaging_box=wx.TextCtrl(self.frame, -1,pos=(15,15),size=(455,285),style=wx.NO_BORDER | wx.TE_MULTILINE|wx.TE_READONLY) 
     send_button=wx.Button(self.frame,label="Send",pos=(350,315),size=(75,40)) 
     self.Bind(wx.EVT_BUTTON, self.sender,send_button) 
     self.Bind(wx.EVT_CLOSE, self.close_window) 
     self.counter = 1 
     self.socket_connect = socket.socket() 
     self.setup() 

    def sender(self,event): 
     self.socket_connect.send(self.input_box.GetValue()) 
     self.input_box.Clear() 
     self.Refresh() 

     ##Important stuff 
    def close_window(self,event): #This is the function in question# 
     self.counter = 0 
     self.socket_connect.shutdown(socket.SHUT_RDWR) 
     sys.exit(0) 
    def setup(self): 
     self.ip_enter = wx.TextEntryDialog(None, "Enter in the IP:", "Setup", "192.168.1.1") 
     if self.ip_enter.ShowModal() ==wx.ID_OK: 
      self.offical_ip = self.ip_enter.GetValue() 
      try: 
       self.socket_connect.connect((self.offical_ip,5003)) 
       self.username = "false" #Tells the server just to give the user a IP username 
       self.Thread1 = threading.Thread(target = self.listening_connect) 
       self.Thread1.start() 
      except socket.error: 
       self.error_connect() 
     else: 
      sys.exit(0) 

    def listening_connect(self): 
     self.socket_connect.send(self.username) 
     while self.counter != 0: 
      data = self.socket_connect.recv(1024) 
      self.messaging_box.AppendText(data) 
      self.Refresh() 
      if not data: 
       break 
     self.socket_connect.close()   
    def error_connect(self): 
     pop_ups = wx.MessageDialog(None, "Failed to Connect to Server!", 'Error', wx.OK) 
     pop_ups.ShowModal() 
     self.setup() 

if __name__=="__main__": 
    app=wx.App(False) 
    window=oranges(parent=None,id=-1) 
    window.Show() 
    app.MainLoop() 

这是一个基本的服务器程序,应该使用它(我无法测试它,但它是非常相似的真实的)

import socket 

HOST = '192.168.1.1' 
PORT=5003 
s = socket.socket() 
s.bind((HOST, PORT)) 
s.listen(1) 
c,addr = s.accept() 
while True: 
    data = c.recv(1024) 
    if not data: 
     break 
c.close() 

回答

1

你需要等待线程结束。否则,它可能会使脚本挂起。为什么?那么线程与GUI线程是分开的,所以它不会因为关闭了你的wxPython应用程序而被杀死。这里是我会推荐的:

def close_window(self, event): 
    self.Thread1.join() 
    self.Destroy() 

这使得脚本等待线程在关闭应用程序之前完成。如果您希望框架消失,则应在join之前致电self.Hide()。另一种方法是在你的线程中放入一些逻辑,在那里你可以发送一条消息告诉它应用程序正在关闭,所以线程需要中止。

你或许应该看看下面的堆栈答案:

+0

这个问题似乎是在线程本身与while循环。即使我将'self.counter'变量设置为0,while循环也不会退出,可能是因为'self.socket_connect.recv(1024)'行。有任何想法吗?感谢您的回应! – user3818089