2009-04-08 1 views
0

Я как бы потерял то, как подойти к этой проблеме. Я хотел бы написать графический интерфейс с использованием Tkinter с помощью python, но сначала я начал с Qt и что проблема распространяется либо на все графические интерфейсы, либо на мое ограниченное понимание.Отображение данных в графическом интерфейсе, в котором данные поступают из внешнего источника.

Данные в этом случае поступают из именованного канала, и я хотел бы отображать все, что попадает через трубу в текстовое поле. Я попытался прослушивать один поток на трубке, а другой создать графический интерфейс, но в обоих случаях один поток всегда кажется зависающим или графический интерфейс никогда не создается.

Любые предложения?

+0

Вы можете отправить пример кода, с которым у вас возникла проблема с –

ответ

0

Вот как я бы сделал это (на окнах):

import wx, wx.lib.newevent, threading 
import win32event, win32pipe, win32file, pywintypes, winerror 


NewMessage, EVT_NEW_MESSAGE = wx.lib.newevent.NewEvent() 
class MessageNotifier(threading.Thread): 
    pipe_name = r"\\.\pipe\named_pipe_demo" 

    def __init__(self, frame): 
     threading.Thread.__init__(self) 
     self.frame = frame 

    def run(self): 
     open_mode = win32pipe.PIPE_ACCESS_DUPLEX | win32file.FILE_FLAG_OVERLAPPED 
     pipe_mode = win32pipe.PIPE_TYPE_MESSAGE 

     sa = pywintypes.SECURITY_ATTRIBUTES() 
     sa.SetSecurityDescriptorDacl(1, None, 0) 

     pipe_handle = win32pipe.CreateNamedPipe(
      self.pipe_name, open_mode, pipe_mode, 
      win32pipe.PIPE_UNLIMITED_INSTANCES, 
      0, 0, 6000, sa 
     ) 

     overlapped = pywintypes.OVERLAPPED() 
     overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None) 

     while 1: 
      try: 
       hr = win32pipe.ConnectNamedPipe(pipe_handle, overlapped) 
      except: 
       # Error connecting pipe 
       pipe_handle.Close() 
       break 

      if hr == winerror.ERROR_PIPE_CONNECTED: 
       # Client is fast, and already connected - signal event 
       win32event.SetEvent(overlapped.hEvent) 

      rc = win32event.WaitForSingleObject(
       overlapped.hEvent, win32event.INFINITE 
      ) 

      if rc == win32event.WAIT_OBJECT_0: 
       try: 
        hr, data = win32file.ReadFile(pipe_handle, 64) 
        win32file.WriteFile(pipe_handle, "ok") 
        win32pipe.DisconnectNamedPipe(pipe_handle) 
        wx.PostEvent(self.frame, NewMessage(data=data)) 
       except win32file.error: 
        continue 


class Messages(wx.Frame): 
    def __init__(self): 
     wx.Frame.__init__(self, None) 
     self.messages = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY) 
     self.Bind(EVT_NEW_MESSAGE, self.On_Update) 

    def On_Update(self, event): 
     self.messages.Value += "\n" + event.data 


app = wx.PySimpleApp() 
app.TopWindow = Messages() 
app.TopWindow.Show() 
MessageNotifier(app.TopWindow).start() 
app.MainLoop() 

Test, отправив некоторые данные:

import win32pipe 

print win32pipe.CallNamedPipe(r"\\.\pipe\named_pipe_demo", "Hello", 64, 0) 

(вы также получите ответ в данном случае)

0

Когда я сделал что-то подобное, я использовал отдельную нить, слушая трубку. В потоке был указатель/дескриптор GUI, чтобы он мог отправлять отображаемые данные.

Я полагаю, вы могли бы сделать это в цикле обновления/события GUI, но вам нужно убедиться, что он делает неблокирующие чтения на трубе. Я сделал это в отдельном потоке, потому что мне пришлось много обрабатывать данные, которые прошли.

О, и когда вы делаете показ, убедитесь, что вы делаете это в нетривиальных «кусках» за раз. Это очень просто, чтобы максимизировать очередь сообщений (по крайней мере на Windows), которые отправляют команды обновления в текстовое поле.

0

В прошлом, когда у меня были данные с графического интерфейса от внешних вещей (например, Ethernet-сокеты), у меня был отдельный поток, который обрабатывает внешнюю информацию, и временный обратный вызов (обычно заданный как-то вроде полсекунды), чтобы обновить виджет GUI, который отображает внешние данные.

Смежные вопросы