[wxpython] Comment utiliser l'axe de base et du temps de wx.lib.plot

introduction

Ceci est le premier post! J'ai hâte de travailler avec vous!

Il est possible de dessiner un graphique en temps réel dans l'interface graphique, et c'est un résumé à ce moment-là. Comme l'interface graphique utilisait wxpython, j'ai utilisé wx.lib.plot dans le même module wx. J'ai eu du mal à trouver des articles sur l'axe du temps, j'espère donc que vous le trouverez utile.

environnement

mac OS python 3.8.5 wxpython 4.1.0

importer

python


import wx
import wx.lib
import wx.lib.plot as plot

De base

Organisez dans l'ordre wx.Frame-> wx.Panel-> plot.Canvas.

python


import wx
import wx.lib
import wx.lib.plot as plot
#Utilisé pour le dessin graphique
import random

#Valeur à dessiner
x_val = list(range(10))
y_val = [random.randint(0, 10) for i in range(10)]  # 0~10 valeurs aléatoires jusqu'à 10

# [(x1, y1), (x2, y2),...(xn, yn)]Transformé pour passer au graphique au format
xy_val = list(zip(x_val, y_val))


class MainFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(500, 500))
        #création de panneaux
        self.panel = wx.Panel(self, -1)
        #création de graphes
        self.plotter = plot.PlotCanvas(self, -1)
        #Créer une ligne à afficher&dessin
        line = plot.PolyLine(xy_val)
        gc = plot.PlotGraphics([line])
        self.plotter.Draw(gc)

        #création de calibre&Installation
        sizer = wx.GridSizer(1, 1, gap=(0, 0))
        sizer.Add(self.plotter, flag=wx.EXPAND)
        self.SetSizer(sizer)

        #Afficher l'interface graphique au centre de l'écran
        self.Center()
        self.Show()


def main():
    app = wx.App()
    MainFrame(None, -1, 'WxLibPlot')
    app.MainLoop()


if __name__ == '__main__':
    main()

résultat WxLibPlot1.png

Disposition

Ajouter un titre, une légende et une étiquette de graphique Activer la fonction de zoom ou de glisser Changer la taille de la police, la couleur et l'épaisseur de la ligne

Le zoom et le glissement ne peuvent pas coexister, donc activer l'un désactive l'autre.

Modifiez le code ci-dessous self.plotter = plot.PlotCanvas (self, -1) dans le code ci-dessus comme suit.

python


self.plotter.enableLegend = True  #Définir l'affichage de la légende sur True
self.plotter.fontSizeTitle = 18  #Définissez la taille de police du titre du graphique sur 18.(Défaut=15)
self.plotter.fontSizeLegend = 18  #Définissez la taille de la légende sur 18.(Défaut=7)
self.plotter.fontSizeAxis = 18  #étiquette xy,Définissez la taille des caractères des coordonnées sur 18.(Défaut=10)

#Activez la fonction de zoom ou de glissement. Un seul peut être activé
# self.plotter.enableZoom = True
self.plotter.enableDrag = True

#Créer une ligne à afficher&dessin()
line = plot.PolyLine(xy_val, legend='sample', colour='red', width=4)  #Ajout du texte de la légende, changement de la couleur de la ligne en rouge et de l'épaisseur à 4
gc = plot.PlotGraphics([line], 'WxLibPlot', 'xaxis', 'yaxis')  #Titre du graphique, étiquette xy ajoutée

résultat Le glissement est activé. WxLibPlot2.gif

Dessin en temps réel

Utilisez wx.Timer pour dessiner un graphique linéaire qui prend des valeurs aléatoires toutes les secondes. Cette fois, nous avons ajouté un bouton pour contrôler le début et la fin du tracé.

python


import wx
import wx.lib
import wx.lib.plot as plot
#Utilisé pour le dessin graphique
import random


class MainFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(500, 500))
        #création de panneaux
        self.panel = wx.Panel(self, -1)
        #Bouton pour démarrer et arrêter la mesure
        self.start_button = wx.Button(self, -1, label='start')
        self.stop_button = wx.Button(self, -1, label='stop')
        #création de graphes
        self.plotter = plot.PlotCanvas(self, -1)
        #Valeur initiale du point de tracé
        self.x_val = 0
        self.xy_val = []

        self.plotter.enableLegend = True  #Définir l'affichage de la légende sur True
        self.plotter.fontSizeTitle = 18  #Définissez la taille de police du titre du graphique sur 18.(Défaut=15)
        self.plotter.fontSizeLegend = 18  #Définissez la taille de la légende sur 18.(Défaut=7)
        self.plotter.fontSizeAxis = 18  #étiquette xy,Définissez la taille des caractères des coordonnées sur 18.(Défaut=10)

        #Activez la fonction de zoom ou de glissement. Un seul peut être activé
        # self.plotter.enableZoom = True
        # self.plotter.enableDrag = True

        #Créer une ligne à afficher&dessin()
        line = plot.PolyLine(self.xy_val, legend='sample', colour='red', width=2)  #Ajout du texte de la légende, changement de la couleur de la ligne en rouge et de l'épaisseur à 4
        gc = plot.PlotGraphics([line], 'RealTimePlot', 'xaxis', 'yaxis')  #Titre du graphique, étiquette xy ajoutée
        self.plotter.Draw(gc)

        #Créer un minuteur d'images
        self.timer = wx.Timer(self)

        #création de calibre&Installation
        sizer1 = wx.FlexGridSizer(2, 1, gap=(0, 0))  #Un calibreur pour organiser un graphique et un calibreur 2 par 1
        sizer2 = wx.GridSizer(1, 2, gap=(0, 0))  #Sizer pour organiser les boutons sur 1 ligne et 2 colonnes

        sizer1.Add(self.plotter, flag=wx.EXPAND)  # flag=wx.EXPAND:Étendre la largeur et la hauteur au maximum
        sizer1.Add(sizer2, flag=wx.ALIGN_RIGHT)  # flag=wx.ALIGN_RIGHT:Installé à droite
        sizer1.AddGrowableCol(0)  #Étendre la largeur de la première ligne au maximum
        sizer1.AddGrowableRow(0)  #Étendre la hauteur de la première ligne au maximum
        #Installation des boutons
        sizer2.Add(self.start_button)
        sizer2.Add(self.stop_button)

        self.SetSizer(sizer1)

        #Événements
        self.start_button.Bind(wx.EVT_BUTTON, self.graph_start)
        self.stop_button.Bind(wx.EVT_BUTTON, self.graph_stop)
        self.Bind(wx.EVT_TIMER, self.graph_plot)

        #Afficher l'interface graphique au centre de l'écran
        self.Center()
        self.Show()

    def graph_start(self, event):
        self.plotter.Clear()  #Initialiser le graphique
        self.x_val, self.xy_val = 0, []  # x_val, xy_Initialiser val
        self.timer.Start(1000)

    def graph_stop(self, event):
        self.timer.Stop()

    def graph_plot(self, event):
        y_val = random.randint(0, 100)
        self.xy_val.append((self.x_val, y_val))
        line = plot.PolyLine(self.xy_val, legend='sample', colour='red', width=2)
        gc = plot.PlotGraphics([line], 'RealTimePlot', 'xaxis', 'yaxis')
        self.plotter.Draw(gc)
        self.x_val += 1


def main():
    app = wx.App()
    MainFrame(None, -1, 'WxLibPlot')
    app.MainLoop()


if __name__ == '__main__':
    main()

résultat Après avoir appuyé sur le bouton de démarrage, il devient blanc une fois car le graphique est initialisé. WxLibPlot3.gif

La méthode de dessin change en modifiant l'attribut appelé xSpec

python


 self.plotter.xSpec = 'auto' # or 'min', int, (min, max), 'none'

WxLibPlot4.gif

À partir du haut, ce sera «auto», «min», int, (min, max). «auto» est la valeur par défaut. Si vous attribuez un type entier, le comportement est le même que "min", mais les coordonnées sont fixes. Dans l'exemple ci-dessus, le graphique est divisé en quatre et les coordonnées sont affichées sur la limite.

«aucun» est omis car il n'efface que l'axe des x et l'étiquette.

Affichage de l'axe du temps

C'est la partie que je voulais le plus écrire. Immédiatement, j'écrirai le code et le résultat. L'intervalle de temps est de 1 seconde.

python


import datetime as dt
import random
import wx
import wx.lib
import wx.lib.plot as plot


class TimeAxisPlot(plot.PlotCanvas):
    def __init__(self, parent, id):
        plot.PlotCanvas.__init__(self, parent, id)
        #Définir les relations de mise en page
        self.enableLegend = True
        self.fontSizeLegend = 18
        self.fontSizeAxis = 18
        self.xSpec = 4

        self.startDate = dt.datetime.now()
        self.data = []
        line = plot.PolyLine(self.data, legend='sample', colour='red')
        gc = plot.PlotGraphics([line], 'TimeAxisPlot', 'time', 'yaxis')
        self.Draw(gc)

    def _xticks(self, *args):
        ticks = plot.PlotCanvas._xticks(self, *args)
        # ticks = [(Points de tracé,Caractère à afficher), (),...()]
        new_ticks = []
        for tick in ticks:
            t = tick[0]
            time_value = self.startDate + dt.timedelta(seconds=t)
            time_value_str = time_value.strftime('%H:%M:%S')
            new_ticks.append([t, time_value_str])
            # new_ticks = [(Points de tracé,Heures du jour), (),...()]
            #Changer les caractères affichés en temps
        return new_ticks


class MainFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(500, 500))
        #création de panneaux
        self.panel = wx.Panel(self, -1)
        #Bouton pour démarrer et arrêter la mesure
        self.start_button = wx.Button(self, -1, label='start')
        self.stop_button = wx.Button(self, -1, label='stop')
        #création de graphes
        self.plotter = TimeAxisPlot(self, -1)
        #Valeur initiale du point de tracé
        self.x_val = 0
        self.xy_val = []

        self.plotter.enableLegend = True  #Définir l'affichage de la légende sur True
        self.plotter.fontSizeTitle = 18  #Définissez la taille de police du titre du graphique sur 18.(Défaut=15)
        self.plotter.fontSizeLegend = 18  #Définissez la taille de la légende sur 18.(Défaut=7)
        self.plotter.fontSizeAxis = 18  #étiquette xy,Définissez la taille des caractères des coordonnées sur 18.(Défaut=10)

        #Créer une ligne à afficher&dessin()
        line = plot.PolyLine(self.xy_val, legend='sample', colour='red', width=2)  #Ajout du texte de la légende, changement de la couleur de la ligne en rouge et de l'épaisseur à 4
        gc = plot.PlotGraphics([line], 'RealTimePlot', 'xaxis', 'yaxis')  #Titre du graphique, étiquette xy ajoutée
        self.plotter.Draw(gc)

        #Créer un minuteur d'images
        self.timer = wx.Timer(self)

        #création de calibre&Installation
        sizer1 = wx.FlexGridSizer(2, 1, gap=(0, 0))  #Un calibreur pour organiser un graphique et un calibreur 2 par 1
        sizer2 = wx.GridSizer(1, 2, gap=(0, 0))  #Sizer pour organiser les boutons sur 1 ligne et 2 colonnes

        sizer1.Add(self.plotter, flag=wx.EXPAND)  # flag=wx.EXPAND:Étendre la largeur et la hauteur au maximum
        sizer1.Add(sizer2, flag=wx.ALIGN_RIGHT)  # flag=wx.ALIGN_RIGHT:Installé à droite
        sizer1.AddGrowableCol(0)  #Étendre la largeur de la première ligne au maximum
        sizer1.AddGrowableRow(0)  #Étendre la hauteur de la première ligne au maximum
        #Installation des boutons
        sizer2.Add(self.start_button)
        sizer2.Add(self.stop_button)

        self.SetSizer(sizer1)

        #Événements
        self.start_button.Bind(wx.EVT_BUTTON, self.graph_start)
        self.stop_button.Bind(wx.EVT_BUTTON, self.graph_stop)
        self.Bind(wx.EVT_TIMER, self.graph_plot)

        #Afficher l'interface graphique au centre de l'écran
        self.Center()
        self.Show()

    def graph_start(self, event):
        self.plotter.Clear()  #Initialiser le graphique
        self.x_val, self.xy_val = 0, []  # x_val, xy_Initialiser val
        self.timer.Start(1000)

    def graph_stop(self, event):
        self.timer.Stop()

    def graph_plot(self, event):
        y_val = random.randint(0, 100)
        self.xy_val.append((self.x_val, y_val))
        line = plot.PolyLine(self.xy_val, legend='sample', colour='red', width=2)
        gc = plot.PlotGraphics([line], 'RealTimePlot', 'xaxis', 'yaxis')
        self.plotter.Draw(gc)
        self.x_val += 1


def main():
    app = wx.App()
    MainFrame(None, -1, 'TimeAxisPlot')
    app.MainLoop()


if __name__ == '__main__':
    main()

résultat WxLibPlot5.gif

Inherit plot.Canvas pour créer une nouvelle classe, en remplaçant la méthode des coordonnées de l'axe x. ici,

python


    def _xticks(self, *args):
        ticks = plot.PlotCanvas._xticks(self, *args)
        # ex)ticks = [(0, '0.0'), (0.5, '0.5'), (1.0, '1.0'), (1.5, '1.5'), (2.0, '2.0')]
        # [(coordonnée x(float)), (coordonnée xに表示する文字(str))...]

ticks renvoie [(coordonnée x (flottant)), (caractère à afficher à la coordonnée x (str)) ...]. L'axe du temps est créé en remplaçant les caractères affichés par l'heure.

Méthode Créez un tuple de coordonnées et d'heure et ajoutez à la liste vide new_ticks ex) Heure de début: 0:00, ticks = [(0, '0.0'), (0.5, '0.5'), (1.0, '1.0'), (1.5, '1.5'), (2.0, '2.0' )]temps

pour la première phrase

  1. tick = (0, '0.0')
  2. t = 0
  3. Créez une date à t secondes de l'heure de début et transformez-la en str (= 00:00)
  4. ajouter (0, '00: 00 ') à new_ticks La boucle suivante

python


        new_ticks = []
        for tick in ticks:  #Boucle avec les tiques acquises
            #0e taple(x points de coordonnées)Avoir
            t = tick[0]
            time_value = self.startDate + dt.timedelta(seconds=t)
            time_value_str = time_value.strftime('%H:%M:%S')
            new_ticks.append([t, time_value_str])
            # new_ticks = [(Points de tracé,Heures du jour), (),...()]
            #Changer les caractères affichés en temps
        return new_ticks

finalement

Merci pour la lecture. Comme je l'ai remarqué lors de l'exécution, la vitesse de dessin la plus rapide était d'environ 0,05 s. Notez que la vitesse d'exécution n'a pas changé même si l'intervalle du minuteur était plus court que cela.

Site de référence

officiel wx.lib.plot — wxPython Phoenix 4.1.1a1 documentation

Référence pour le dessin en temps réel wxPython: dessin simultané d'animation et de dessin graphique

Référence de l'axe des temps [Note] Personnalisez l'échelle de l'axe y du tracé ─ wxPython wxPython-users - wx.lib.plot custom labels?

Recommended Posts

[wxpython] Comment utiliser l'axe de base et du temps de wx.lib.plot
Comment utiliser le bloc-notes Jupyter [super basique]
Comment utiliser xml.etree.ElementTree
Comment utiliser Python-shell
Remarques sur l'utilisation de tf.data
Comment utiliser virtualenv
Comment utiliser MkDocs pour la première fois
Comment utiliser Seaboan
Comment utiliser la correspondance d'image
Comment utiliser le shogun
Comment implémenter le traitement du temps d'attente avec wxpython
Comment utiliser Virtualenv
Comment utiliser numpy.vectorize
Comment utiliser pytest_report_header
Comment utiliser partiel
Comment utiliser Bio.Phylo
Comment utiliser SymPy
Comment utiliser x-means
Comment utiliser WikiExtractor.py
Comment utiliser virtualenv
Comment utiliser Matplotlib
Comment utiliser iptables
Comment utiliser numpy
Comment utiliser TokyoTechFes2015
Comment utiliser venv
Comment utiliser Pyenv
Comment utiliser la liste []
Comment utiliser python-kabusapi
Comment utiliser OptParse
Comment utiliser le retour
Comment utiliser pyenv-virtualenv
Comment utiliser imutils
Débutants! Commandes et utilisation de base de Linux!
Comment utiliser Qt Designer
Comment utiliser la recherche triée
python3: Comment utiliser la bouteille (2)
Comprendre comment utiliser django-filter
Comment utiliser le générateur
Comment utiliser FastAPI ③ OpenAPI
Comment utiliser Python Argparse
Comment utiliser IPython Notebook
Comment utiliser Pandas Rolling
[Note] Comment utiliser virtualenv
Comment utiliser les dictionnaires redis-py
[Python] Comment utiliser checkio
[Aller] Comment utiliser "... (3 périodes)"
[Python] Comment utiliser input ()
Comment utiliser le décorateur
[Introduction] Comment utiliser open3d
Comment utiliser Python lambda
Comment utiliser Jupyter Notebook
[Python] Comment utiliser virtualenv
python3: Comment utiliser la bouteille (3)
python3: Comment utiliser la bouteille
Comment augmenter l'axe
Comment utiliser Google Colaboratory
Comment utiliser les octets Python
Comment utiliser la fonction zip