Comment implémenter le traitement du temps d'attente avec wxpython

introduction

La première fois que j'ai essayé d'écrire un processus d'attente avec wxpython

  1. Essayez d'attendre un moment avec time.sleep ()
  2. L'écran ne répond plus et la cause est recherchée.
  3. Prise en charge avec wx.Timer et Thread

Je pense que vous suivrez le chemin. (N'est-ce pas?) J'ai noté ce processus d'attente car je l'utilise assez souvent.

Honnêtement, ce contenu est partout, alors j'espère que vous pourrez le voir dans l'un des articles de référence.

Cause de l'erreur time.sleep ()

En gros, la cause est que la boucle principale exécutée derrière l'interface graphique s'arrête en mode veille.

environnement

Mac OS wxpython 4.1.0

importer

Installez wxpython

python


pip install wxpython

le filetage peut être utilisé sans installation. Non utilisé lors de l'utilisation de wx.Timer, mais à la place du temps.

python


import wx
import threading
import time

Méthode 1 wx.Timer

Ceci est efficace lorsque le traitement est effectué à intervalles réguliers. Est-ce le plus simple à utiliser pour mettre à jour l'heure actuelle? WxTimer1.gif

python


import wx
import threading  #Non utilisé cette fois
import time  #Non utilisé cette fois
#Utilisé pour l'affichage de l'heure
import datetime as dt


class MainFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(400, 200))

        #Création d'instance TimerPanel
        self.panel = TimerPanel(self, -1)

        #Affichage avec l'écran centré
        self.Center()
        self.Show()


class TimerPanel(wx.Panel):
    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent, id)

        #Créer une chaîne de l'heure actuelle, self.clock_création txt,Temps d'affichage
        now = dt.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
        self.clock_txt = wx.StaticText(self, -1, label=now)

        #Paramètres de police,Après avoir changé la taille à 20 auto.clock_Reflété dans txt
        font = wx.Font(20, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
        self.clock_txt.SetFont(font)

        #Créer un calibreur, self.clock_Ajouter txt au sizer,Appliquer le calibreur au panneau
        sizer = wx.GridSizer(1, 1, gap=(0, 0))
        sizer.Add(self.clock_txt, flag=wx.ALIGN_CENTRE)  # ALIGN_CENTRE: Installé au centre du calibreur
        self.SetSizer(sizer)

        self.timer = wx.Timer(self)  #Créer une minuterie dans le panneau
        self.Bind(wx.EVT_TIMER, self.clock)  #Auto à intervalles spécifiés.Horloge de course
        self.timer.Start(1000)  #Minuterie de 1000 ms(=1s)Prêt à démarrer
        # self.timer.Stop()  #Si vous souhaitez arrêter le chronomètre


    def clock(self, event):
        #Obtenez l'heure actuelle et vous-même.clock_Définir dans txt
        now = dt.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
        self.clock_txt.SetLabel(now)
        self.Refresh()


if __name__ == '__main__':
    app = wx.App()
    MainFrame(None, -1, 'TimeEvent')
    app.MainLoop()

Créez une minuterie avec le cadre ou le panneau comme parent, définissez l'intervalle et commencez. Plusieurs minuteries peuvent être exécutées en même temps.

WxTimer2.gif

Le gif ci-dessus a deux panneaux, chacun affichant l'heure avec une minuterie.

Le panneau supérieur dure 1 seconde et le bas 2 secondes.

Méthode 2 Filetage de traitement parallèle.

wx.Timer utilise threading.Thread pour un traitement difficile à implémenter. Cette fonction peut créer un autre thread et exécuter plusieurs processus en même temps. Vous ne devez pas utiliser time.sleep () dans le thread où l'interface graphique est exécutée, mais il n'y a aucun problème dans un autre thread.

Voici le processus que je trouve difficile avec wx.Timer --Exécution périodique (ex: signal) dont l'intervalle d'attente n'est pas le même --Traitement qui change d'état avec le temps -> Il est gênant de faire une branche conditionnelle à chaque fois lors d'une exécution régulière (ex: signal)

En d'autres termes, utilisez threadind.Thred lorsque vous faites un feu de signalisation (n'est-ce pas trop limité?)

WxThread1.gif

Le bleu, le jaune et le rouge sont affichés pendant 4, 1 et 5 secondes chacun.

python


import wx
import time
import threading


class TrafficLight(threading.Thread):
    def __init__(self, panel):
        super().__init__()
        self.panel = panel
        #Démonisez le sous-thread, s'il n'est pas défini sur True, le sous-thread continuera à s'exécuter même si l'écran est fermé.
        self.setDaemon(True)

    def run(self):
        while True:
            #Panneau jaune->noir,Panneau rouge->rouge
            self.panel.yellow_panel.SetBackgroundColour('#000000')
            self.panel.red_panel.SetBackgroundColour('#ff0000')
            self.panel.Refresh()
            time.sleep(5)

            #Panneau rouge->noir,Panneau bleu->Bleu
            self.panel.red_panel.SetBackgroundColour('#000000')
            self.panel.blue_panel.SetBackgroundColour('#00ff00')
            self.panel.Refresh()
            time.sleep(4)

            #Panneau bleu->noir,Panneau jaune->Jaune
            self.panel.blue_panel.SetBackgroundColour('#000000')
            self.panel.yellow_panel.SetBackgroundColour('#ffff00')
            self.panel.Refresh()
            time.sleep(1)


class MainFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(600, 200))

        self.main_panel = MainPanel(self, -1)
        
        #Afficher l'écran au centre
        self.Center()
        self.Show()


class MainPanel(wx.Panel):
    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent, id)
        
        #Panneau bleu, couleur spécifiée comme noir
        self.blue_panel = wx.Panel(self, -1)
        self.blue_panel.SetBackgroundColour('#000000')
        
        #Panneau jaune, couleur spécifiée comme noir
        self.yellow_panel = wx.Panel(self, -1)
        self.yellow_panel.SetBackgroundColour('#000000')

        #Panneau rouge, couleur spécifiée comme noir
        self.red_panel = wx.Panel(self, -1)
        self.red_panel.SetBackgroundColour('#000000')
        
        #Bouton Start
        self.button = wx.Button(self, -1, 'start')
        
        #Mise en page liée
        sizer1 = wx.FlexGridSizer(2, 1, gap=(0, 0))
        sizer2 = wx.GridSizer(1, 3, gap=(0, 0))

        sizer1.Add(sizer2, flag=wx.EXPAND)
        sizer1.Add(self.button, flag=wx.ALIGN_RIGHT)
        sizer1.AddGrowableCol(0)
        sizer1.AddGrowableRow(0)

        sizer2.Add(self.blue_panel, flag=wx.EXPAND)
        sizer2.Add(self.yellow_panel, flag=wx.EXPAND)
        sizer2.Add(self.red_panel, flag=wx.EXPAND)
        self.SetSizer(sizer1)
        
        #Création d'instances de sous-threads, auto-argument
        self.traffic_light = TrafficLight(self)
        
        #Événement de bouton
        self.button.Bind(wx.EVT_BUTTON, self.start)

    def start(self, event):
        #Création d'instances de sous-threads, auto-argument
        traffic_light = TrafficLight(self)
        #L'opération de sous-thread a commencé
        traffic_light.start()
        self.start_button.Disable()  #Bouton désactiver,Empêcher la création de plusieurs threads

if __name__ == "__main__":
    app = wx.App()
    MainFrame(None, -1, "feu de circulation")
    app.MainLoop()

Remplacement de la méthode d'exécution de threading.Thread. Seul self peut être passé à la méthode run. Les attributs requis sont transmis lors de la création de l'instance. De plus, comme il ne peut être exécuté qu'une seule fois par thread, il est instancié lorsque le bouton est enfoncé.

Terminer le fil à tout moment

Le feu de signalisation ci-dessus ne peut pas être arrêté car il se déplace alors que True. Mais je veux pouvoir l'arrêter. Par conséquent, réécrivez la classe TrafficLight et ajoutez des variables et des fonctions globales.

L'interface graphique a ajouté un bouton d'arrêt. Lorsque le bouton d'arrêt est enfoncé, thread_stop_flag devient True et l'opération de thread se termine.

WxThread

python


import wx
import time
import threading

thread_stop_flag = False


def wait_time(seconds):
    """
Arrêtez pendant le temps d'attente écoulé_Attendez en regardant le drapeau
    stop_Quitte l'instruction while lorsque l'indicateur est True
    :param seconds: int
Temps d'attente
    :return: None
    """
    wait_start = time.time()
    while time.time() - wait_start <= seconds:
        if not thread_stop_flag:
            time.sleep(1)
        else:
            break


class TrafficLight(threading.Thread):
    def __init__(self, panel):
        super().__init__()
        self.panel = panel
        #Démonisez le sous-thread, s'il n'est pas défini sur True, le sous-thread continuera à s'exécuter même si l'écran est fermé.
        self.setDaemon(True)

    def run(self):
        while not thread_stop_flag:  #Changement 2
            #Panneau jaune->noir,Panneau rouge->rouge
            self.panel.yellow_panel.SetBackgroundColour('#000000')
            self.panel.red_panel.SetBackgroundColour('#ff0000')
            self.panel.Refresh()
            wait_time(5)

            #Panneau rouge->noir,Panneau bleu->Bleu
            self.panel.red_panel.SetBackgroundColour('#000000')
            self.panel.blue_panel.SetBackgroundColour('#00ff00')
            self.panel.Refresh()
            wait_time(4)

            #Panneau bleu->noir,Panneau jaune->Jaune
            self.panel.blue_panel.SetBackgroundColour('#000000')
            self.panel.yellow_panel.SetBackgroundColour('#ffff00')
            self.panel.Refresh()
            wait_time(1)

        #Changement 3,Tout remettre en noir
        self.panel.blue_panel.SetBackgroundColour('#000000')
        self.panel.yellow_panel.SetBackgroundColour('#000000')
        self.panel.red_panel.SetBackgroundColour('#000000')
        self.panel.Refresh()


class MainFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(600, 200))

        self.main_panel = MainPanel(self, -1)

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


class MainPanel(wx.Panel):
    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent, id)

        #Panneau bleu, couleur spécifiée comme noir
        self.blue_panel = wx.Panel(self, -1)
        self.blue_panel.SetBackgroundColour('#000000')

        #Panneau jaune, couleur spécifiée comme noir
        self.yellow_panel = wx.Panel(self, -1)
        self.yellow_panel.SetBackgroundColour('#000000')

        #Panneau rouge, couleur spécifiée comme noir
        self.red_panel = wx.Panel(self, -1)
        self.red_panel.SetBackgroundColour('#000000')

        #début,Bouton d'arrêt
        self.start_button = wx.Button(self, -1, 'start')
        self.stop_button = wx.Button(self, -1, 'stop')

        #Mise en page liée
        sizer1 = wx.FlexGridSizer(2, 1, gap=(0, 0))
        sizer2 = wx.GridSizer(1, 3, gap=(0, 0))
        sizer3 = wx.GridSizer(1, 2, gap=(0, 0))

        sizer1.Add(sizer2, flag=wx.EXPAND)
        sizer1.Add(sizer3, flag=wx.ALIGN_RIGHT)
        sizer1.AddGrowableCol(0)
        sizer1.AddGrowableRow(0)

        sizer2.Add(self.blue_panel, flag=wx.EXPAND)
        sizer2.Add(self.yellow_panel, flag=wx.EXPAND)
        sizer2.Add(self.red_panel, flag=wx.EXPAND)

        sizer3.Add(self.start_button)
        sizer3.Add(self.stop_button)
        self.SetSizer(sizer1)

        #Événement de bouton
        self.start_button.Bind(wx.EVT_BUTTON, self.start)
        self.stop_button.Bind(wx.EVT_BUTTON, self.stop)

    def start(self, event):
        global thread_stop_flag
        thread_stop_flag = False
        #Création d'instances de sous-threads, auto-argument
        traffic_light = TrafficLight(self)
        #L'opération de sous-thread a commencé
        traffic_light.start()
        self.start_button.Disable()  #Empêche la création de plusieurs threads d'invalidation de bouton

    def stop(self, event):
        #Fil de variable global_stop_flag à True=Définissez la condition de l'instruction while du thread sur False
        global thread_stop_flag
        thread_stop_flag = True
        self.start_button.Enable()


if __name__ == "__main__":
    app = wx.App()
    MainFrame(None, -1, "feu de circulation")
    app.MainLoop()

Ce n'est pas un gros problème, mais ça fait longtemps. S'il vous plaît laissez-moi savoir s'il existe une autre bonne façon d'écrire ...

À la fin

Merci pour la lecture. Naturellement, la méthode utilisant le filetage a d'autres utilisations que les feux de signalisation. Par exemple, lorsque vous souhaitez exécuter une série d'opérations une seule fois au lieu d'une exécution périodique. Je l'utilise pour les paramètres initiaux de l'appareil.

Article de référence

Je me réfère aux articles suivants.

Cause d'erreur Python-je suis un débutant. Après avoir inséré l'instruction de veille, l'application a cessé de fonctionner correctement. | teratail

Rupture de fil Votre threading.Event est mal utilisé-Qiita

Recommended Posts

Comment implémenter le traitement du temps d'attente avec wxpython
Comment faire un traitement parallèle multicœur avec python
Comment mesurer le temps d'exécution avec Python Partie 1
[wxpython] Comment utiliser l'axe de base et du temps de wx.lib.plot
Comment mesurer le temps d'exécution avec Python, partie 2
Comment mesurer le temps de traitement avec Python ou Java
Comment mesurer le temps de lecture d'un fichier mp3 avec python
Comment mettre à jour avec SQLAlchemy?
Comment lancer avec Theano
Comment modifier avec SQLAlchemy?
Comment séparer les chaînes avec ','
Comment faire RDP sur Fedora31
Comment supprimer avec SQLAlchemy?
Comment annuler RT avec Tweepy
Python: comment utiliser async avec
Pour utiliser virtualenv avec PowerShell
Comment installer python-pip avec ubuntu20.04LTS
Comment gérer les données déséquilibrées
Comment démarrer avec Scrapy
Comment démarrer avec Python
Comment gérer l'erreur DistributionNotFound
Comment démarrer avec Django
Comment augmenter les données avec PyTorch
Comment calculer la date avec python
Comment installer mysql-connector avec pip3
Comment INNER JOIN avec SQL Alchemy
Comment installer Anaconda avec pyenv
Comment extraire des fonctionnalités de données de séries chronologiques avec les bases de PySpark
Résumez comment prétraiter le texte (traitement du langage naturel) avec l'api tf.data.Dataset
Comment écrire hors ligne en temps réel Résolution des problèmes F01 avec Python
Comment calculer "xx time" en un seul coup avec Python Timedelta
Comment effectuer un traitement arithmétique avec le modèle Django
[Blender] Comment définir shape_key avec un script
Comment titrer plusieurs figures avec matplotlib
Comment obtenir l'identifiant du parent avec sqlalchemy
Comment comparer des données de séries chronologiques - Dérivée DTW, DTW-
Comment ajouter un package avec PyCharm
Comment régler l'heure du serveur sur l'heure japonaise
Comment installer DLIB avec 2020 / CUDA activé
Comment écrire hors ligne en temps réel J'ai essayé de résoudre E11 avec python
Comment utiliser ManyToManyField avec l'administrateur de Django
Comment utiliser OpenVPN avec Ubuntu 18.04.3 LTS
Comment utiliser Cmder avec PyCharm (Windows)
Comment obtenir la différence de date et d'heure en secondes avec Python
Comment empêcher les mises à jour de paquets avec apt
Comment utiliser BigQuery en Python
Comment utiliser Ass / Alembic avec HtoA
Comment gérer les erreurs de compatibilité d'énumération
Comment utiliser le japonais avec le tracé NLTK
Comment faire un test de sac avec python
Comment rechercher Google Drive dans Google Colaboratory
Comment afficher le japonais python avec lolipop
Comment télécharger des vidéos YouTube avec youtube-dl
Comment utiliser le notebook Jupyter avec ABCI
Comment mettre hors tension de Linux sur Ultra96-V2