Как использовать поток с matplotlib на wxpython - PullRequest
0 голосов
/ 16 мая 2019

Я хочу использовать другой поток для matplotlib. Но когда я запускаю скрипт ниже, он выдает ошибку , таймер может быть запущен только из основного потока . Любая помощь будет оценена.

import wx
from threading import Thread
import serial
import threading
import time
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax1 = plt.subplots( )  
def runA():
    print("THREAD")
    while True:
        def mix(i)
            x=[1,3,5]
            y=[13,5,23]
            plt.plot(x,y)
            time.sleep(1)
        ani =animation. FuncAnimation(fig,mix)
        plt.show()

class MyFrame1 ( wx.Frame ):
    def __init__ (self, parent):
        wx.Frame.__init__(self, parent)
        self.SetSizeHints( wx.Defaultsize, wx.DefaultSize)
        bSizer3= wx.BoxSizer(wx.VERTICAL)

        self.button1= wx.Button( self, wx.ID_ANY, "mybutton1", wx.DefaultPosition, wx.DefaultSize, 0)

        bsizer3.Add( self.button1, 1, wx.ALL|wx.EXPAND, 5)

        self.button2= wx.Button( self, wx.ID_ANY, "mybutton2", wx.DefaultPosition, wx.DefaultSize, 0)

        bsizer3.Add( self.button2, 1, wx.ALL|wx.EXPAND, 5)
        self SetSizer( bsizer3)
        self.Layout ()
        self.Centre( wx. BOTH )
# Connect Events
        self.button1.Bind(wx.EVT_BUTTON, self.b1_f )
        self.button2.Bind(wx.EVT_BUTTON, self.b2_f )

    def b1_f( self, event ):
        t2=Thread (target =runA)
        t2.start()

    def b2_f( self, event):
        print("heLLo")

if __name__ == "__main__":
    app = wx.App(False)
    frame=MyFrame1 (None)
    frame.Show(True)
    app.MainLoop()

Примечание. На самом деле wxpython имеет собственную библиотеку печати. Но мне не удалось прочитать изображение и нанести на него данные.

1 Ответ

1 голос
/ 23 мая 2019

В вашем вопросе было несколько проблем с кодом. Следующая строка не работает в wxPython 4.0.4, self.SetSizeHints( wx.Defaultsize, wx.DefaultSize), и вы использовали разные имена для wx.BoxSizer. Что касается вопроса, я не смог воспроизвести вашу ошибку, но я думаю, что проблема в том, что вам нужно переместить код построения на class MyFrame1. Один из способов сделать это:

import wx
from threading import Thread
import serial
import threading
import time
import matplotlib.pyplot as plt
import matplotlib.animation as animation

class MyFrame1(wx.Frame):
    def __init__ (self, parent):
        wx.Frame.__init__(self, parent)
        #self.SetSizeHints(wx.Defaultsize, wx.DefaultSize)
        bSizer3= wx.BoxSizer(wx.VERTICAL)

        self.button1 = wx.Button(self, wx.ID_ANY, "mybutton1", 
                                 wx.DefaultPosition, wx.DefaultSize, 0)

        bSizer3.Add(self.button1, 1, wx.ALL|wx.EXPAND, 5)

        self.button2 = wx.Button(self, wx.ID_ANY, "mybutton2", 
                                 wx.DefaultPosition, wx.DefaultSize, 0)

        bSizer3.Add(self.button2, 1, wx.ALL|wx.EXPAND, 5)
        self.SetSizer(bSizer3)
        self.Layout()
        self.Centre(wx.BOTH)
# Connect Events
        self.button1.Bind(wx.EVT_BUTTON, self.b1_f)
        self.button2.Bind(wx.EVT_BUTTON, self.b2_f)

    def b1_f( self, event ):
        print('Hello2')
        t2=Thread(target = self.runA)
        t2.start()

    def b2_f( self, event):
        print("heLLo")


    def runA(self):
        fig, ax1 = plt.subplots( )  
        print("THREAD")
        while True:
            def mix(i):
                x=[1,3,5]
                y=[13,5,23]
                plt.plot(x,y)
                time.sleep(1)
            ani = animation.FuncAnimation(fig,mix)
            plt.show()

if __name__ == "__main__":
    app = wx.App()
    frame=MyFrame1(None)
    frame.Show()
    app.MainLoop()

Сейчас эта работа, но:

1 - вам следует рассмотреть возможность использования бэкэнда wxAgg для matplotlib . Используемый теперь бэкэнд выдает нефатальную ошибку при создании графика, закрытии и повторном построении. Кроме того, он работает в Win10 и Linux (Fedora 30), но не работает в macOS 10.14.4. Вот пример .

2 - Вам нужно найти способ деактивировать / активировать button1, потому что с текущим бэкэндом matplotlib вы не можете иметь два графика одновременно. Поэтому нажатие кнопки во время показа графика приводит к тому, что графический интерфейс не отвечает.

3 - таймер в функции построения графика делает график не отвечающим. Возможно, у matplotlib есть другой способ управления скоростью анимации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...