Отображение данных в графическом интерфейсе, где данные поступают из внешнего источника - PullRequest
0 голосов
/ 09 апреля 2009

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

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

Есть предложения?

Ответы [ 3 ]

0 голосов
/ 09 апреля 2009

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

0 голосов
/ 09 апреля 2009

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

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()

Проверьте это, отправив некоторые данные с:

import win32pipe

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

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

0 голосов
/ 09 апреля 2009

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

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

Да, и когда вы делаете отображение, убедитесь, что вы делаете это нетривиальными "кусками" за раз. Очень легко максимизировать очередь сообщений (по крайней мере в Windows), которая отправляет команды обновления в текстовое поле.

...