Датчик wxPython зависает в Linux

1

Я борюсь с wxPython в Linux. После большого количества времени и исследований я сократил свою программу до минимума, чтобы показать вам одну из проблем, с которыми я столкнулся. Я мог бы уменьшить его до довольно небольшого примера кода, используя только один датчик в окне, который обновляется таймером. Мои первые проблемы появились с кнопками, цвет фона которых должен был быть быстро изменен, что привело к странным ошибкам памяти. Поскольку полное приложение далеко не сложно, я искал простой пример - бинго! Вот приведенный код, который отлично работает в Windows и не работает на Raspberry Pi, а также виртуальные виртуальные машины VirtualBox от Raspberry Pi и Debian 9. Я пробовал wxPython 3.0.2.0 и 4.0.3, каждый с gtk2 и python 2.7 и python 3.5:

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import wx
from threading import Timer

class MainWindow(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Test", size=(600, 100))
        panel = wx.Panel(self)

        self.gauge = wx.Gauge(panel, wx.ID_ANY, 100, (10, 10), (480, 10))
        self.gaugeval = 0
        self.gauge.SetValue(self.gaugeval)

        self.Show()
        Timer(1, self.loop).start()

    def loop(self):
        self.gaugeval += 1
        if self.gaugeval > 100:
            self.gaugeval = 0
        self.gauge.SetValue(self.gaugeval)
        Timer(0.01, self.loop).start()


app = wx.App(False)
frame = MainWindow()
app.MainLoop()

После запуска программы требуется одна секунда, пока калибр не должен "жить" и заполнить панель слева направо, а затем снова начать с левой стороны и так далее. Однако в любой из протестированных систем Linux он замерзает очень быстро.

Что здесь происходит? Может ли кто-нибудь воспроизвести это? Я с трудом могу поверить, что такая простая функция не сработает. Большое спасибо за то, что посмотрели на эту проблему!

Теги:
wxpython

1 ответ

0
Лучший ответ

Я подозреваю, что ваша проблема может заключаться в использовании Timer из модуля потоковой передачи.
Используйте wx.Timer.

import wx

class MainWindow(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Test", size=(600, 100))
        panel = wx.Panel(self)
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onTimer, self.timer)
        self.gauge = wx.Gauge(panel, wx.ID_ANY, 100, (10, 10), (480, 10))
        self.Show()
        self.timer.Start(100) # fire every 10th of a second

    def onTimer(self, evt):
        val = self.gauge.GetValue()
        val += 1
        if val > 100:
            val = 0
        self.gauge.SetValue(val)

app = wx.App(False)
frame = MainWindow()
app.MainLoop()
  • 0
    Спасибо, выглядит очень хорошо сейчас! Тем не менее, я должен увидеть, как интегрировать это в реальную программу, которая намного сложнее. Там таймер работает в другом процессе, и вызов для обновления датчика отправляется по каналу. Во всяком случае, очень полезный подход. :-)
  • 0
    К вашему сведению: использование wx.CallAfter, похоже, решило все проблемы, вызванные параллельными процессами, таймерами, потоками. Ваш ответ привел меня на правильный путь, чтобы проверить безопасные методы: blog.pythonlibrary.org/2010/05/22/wxpython-and-threads
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню