我对如何解决这个问题有点迷茫,我想用 Tkinter 和 python 编写一个理想的 GUI,但我最初是从 Qt 开始的,发现问题延伸到所有 GUI 框架或我有限的理解。
在这种情况下,数据来自命名管道,我想将通过管道传入的任何内容显示到文本框中。我试过让一个线程在管道上侦听,另一个线程创建 GUI,但在这两种情况下,一个线程似乎总是挂起或 GUI 永远不会被创建。
有什么建议么?
我对如何解决这个问题有点迷茫,我想用 Tkinter 和 python 编写一个理想的 GUI,但我最初是从 Qt 开始的,发现问题延伸到所有 GUI 框架或我有限的理解。
在这种情况下,数据来自命名管道,我想将通过管道传入的任何内容显示到文本框中。我试过让一个线程在管道上侦听,另一个线程创建 GUI,但在这两种情况下,一个线程似乎总是挂起或 GUI 永远不会被创建。
有什么建议么?
当我做这样的事情时,我使用了一个单独的线程来监听管道。该线程有一个指向 GUI 的指针/句柄,因此它可以发送要显示的数据。
我想你可以在 GUI 的更新/事件循环中做到这一点,但你必须确保它在管道上进行非阻塞读取。我在一个单独的线程中完成了它,因为我必须对通过的数据进行大量处理。
哦,当您进行显示时,请确保一次以非平凡的“块”进行显示。最大化将更新命令发送到文本框的消息队列(至少在 Windows 上)非常容易。
过去,当我让 GUI 从外部事物(例如:以太网套接字)读取数据时,我有一个单独的线程来处理外部事物的服务,以及一个定时回调(通常设置为半秒左右)更新显示外部数据的 GUI 小部件。
这是我的做法(在 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)
(在这种情况下,您也会收到回复)