IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PyQt Python Discussion :

Déplacement d'une fenêtre QWidget.


Sujet :

PyQt Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2016
    Messages : 13
    Points : 7
    Points
    7
    Par défaut Déplacement d'une fenêtre QWidget.
    Bonjour à tous,

    je butte sur un sujet que je n'arrive pas à résoudre en Python 3.5 et PyQt5: Comment faire glisser une fenêtre indépendante d'un coin de l'écran à l'autre de manière fluide.
    La bibliothèque QT étant très riche en fonctionnalités, je ne sait pas trop sûr de la direction dans laquelle partir.

    Dois-je utiliser les classes QStateMachine, QState, QParallelAnimationGroup et autres transitions ?

    Cordialement,
    Pingoo

  2. #2
    Membre éclairé
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 513
    Points : 700
    Points
    700
    Par défaut
    Bonjour,
    Alors je ne suis pas sûr d'avoir compris la question, personnellement je n'est jamais remarqué de problème de fluidité avec les QMainWindow ou QDialog

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2016
    Messages : 13
    Points : 7
    Points
    7
    Par défaut
    Pardon, je n'ai sûrement pas donné assez de détail sur ce que je souhaite faire.
    Le "glissement" en question, il s'agirait d'une animation automatique, sans intervention extérieure.
    Donc, concrètement, je voudrais faire déplacer une fenêtre (QWidget) d'un point A de l’écran à un point B par programmation, et que ce soit fait de manière fluide et progressive (une animation de 2 à 3 secondes).

  4. #4
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Tu peux essayer quelque chose comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    # -*- coding: utf-8 -*-
     
    import time
     
    from PyQt5 import QtCore, QtGui, QtWidgets
     
    class Ui_Dialog(object):
        def setupUi(self, Dialog):
            Dialog.setGeometry(500, 60, 214, 70)
            self.gridLayout = QtWidgets.QGridLayout(Dialog)
            self.horizontalLayout = QtWidgets.QHBoxLayout()
            self.left_btn = QtWidgets.QPushButton(Dialog)
            self.left_btn.setText("Left")
            self.horizontalLayout.addWidget(self.left_btn)
            self.right_btn = QtWidgets.QPushButton(Dialog)
            self.right_btn.setText("Right")
            self.horizontalLayout.addWidget(self.right_btn)
            self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
     
            self.screen_width = self.get_main_screen_width()
            self.right_btn.clicked.connect(self.move_to_right)
            self.left_btn.clicked.connect(self.move_to_left)
            self.dial = Dialog
     
        def get_main_screen_width(self):
            size = QtWidgets.QDesktopWidget().availableGeometry(-1)
            return size.width()
     
        def move_to_right(self):
            g = self.dial.geometry()
            delta = self.screen_width - g.x() - g.width()
            for i in range(int(delta/10)):
                self.dial.setGeometry(g.x()+i*10, g.y(), g.width(), g.height())
                time.sleep(0.05)
     
        def move_to_left(self):
            g = self.dial.geometry()
            delta = self.screen_width - g.x()
            for i in range(int(delta/10)):
                self.dial.setGeometry(g.x()-i*10, g.y(), g.width(), g.height())
                time.sleep(0.05)
     
    if __name__ == "__main__":
        import sys
        app = QtWidgets.QApplication(sys.argv)
        Dialog = QtWidgets.QDialog()
        ui = Ui_Dialog()
        ui.setupUi(Dialog)
        Dialog.show()
        sys.exit(app.exec_())
    Il faut ajuster la valeur de déplacement, personnellement je trouve ça un peu saccadé.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2016
    Messages : 13
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par VinsS Voir le message
    [...]personnellement je trouve ça un peu saccadé.
    Merci pour ta réponse, VinsS, mais cette technique sera toujours saccadée dans la mesure où le time.sleep() provoque un blocage du code.
    Je cherche plutôt à utiliser le framework d'animation de QT pour gérer une vraie animation.

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2016
    Messages : 13
    Points : 7
    Points
    7
    Par défaut
    Voici ce que j'ai trouvé qui fonctionne plutôt pas mal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            self.setGeometry(0, 0, 200, 200) # paramètre la fenêtre de 200x200 en haut à gauche de l'écran
     
            self.anim = QPropertyAnimation(self, b'pos') # Créé une animation basée sur les propriétés des objets Qt (Qt Properties), ici l'objet courant et basée sur la position
            self.anim.setDuration(3000) # paramètre de durée de l'animation, ici 3s
            self.anim.setStartValue(self.pos()) # point de départ de l'animation, ici la position courante de l’objet
            self.anim.setEndValue(QPointF(500, 500)) # point d'arrivée de l'animation
            self.anim.start()
    Voila, en fait, c'est tout con et comme c'est natif ça fonctionne très bien

  7. #7
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Ça ne semble pas être applicable aux fenêtre mais seulement aux widgets et aux objets de la famille QGraphicsItem

    Tu peux essayer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        def move_to_right(self):
            g = self.dial.geometry()
            anim = QtCore.QPropertyAnimation(self.dial, b"geometry")
            anim.setDuration(2000)
            anim.setStartValue(g)
            anim.setEndValue(QtCore.QRect(self.screen_width - g.width(), 60, 214, 70))
            anim.start()
    Si tu remplaces self.dial par un des deux boutons tu le verras disparaître mais la fenêtre ne bouge pas.

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2016
    Messages : 13
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Ça ne semble pas être applicable aux fenêtre mais seulement aux widgets et aux objets de la famille QGraphicsItem
    Faux, cela s'applique à tous les dérivés de QObject, dixit la doc officielle de QT5 dont le lien est dans le post #5. Et les fenêtres en QT héritent de QWidget qui hérite lui-même de QObject, il me semble.

    Maintenant, j'ai posté ce code car je l'ai testé sur une fenêtre, vu que c'est ce que je cherche à faire. Ça fonctionne même aussi bien en ouvrant plusieurs fenêtres qui s'animent toutes de manière fluide.
    Bonjour le scepticisme

  9. #9
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Ce n'est pas du scepticisme, c'est le résultat d'un test, ça ne fonctionne absolument pas sur ma machine, sans message d'erreur.

    Par contre ceci fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
        def move(self, value):
            g = self.dial.geometry()
            x = g.x() + self.step
            self.dial.setGeometry(QtCore.QRect(x, g.y(), g.width(), g.height()))
     
        def move_to_right(self):
            g = self.dial.geometry()
            delta = self.screen_width - g.x() - g.width()
            self.step = delta / 100
            tl = QtCore.QTimeLine(5000, self.dial)
            tl.setFrameRange(0, 100)
            tl.frameChanged.connect(self.move)
            tl.start()
     
        def move_to_left(self):
            g = self.dial.geometry()
            self.step = -g.x() / 100
            tl = QtCore.QTimeLine(5000, self.dial)
            tl.setFrameRange(0, 100)
            tl.frameChanged.connect(self.move)
            tl.start()

  10. #10
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour VinsS,

    Je confirme que ça marche. Je viens d'essayer avec une simple fenêtre QWidget et un bouton qui lance l'animation.

    Dans la méthode lancée par ce bouton, j'ai mis:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            self.anim = QtCore.QPropertyAnimation(self, b'geometry')
            self.anim.setDuration(3000)
            self.anim.setStartValue(QtCore.QRect(100, 100, 300, 200))
            self.anim.setEndValue(QtCore.QRect(300, 300, 300, 200))
            self.anim.start()
    Et si on remplace la ligne du setStartValue par "self.anim.setStartValue(self.geometry())", on part de la position courante de la fenêtre quelle qu’elle soit.

    Ma fenêtre fait 300x200 pixels, et elle va bien de [100,100] à [300,300] en glissant pendant 3s. On peut aussi faire varier sa dimension et pas seulement sa position.

    Il y a d'ailleurs des exemples du même genre sur le web: http://zetcode.com/pyqt/qpropertyanimation/

    Merci à Pingoo0!
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VB6] [Système] Récupérer le contenu d'une fenêtre DOS
    Par Nounours666 dans le forum VB 6 et antérieur
    Réponses: 16
    Dernier message: 18/11/2004, 16h38
  2. [MDI] Ouvrir immédiatement une fenetre fille
    Par phil56 dans le forum C++Builder
    Réponses: 8
    Dernier message: 12/03/2003, 14h27
  3. [VB6] Dimension d'une fenetre extérieure
    Par Ingham dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 22/01/2003, 16h52
  4. Aide sur une fenetre
    Par Ray-j dans le forum Autres éditeurs
    Réponses: 4
    Dernier message: 29/11/2002, 08h51
  5. gérer les jpg dans une fenetre directdraw???
    Par Anonymous dans le forum DirectX
    Réponses: 1
    Dernier message: 14/06/2002, 13h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo