我对wxpython的textctrl和线程有任何问题。如有任何帮助,我们将不胜感激。
我的程序处理文件,当每个文件被处理时,它在textctrl中被列为已完成。当只处理几个文件时,textctrl会做出响应,并立即显示自己,不会消失。即使这些文件很大。在一个700mb的文件上做了一个测试,textctrl运行得很好。
在处理许多文件时会出现问题,比如exmaple的20+。在这种情况下,textctrl会消失6或7秒,然后再次出现并正常工作。
我尝试过普通线程、守护进程线程等。还尝试过使用.join(),这让情况变得更糟。我想知道这是否只是因为我的程序占用了大量处理器,或者我只是做错了什么。
下面列出了我的线程代码行。到目前为止,这是最快的方法,但对我的目的来说还不够好。提前谢谢,克林顿。
def Worker(self, e, _file):
match = ''
with open(_file, 'r') as f:
data = f.read()
for char in data:
if char in self.key:
match += chr(self.key.index(char))
open(_file, 'w').close()
with open(_file, 'w') as f:
f.write(match)
wx.CallAfter(self.ListFilesEncrypt, e, _file)
if __name__ == '__main__':
for _file in self.file2process:
self.filenum += 1
Thread(target=self.Worker, args=(e, _file,)).start()
使用线程安全方法更新GUI。在wxPython中,有3:
- wx.CallAfter
- wx.CallLater
- wx.PostEvent
您还应该查看wxPython wiki,了解有关wxPython和线程的信息:
- http://wiki.wxpython.org/LongRunningTasks
我还写了一个关于这个主题的教程:
- http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/
UPDATE:下面是一个创建40个线程并"处理"40个组成文件的简单示例。它会在每个线程完成后更新显示。但是,我看不出你所说的问题。
import random
import time
import wx
from threading import Thread
from wx.lib.pubsub import Publisher
########################################################################
class TestThread(Thread):
"""Test Worker Thread Class."""
#----------------------------------------------------------------------
def __init__(self, fname, sleepAmt):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.fname = fname
self.sleepAmt = sleepAmt
self.start() # start the thread
#----------------------------------------------------------------------
def run(self):
"""Run Worker Thread."""
# This is the code executing in the new thread.
time.sleep(self.sleepAmt)
msg = "%s finished in %s seconds!" % (self.fname, self.sleepAmt)
wx.CallAfter(Publisher().sendMessage, "update", msg)
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial")
panel = wx.Panel(self, wx.ID_ANY)
self.updateText = wx.TextCtrl(panel, style=wx.TE_MULTILINE)
self.btn = btn = wx.Button(panel, label="Start Thread")
btn.Bind(wx.EVT_BUTTON, self.onButton)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.updateText, 1, wx.ALL|wx.EXPAND, 5)
sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
panel.SetSizer(sizer)
# create a pubsub receiver
Publisher().subscribe(self.updateDisplay, "update")
#----------------------------------------------------------------------
def onButton(self, event):
"""
Runs the thread
"""
for i in range(40):
fname = "test%s.txt" % i
secs = random.choice(range(3, 15))
TestThread(fname, secs)
#----------------------------------------------------------------------
def updateDisplay(self, msg):
"""
Receives data from thread and updates the display
"""
data = msg.data + "n"
self.updateText.WriteText(data)
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyForm().Show()
app.MainLoop()
我在Windows 7上运行,使用Python 2.6和wxPython 2.8.12.1
您的线程应该而不是直接更新文本控件-它们应该使用wx.CallAfter
,或者更好地为主线程(GIU)设置一个标志来更新控件-听起来端线程方法可能是合适的。
它不仅占用CPU,还可能占用IO。IO密集型应用程序可能会对性能产生很大影响,尤其是当您还将IO单元用于其他关键用途(如分页)时。我建议一次发球5到10次,其余的都排队。
我正在使用wxpython 4.1.1,发现它不再有效。
wxPyDeprecationWarning: wx.lib.pubsub has been deprecated, plese migrate your code to use pypubsub, available on PyPI.
======================================================================
*** ATTENTION ***
This messaging protocol is deprecated. This module, and hence arg1
messaging protocol, will be removed in v3.4 of PyPubSub. Please make
the necessary changes to your code so that it no longer requires this
module. The pypubsub documentation provides steps that may be useful
to minimize the chance of introducing bugs in your application.
======================================================================