如何连续更新(类似终端)一个wxPython TextCtrl

时间:2016-12-12 13:22:49

标签: python python-2.7 wxpython

我正在使用esptool.py的wxPython GUI,即应用程序将调用该脚本。对于初学者,我想将esptool.py打印的内容重定向到控制台到TextCtrl。我跟着frequently referenced article进行了检查,效果很好。

但是,我目前无法处理progress monitor that esptool.py prints to console。它可以打印出像" 25%"然后是一些\b,它会立即删除所打印的内容,然后是" 26%"它会立即被删除,等等。

计划是解析字符串,TextCtrl.AppendText()除了退格字符之外的所有内容,然后TextCtrl.Remove()解析与退格字符一样多的字符。

当我使用调试器逐步执行它时,下面的代码工作正常,但是当"松散"时它会崩溃。似乎有一些时间/线程问题。显然我无法在TextCtrl.Remove()之后立即致电TextCtrl.AppendText()

class RedirectText:
    def __init__(self, textCtrl):
        self.out = textCtrl

    def write(self, string):
        new_string = ""
        number_of_backspaces = 0
        # this could definitely be improved performance wise...
        for c in string:
            if c == "\b":
                number_of_backspaces += 1
            else:
                new_string += c

        self.out.AppendText(new_string)
        if number_of_backspaces > 0:
            last_position = self.out.GetLastPosition()
            self.out.Remove(last_position - number_of_backspaces, last_position)

    def flush(self):
        None

调用esptool.py的代码在其自己的线程中运行,以免占用主UI线程。

这是我的第一个真正的Python项目(当然也是第一个w / wxPython)并且我多年没有为桌面编码了。所以,我完全有可能错过一些明显的东西。

1 个答案:

答案 0 :(得分:1)

为了完整性,这里有(解决方案之一)。

事实证明,快速连续使用wx.CallAfter操纵文本控件并不太可靠GetLastPosition()。因此,它现在只需附加文本并记住要删除的下一个时间write()被删除的字符数。然后在附加新文本之前删除这些字符。

class RedirectText:
    def __init__(self, text_ctrl):
        self.out = text_ctrl
        self.pending_backspaces = 0

    def write(self, string):
        new_string = ""
        number_of_backspaces = 0
        for c in string:
            if c == "\b":
                number_of_backspaces += 1
            else:
                new_string += c

        if self.pending_backspaces > 0:
            # current value minus pending backspaces plus new string
            new_value = self.out.GetValue()[:-1 * self.pending_backspaces] + new_string
            wx.CallAfter(self.out.SetValue, new_value)
        else:
            wx.CallAfter(self.out.AppendText, new_string)

        self.pending_backspaces = number_of_backspaces

    def flush(self):
        None