【问题标题】:Frequent Updating of GUI WxPYTHONGUI WxPYTHON 的频繁更新
【发布时间】:2016-09-21 22:16:24
【问题描述】:

我有一段代码必须每 100 毫秒执行一次并更新 GUI。当我更新 GUI 时 - 我正在按下一个按钮,该按钮调用一个线程,然后它调用一个目标函数。目标函数使用 pub sub 将消息返回给 GUI 线程,如下所示。

wx.CallAfter(pub.sendMessage, "READ EVENT", arg1=data, arg2=status_read) # This command line is in my target function

        pub.subscribe(self.ReadEvent, "READ EVENT") # This is in my GUI file - whihc calls the following function

 def ReadEvent(self, arg1, arg2):
        if arg2 == 0:
            self.MessageBox('The program did not properly read data from MCU \n Contact the Program Developer')
            return

        else:
            self.data = arg1

            self.firmware_version_text_control.Clear()
            #fwversion = '0x' + ''.join('{:02X}'.format(j) for j in reversed(fwversion))
            self.firmware_version_text_control.AppendText(str(SortAndDecode(self.data, 'FwVersion')))
            # Pump Model
            self.pump_model_text_control.Clear()
            self.pump_model_text_control.AppendText(str(SortAndDecode(self.data, 'ModelName')))
            # Pump Serial Number
            self.pump_serial_number_text_control.Clear()
            self.pump_serial_number_text_control.AppendText(str(SortAndDecode(self.data, 'SerialNum'))[:10]) # Personal Hack to not to display the AA , AB and A0
            # Pressure GAIN
            self.gain_text_control.Clear()
            self.gain_text_control.AppendText(str(SortAndDecode(self.data, 'PresGain')))
            # Pressure OFFSET Offset
            self.offset_text_control.Clear()
            self.offset_text_control.AppendText(str(SortAndDecode(self.data, 'PresOffset')))
            #Wagner Message:
            #self.status_text.SetLabel(str(SortAndDecode(self.data, 'WelcomeMsg')))
            # PUMP RUNNING OR STOPPED

            if PumpState(SortAndDecode(self.data, 'PumpState')) == 1:
                self.led6.SetBackgroundColour('GREEN')
            elif PumpState(SortAndDecode(self.data, 'PumpState')) == 0:
                self.led6.SetBackgroundColour('RED')
            else:
                self.status_text.SetLabel(PumpState(SortAndDecode(self.data, 'PumpState')))
            # PUMP RPM
            self.pump_rpm_text_control.Clear()
            if not self.new_model_value.GetValue():
                self.pump_rpm_text_control.AppendText("000")
            else:
                self.pump_rpm_text_control.AppendText(str(self.sheet_num.cell_value(self.sel+1,10)*(SortAndDecode(self.data, 'FrqQ5'))/65536))
            # PUMP PRESSURE
            self.pressure_text_control.Clear()
            self.pressure_text_control.AppendText(str(SortAndDecode(self.data, 'PresPsi')))
            # ON TIME   -- HOURS AND MINUTES --- EDITING IF YOU WANT
            self.on_time_text_control.Clear()
            self.on_time_text_control.AppendText(str(SortAndDecode(self.data, 'OnTime')))
            # JOB ON TIME - HOURS AND MINUTES - EDITING IF YOU WANT
            self.job_on_time_text_control.Clear()
            self.job_on_time_text_control.AppendText(str(SortAndDecode(self.data, 'JobOnTime')))
            # LAST ERROR ----- RECHECK THIS AGAIN
            self.last_error_text_control.Clear()
            self.last_error_text_control.AppendText(str(SortAndDecode(self.data, 'LastErr')))
            # LAST ERROR COUNT --- RECHECK THIS AGAIN
            self.error_count_text_control.Clear()
            self.error_count_text_control.AppendText("CHECK THIS")

如您所见,我的 READEVENT 非常大,GUI 需要一段时间才能成功完成所有这些事情。我的问题是,当我的 GUI 更新 TEXTCTRL 的值时,它会无响应 - 我不能做任何其他事情。我无法按下按钮或输入数据或其他任何内容。我的问题是我是否有更好的方法来做到这一点,所以我的 GUI 不会无响应。我不知道如何将它放在不同的线程中,因为所有小部件都在主 GUI 中。但这也需要每 100 毫秒创建线程——这太可怕了。任何建议都会很有帮助。

【问题讨论】:

    标签: multithreading wxpython publish-subscribe


    【解决方案1】:

    一些建议:

    1. SortAndDecode 需要多长时间?结果的str() 呢?这些可能是将处理保留在工作线程而不是 UI 线程中并将值传递给预先排序和解码的 UI 线程的良好候选者。

    2. 您可以通过调用ChangeValue 而不是ClearAppendText 在每次迭代中节省一点时间。为什么每个文本小部件有两个函数调用而不是一个?与其他 Python 代码相比,Python 中的函数调用相对昂贵。

    3. 如果可能会发送与上次迭代中发送的相同值,则添加对与旧值匹配的新值的检查并跳过小部件的更新可能会节省大量时间。与不理会它们相比,更新小部件值非常昂贵。

    4. 除非对 100 毫秒更新有硬性要求,否则您可能想尝试 150 或 200 次。对于大多数人来说,每秒更少的更新可能就足够快了,尤其是因为它主要是文本的。 100ms 能读多少文字?

    5. 如果您仍然无法获得比 UI 线程能够跟上的更多更新,那么您可能希望使用与 pubsub 和 wx.CallAfter 不同的方法。例如,您可以让工作线程接收并处理数据,然后将对象添加到Queue.Queue,然后调用wx.WakeUpIdle()。在 UI 线程中,您可以有一个 EVT_IDLE 事件处理程序,它检查队列并将第一项从队列中拉出(如果有的话),然后使用该数据更新小部件。这样做的好处是不会让来自太多 wx.CallAfter 调用的事件淹没待处理事件列表,如果数据队列中有太多项目,您还可以执行诸如从数据队列中删除项目之类的操作。

      李>

    【讨论】:

    • 有趣的答案。我对第 3 点和第 5 点更感兴趣。第 3 点 - 那不是要运行更多代码吗?并进一步减慢进程?第5点:你能给我举个例子吗?我像一个月前一样尝试了队列,但失败得很厉害,因为它只给出了 192 长度的 numpy 数组中的一个元素。如果你能给我一个使用 wx.WakeupIdle 的例子,我将不胜感激
    猜你喜欢
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-10
    • 2020-08-02
    相关资源
    最近更新 更多