[SetValue上的wxpython TextCtrl分段错误

问题描述 投票:0回答:1

我正在用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 /小部件被修改以来,迭代器已创建。您必须使用标记,字符数或行数字以在缓冲区修改中保留位置。您可以在不使迭代器无效的情况下应用标签和插入标记,但是任何影响“可索引”缓冲区内容(可以通过字符偏移量引用)将使所有杰出的迭代器细分错误

python wxpython
1个回答
0
投票

我不认为从线程内更新将正常进行。更新应使用主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()
© www.soinside.com 2019 - 2024. All rights reserved.