我正在用wxglade构建一个小型应用程序。
它基本上只是一个TextCtrl多行和只读。我启动一个线程,该线程读取文件并将内容显示到TextCtrl中。一堆执行后,我得到了一个细分错误。
Debian 9的Python 3.5.3wxpython 4.0.7.post2
有任何建议吗?非常感谢!
代码
import wx, threading, pdb
import gettext
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((400, 300))
self.text_ctrl_1 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
self.__set_properties()
self.__do_layout()
self.update_text()
def update_text(self):
print("update_text")
text = ""
try:
f = open("test.txt", "r")
text = f.read()
f.close()
except:
print(_('Error opening test.txt file!'))
text = _('Error opening test.txt file!')
self.text_ctrl_1.SetValue(text)
threading.Timer(1, self.update_text).start()
def __set_properties(self):
self.SetTitle(_("frame"))
def __do_layout(self):
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_1.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
self.Layout()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
if __name__ == "__main__":
gettext.install("app") # replace with the appropriate catalog name
app = MyApp(0)
app.MainLoop()
错误
update_textupdate_textupdate_text更新文本
(wxglade_out.py:5127):Gtk-警告**:无效的文本缓冲区迭代器:迭代器未初始化,或者自从缓冲区中的字符/ pixbufs /小部件被修改以来,迭代器已创建。您必须使用标记,字符数或行数字以在缓冲区修改中保留位置。您可以在不使迭代器无效的情况下应用标签和插入标记,但是任何影响“可索引”缓冲区内容(可以通过字符偏移量引用)将使所有出色的迭代器
(wxglade_out.py:5127):Gtk-警告**:无效的文本缓冲区迭代器:迭代器未初始化,或者自从缓冲区中的字符/ pixbufs /小部件被修改以来,迭代器已创建。您必须使用标记,字符数或行数字以在缓冲区修改中保留位置。您可以在不使迭代器无效的情况下应用标签和插入标记,但是任何影响“可索引”缓冲区内容(可以通过字符偏移量引用)将使所有杰出的迭代器细分错误
我不认为从线程内更新将正常进行。更新应使用主GUI循环执行。我不知道这与gtk是否相关:Gtk +3 TextView application crashes
您可以使用变量通过pubsub或您自己的某些设备尝试更新,也可以使用wx.Timer
而不是线程来进行更新。
import wx
import time
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((400, 300))
self.text_ctrl_1 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
self.__set_properties()
self.__do_layout()
#self.update_text(None)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.update_text, self.timer)
self.timer.Start(5000)
def update_text(self, event):
print("update_text")
self.text_ctrl_1.Clear()
wx.GetApp().Yield() # to see the clear occur release momentarily to the main loop
try:
with open("test.txt", "r") as f:
text = f.read()
except:
print(_('Error opening test.txt file!'))
text = _('Error opening test.txt file!')
time.sleep(2)
self.text_ctrl_1.SetValue(text)
def __set_properties(self):
self.SetTitle("My frame")
def __do_layout(self):
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_1.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
self.Layout()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
if __name__ == "__main__":
app = MyApp()
app.MainLoop()