Partage
  • Partager sur Facebook
  • Partager sur Twitter

Modifier et déplacer une ligne QGraphicsLineItem

relier deux éléments par une droite

    24 octobre 2023 à 23:58:58

    Bonsoir,

    Je demande votre aide car actuellement je suis sur un cas difficile (pour moi)
    j'ai un code dans lequel je crée des élément qui sont sous la forme d'un rectangle associé à deux petits cercles au milieu en haut et en bas du rectangle.
    pour chacun des éléments je veux pouvoir relier les cercles par une droite, en gros:

    1) je clique sur un des cercle de l'élément et une droite se crée tel que la première extrémité de la droite est attaché au cercle et la deuxième extrémité est attaché à la souris.
    2) je bouge la souris en direction d'un des cercle de l'élément 2, donc la souris est dynamique, donc la droite est aussi dynamique (sa longueur, son orientation, etc .....)
    3) je clique sur l'un des cercle du deuxième élément, donc la deuxième extrémité de la droite est rattaché au cercle du deuxième élément.
    4) je peut bouger l'un des deux élément lié, la droite change de dimension et d'orientation en fonction de mon mouvement.

    j'ai déjà un commencement de code mais il ne fonctionne pas. La droite n'apparait pas donc rien ne se lie.

    import sys
    import os
    from PyQt5.QtWidgets import QApplication, QComboBox, QMainWindow, QToolBar, QToolButton, QLabel, QGraphicsEllipseItem, QGraphicsScene, QGraphicsView, QGraphicsRectItem, QGraphicsTextItem, QInputDialog
    from PyQt5.QtCore import Qt, QPoint, QCoreApplication 
    from PyQt5.QtGui import QIcon, QPen, QBrush, QCursor, QTransform
    
    
    
    class App(QMainWindow):
    
        def __init__(self):
            super().__init__()
            self.setMouseTracking(True)
            self.title = 'Glisser-Deposer'
            self.left = 10
            self.top = 40
            self.width = 640
            self.height = 480
            self.drawing_line = None
            self.start_circle = None
            self.initUI()
    
        def initUI(self):
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
    
            # Créez un QToolBar
            self.toolbar = QToolBar(self)
            self.addToolBar(Qt.LeftToolBarArea, self.toolbar)
    
        
            
            # Catégorie "Construction"
            constructionLabel = QLabel("Construction")      
            self.toolbar.addWidget(constructionLabel)
            groupeButton = QToolButton(self)
            groupeButton.setText("Groupe")
            groupeButton.clicked.connect(self.showConstantDialogForGroupe)
            self.toolbar.addWidget(groupeButton)
    
            
            # Catégorie "Analyse"
            analyseLabel = QLabel("Analyse")
            self.toolbar.addWidget(analyseLabel)
            
            self.indisComboBox = QComboBox(self)
            self.indisComboBox.addItems(["indis", "MAma", "Rfr", "Sssd"])  # Ajoutez une option vide au début pour la valeur par défaut
            self.indisComboBox.activated.connect(self.showConstantDialogForIndis)
            self.toolbar.addWidget(self.indisComboBox)
    
            # Zone de travail principale
            self.scene = QGraphicsScene()
            self.view = QGraphicsView(self.scene, self)
            self.setCentralWidget(self.view)
    
            self.show() 
            
                
        def showConstantDialogForGroupe(self):
            constant, ok = QInputDialog.getInt(self, 'Modifier les constantes', 'Entrez la constante pour Groupe:')
            if ok:
                # Obtenez la position actuelle du curseur
                cursor_pos = self.mapFromGlobal(QCursor.pos())
                x, y = cursor_pos.x(), cursor_pos.y()
    
                # Créez l'élément graphique à la position du curseur
                item = QGraphicsRectItem(x, y, 100, 40)  # Créez un rectangle de taille 100x40 pour avoir de l'espace pour le texte
                item.setBrush(QBrush(Qt.blue))  # Définissez la couleur à bleu
                item.setFlag(QGraphicsRectItem.ItemIsMovable)  # Rendez l'élément déplaçable
                
                # Utilisez la sous-classe HoverableEllipse pour créer les cercles
                top_circle = HoverableEllipse(x + 45, y - 10, 10, 10, item)  # Le dernier argument "item" lie le cercle au rectangle
                bottom_circle = HoverableEllipse(x + 45, y + 40, 10, 10, item)
                
                # Créez les cercles au-dessus et en dessous du rectangle
                top_circle = QGraphicsEllipseItem(x + 45, y - 10, 10, 10, item)  # Le dernier argument "rect" lie le cercle au rectangle
                top_circle.setAcceptHoverEvents(True)  # Activez le suivi de la souris pour le cercle supérieur
                bottom_circle = QGraphicsEllipseItem(x + 45, y + 40, 10, 10, item)
                bottom_circle.setAcceptHoverEvents(True)  # Activez le suivi de la souris pour le cercle inférieur
    
                # Ajoutez le nom "Groupe" à l'intérieur du rectangle
                text = QGraphicsTextItem("Groupe", item)  # Associez le texte à l'élément rectangulaire
                text.setDefaultTextColor(Qt.white)  # Définissez la couleur du texte à blanc
                text.setPos(x + 10, y + 10)  # Positionnez le texte à l'intérieur du rectangle
                
                # Ajoutez le groupe (rectangle + cercles) à la scène
                self.scene.addItem(item)
                      
        def showConstantDialogForIndis(self, index):
            if index == 0:  # Si l'option vide est sélectionnée, ne faites rien
                return
            indir = self.indisComboBox.currentText()
            constant, ok = QInputDialog.getInt(self, 'Modifier les constantes', f'Entrez la constante pour {indir}:')
            if ok:
                # Obtenez la position actuelle du curseur
                cursor_pos = self.mapFromGlobal(QCursor.pos())
                x, y = cursor_pos.x(), cursor_pos.y()
        
                # Créez le rectangle à la position du curseur
                item = QGraphicsRectItem(x, y, 100, 40)
                item.setBrush(QBrush(Qt.blue))
                item.setFlag(QGraphicsRectItem.ItemIsMovable)
                
                # Utilisez la sous-classe HoverableEllipse pour créer les cercles
                top_circle = HoverableEllipse(x + 45, y - 10, 10, 10, item)  # Le dernier argument "item" lie le cercle au rectangle
                bottom_circle = HoverableEllipse(x + 45, y + 40, 10, 10, item)
            
                # Créez les cercles au-dessus et en dessous du rectangle
                top_circle = QGraphicsEllipseItem(x + 45, y - 10, 10, 10, item)  # Le dernier argument "rect" lie le cercle au rectangle
                top_circle.setAcceptHoverEvents(True)  # Activez le suivi de la souris pour le cercle supérieur
                bottom_circle = QGraphicsEllipseItem(x + 45, y + 40, 10, 10, item)
                bottom_circle.setAcceptHoverEvents(True)  # Activez le suivi de la souris pour le cercle inférieur
            
                # Ajoutez le nom de l'indicateur à l'intérieur du rectangle
                text = QGraphicsTextItem(indir, item)
                text.setDefaultTextColor(Qt.white)
                text.setPos(x + 10, y + 10)
            
                # Ajoutez le groupe (rectangle + cercles) à la scène
                self.scene.addItem(item)
            
            # Réinitialisez la valeur du QComboBox
            self.indisComboBox.setCurrentIndex(0)
        
        def mousePressEvent(self, event):
            print("mousePressEvent appelé")
            # Détectez si le clic est sur un cercle
            item = self.scene.itemAt(event.pos(), QTransform())
            print(type(item))
            if isinstance(item, QGraphicsEllipseItem):
                if not self.drawing_line:
                    # Commencez à dessiner une ligne à partir de ce cercle
                    start_point = item.scenePos()
                    self.drawing_line = QGraphicsLineItem(start_point.x(), start_point.y(), start_point.x(), start_point.y())
                    self.scene.addItem(self.drawing_line)
                    self.start_circle = item
                else:
                    # Terminez le dessin de la ligne en cliquant sur un autre cercle
                    end_point = item.scenePos()
                    self.drawing_line.setLine(self.start_circle.scenePos().x(), self.start_circle.scenePos().y(), end_point.x(), end_point.y())
                    self.drawing_line = None
                    self.start_circle = None
    
        def mouseMoveEvent(self, event):
            print("mouseMoveEvent appelé")
            super().mouseMoveEvent(event)
            if self.drawing_line:
                line = self.drawing_line.line()
                self.drawing_line.setLine(line.x1(), line.y1(), event.pos().x(), event.pos().y())
    
        def closeEvent(self, event):
            super(App, self).closeEvent(event)
            QCoreApplication.instance().quit()
    
            
    class HoverableEllipse(QGraphicsEllipseItem):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.setAcceptHoverEvents(True)
    
        def hoverEnterEvent(self, event):
            # Ce code sera exécuté lorsque la souris entrera dans l'ellipse
            self.setBrush(QBrush(Qt.green))  # Changez la couleur en vert lors de la survol
    
        def hoverLeaveEvent(self, event):
            # Ce code sera exécuté lorsque la souris quittera l'ellipse
            self.setBrush(QBrush(Qt.blue))  # Changez la couleur en bleu lors de la sortie
    
    if __name__ == '__main__':
        app = QApplication([])
        ex = App()
        ex.show()
        sys.exit(app.exec_())


    merci de votre aide

    • Partager sur Facebook
    • Partager sur Twitter

    Modifier et déplacer une ligne QGraphicsLineItem

    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
    • Editeur
    • Markdown