Partage
  • Partager sur Facebook
  • Partager sur Twitter

problème avec QtWidgets.QGraphicsView pyqt5

drag and drop d'une liste QListWidget vers une QGraphicsView

    14 avril 2024 à 13:26:37

    bonjour tout le monde et merci d'avance  , je suis débutant avec python et je   travail sur un application de projet de fin d'étude avec python et pyqt 5 et j'ai un petit problème avec QtWidgets.QGraphicsView  j'essayer  de faire un drag and drop d'une liste des mots clef pour les déposer dans une interface graphique mais ca marche pas  et par contre ca marche avec le double clique 

    c'est  le code que j'ai

    from PyQt5 import QtCore, QtGui, QtWidgets
    import sys
    import json
    import os
    from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsView, QVBoxLayout, QSplitter, QWidget, QListWidget, QTextEdit, QLabel
    from PyQt5.QtCore import Qt, QRectF
    from PyQt5.QtCore import * 
    from PyQt5.QtGui import * 
    from PyQt5.QtWidgets import *
    from AddModuleDialog import AddModuleDialog
    from ScriptFileDialog import ScriptFileDialog
    from function import get_file_extension,get_file_type,run_script_python,run_script_javaScript,run_test
    
    class CustomListWidget(QtWidgets.QListWidget):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setDragEnabled(True)  # Activer le glisser-déposer
            self.setSelectionMode(QAbstractItemView.SingleSelection)  # Permettre la sélection d'un seul élément à la fois
    
        def mimeData(self, indexes):
            mime_data = super().mimeData(indexes)
            item = self.currentItem()
            if item:
                mime_data.setData('application/custom-type', item.text().encode())
            return mime_data
    
    class CustomGraphicsView(QtWidgets.QGraphicsView):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setAcceptDrops(True)
            self.scene = QtWidgets.QGraphicsScene(self)
            self.setScene(self.scene)
    
        def dragEnterEvent(self, event):
            print("Drag Enter Event Triggered")  # Ajout d'un message de débogage
            if event.mimeData().hasFormat('application/custom-type'):
                event.accept()
            else:
                event.ignore()
    
        def dropEvent(self, event):
            print("Drop Event Triggered")  # Ajout d'un message de débogage
            if event.mimeData().hasFormat('application/custom-type'):
                event.accept()
                position = event.pos()
                text = event.mimeData().data('application/custom-type').data().decode()
                print("Content of dropped item:", text)  # Ajout d'un message de débogage pour afficher le contenu du presse-papiers
                label = QtWidgets.QLabel(text)
                label.setStyleSheet("border: 1px solid black; padding: 10px;")
                proxy = self.scene().addWidget(label)
                proxy.setPos(position)
            else:
                event.ignore()
    
    class Main(QMainWindow):
        def __init__(self):
            super().__init__()
            self.setupUi(self)
            self.setWindowTitle("Application PyQt5")
            self.createMenuBar()
            self.createToolBars()
    
            self.current_x = 10
            self.current_y = 10
    
            self.keywords = []  # Variable pour stocker les mots-clés
            self.scripts = []   # Variable pour stocker les scripts
    
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(1120, 854)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
    
            self.keywordList = CustomListWidget(self.centralwidget)
            self.keywordList.setGeometry(QtCore.QRect(0, 0, 256, 531))
    
            self.fileListe = CustomListWidget(self.centralwidget)
            self.fileListe.setGeometry(QtCore.QRect(0, 530, 256, 281))
            self.fileListe.setObjectName("fileListe")
    
            self.view1 = CustomGraphicsView(self.centralwidget)
            self.view1.setGeometry(QtCore.QRect(250, 0, 871, 531))
            self.view1.setMouseTracking(True)
            self.view1.setTabletTracking(True)
            self.view1.setFocusPolicy(QtCore.Qt.WheelFocus)
            self.view1.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorViewCenter)
            self.view1.setObjectName("view1")
    
            self.consol = QtWidgets.QTextBrowser(self.centralwidget)
            self.consol.setGeometry(QtCore.QRect(255, 530, 866, 281))
            self.consol.setObjectName("consol")
    
            MainWindow.setCentralWidget(self.centralwidget)
            self.menubar = QtWidgets.QMenuBar(MainWindow)
            self.menubar.setGeometry(QtCore.QRect(0, 0, 1120, 26))
            self.menubar.setObjectName("menubar")
            MainWindow.setMenuBar(self.menubar)
            self.statusbar = QtWidgets.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
            self.load_data()
    
            self.keywordList.itemDoubleClicked.connect(self.add_label_to_scene)
            self.fileListe.itemDoubleClicked.connect(self.add_label_to_scene)
    
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
    
        def show(self):
            super().show()  # Appel de la méthode show() de la classe de base
    
        def load_data(self):
            # Nettoyer la keywordList et la fileListe
            self.keywordList.clear()
            self.fileListe.clear()
    
            # Charger les données à partir d'un fichier JSON
            try:
                with open('keywords.json', 'r') as f:
                    data = json.load(f)
                    self.keywords = data.get('keywords', [])
                    self.scripts = data.get('script', [])
    
                # Charger les données dans keywordList
                for keyword_data in self.keywords:
                    keyword = keyword_data['keyword']
                    self.keywordList.addItem(keyword)
    
                # Charger les données dans fileListe
                for script_data in self.scripts:
                    file_name = script_data['file_name']
                    self.fileListe.addItem(file_name)
    
            except Exception as e:
                print("Une erreur s'est produite lors du chargement des données:", e)
    
        def createToolBars(self):
            # Using a title
            toolbar = self.addToolBar("File")
    
            import_script = QAction(QIcon('../app/icone/import_file.png'), 'import script', self)
            import_script.triggered.connect(self.upload_script)  # Connect the action to the run_code function
            toolbar.addAction(import_script)
    
            delete_script = QAction(QIcon('../app/icone/delete.png'), 'Run', self)
            delete_script.triggered.connect(self.remove_selected_item)  # Connect the action to the run_code function
            toolbar.addAction(delete_script)
    
            newModel = QAction(QIcon('../app/icone/new_function.png'), 'newModel', self)
            newModel.triggered.connect(self.newModel)  # Connect the action to the run_code function
            toolbar.addAction(newModel)
    
            toolbar.addSeparator()
    
            run_action = QAction(QIcon('../app/icone/run-icon.png'), 'run script', self)
            run_action.triggered.connect(self.run_script)  # Connect the action to the run_code function
            toolbar.addAction(run_action)
    
            run_action = QAction(QIcon('../app/icone/run_model.png'), 'run model', self)
            run_action.triggered.connect(self.run_model)  # Connect the action to the run_code function
            toolbar.addAction(run_action)
    
            clear_scenario = QAction(QIcon('../app/icone/clear_scenario.png'), 'clear scenario', self)
            clear_scenario.triggered.connect(self.fn_clear_scenario)  # Connect the action to the run_code
            toolbar.addAction(clear_scenario)
    
            clear_console = QAction(QIcon('../app/icone/clear_scenario.png'), 'clear console', self)
            clear_console.triggered.connect(self.fn_clear_console)  # Connect the action to the run_code
            toolbar.addAction(clear_console)
    
        def createMenuBar(self):
            menuBar = self.menuBar()
            fileMenu = menuBar.addMenu('&File')
            fileMenu.addAction('import script', self.upload_script)
            fileMenu.addAction('New Module', self.newModel)
            fileMenu.addAction('&Exit', self.close)
    
            fileMenu = menuBar.addMenu('&run')
            fileMenu.addAction('run script', self.run_script)
            fileMenu.addAction('run Module', self.run_model)
            fileMenu.addAction('clear scenario', self.fn_clear_scenario)
            fileMenu.addAction('clear console', self.fn_clear_console)
    
        def upload_script(self):
            file_dialog = ScriptFileDialog(self)
            if file_dialog.exec_():
                file_paths = file_dialog.selectedFiles()
                for file_path in file_paths:
                    file_name = os.path.basename(file_path)
                    script_entry = {"file_name": file_name, "path": file_path}
    
                    # Open JSON file and load existing data
                    with open('keywords.json', 'r') as f:
                        data = json.load(f)
    
                        # Add the new script entry to the list of scripts
                    data.setdefault('script', []).append(script_entry)
    
                    # Save the updated data back to the JSON file
                    with open('keywords.json', 'w') as f:
                        json.dump(data, f, indent=4)
            self.load_data()
    
        def newModel(self):
            dialog = AddModuleDialog(parent=self)
            if dialog.exec_() == QDialog.Accepted:
                self.load_data()
    
        def run_script(self, output=None):
            selected_item = self.fileListe.currentItem()
            if selected_item is not None:
                file_name = selected_item.text()
                for script in self.scripts:
                    if script.get('file_name') == file_name:
                        file_path = script.get('path')
                        extension = get_file_extension(file_path)
                        file_type = get_file_type(extension)
                        if file_type == 'Python':
                            try:
                                output_with_duration = run_script_python(file_path, file_name)
                                self.console.append(output_with_duration)
                            except Exception as e:
                                print(f"Erreur lors de l'exécution du script : {e}")
                            break
                        elif file_type == 'JavaScript':
                            try:
                                output_with_duration = run_script_javaScript(file_path, file_name)
                                self.console.append(output_with_duration)
                            except Exception as e:
                                print(f"Erreur lors de l'exécution du script : {e}")
                            break
            else:
                QMessageBox.information(self, "run script", "select script to run")
    
        def remove_selected_item(self):
            selected_item = self.fileListe.currentItem()
            if selected_item is not None:
                reply = QMessageBox.question(self, 'Confirmation', 'Are you sure you want to delete this script?',
                                              QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
                if reply == QMessageBox.Yes:
                    file_name = selected_item.text()
                    with open('keywords.json', 'r') as f:
                        data = json.load(f)
                        scripts = data.get('script', [])
                    updated_scripts = [script for script in scripts if script.get('file_name') != file_name]
                    data['script'] = updated_scripts
                    with open('keywords.json', 'w') as f:
                        json.dump(data, f, indent=4)
                self.load_data()
            else:
                QMessageBox.information(self, "delete script", "select script to delate")
    
        def fn_clear_scenario(self):
            self.view1.scene().clear()
    
        def fn_clear_console(self):
            self.console.clear()
    
        def run_model(self):
            total_items = self.view1.count()
            items = [self.view1.item(index).text() for index in range(total_items)]
            parts = []
            current_part = []
            for item in items:
                is_keyword = any(keyword['keyword'] == item for keyword in self.keywords)
                if is_keyword:
                    if current_part:
                        parts.append(current_part)
                    current_part = [item]
                else:
                    current_part.append(item)
            if current_part:
                parts.append(current_part)
            for part in parts:
                keyword_used = part[0]
                if keyword_used:
                    run_object = next((keyword for keyword in self.keywords if keyword['keyword'] == keyword_used),
                                      None)
                    if run_object:
                        function_name = run_object.get('function_name')
                        snippet_code = run_object.get('snippet_code')
                        param = run_object.get('parameters')
                        if function_name and snippet_code:
                            namespace = {}
                            exec(snippet_code, namespace)
                            function_to_call = namespace.get(function_name)
                            if function_to_call:
                                if param:
                                    function_to_call(part, self.scripts, get_file_extension, get_file_type,
                                                     run_script_python, self.console, run_script_javaScript, param)
                                else:
                                    function_to_call(part, self.scripts, get_file_extension, get_file_type,
                                                     run_script_python, self.console, run_script_javaScript)
                            else:
                                print(f"La fonction spécifiée '{function_name}' n'a pas été trouvée dans le snippet_code.")
                        else:
                            print("Le nom de la fonction ou le code du snippet_code est manquant.")
    
        def add_label_to_scene(self, item):
            text = item.text()
            label = QLabel(text)
            label.setStyleSheet("border: 1px solid black; padding: 10px;")
    
            # Crée un QGraphicsProxyWidget pour afficher le QLabel dans la QGraphicsScene
            proxy = self.view1.scene.addWidget(label)
            # Positionner le QLabel à l'endroit spécifié
            proxy.setPos(self.current_x, self.current_y)
    
            # Mettre à jour les coordonnées pour le prochain élément
            self.current_x += 50
            self.current_y += 50
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = Main()
        window.show()
        sys.exit(app.exec_())
    

     merci encore ^^'

    • Partager sur Facebook
    • Partager sur Twitter
      15 avril 2024 à 16:37:43

      Bonjour,

      Vous avez un message d'erreur ?

      • Partager sur Facebook
      • Partager sur Twitter

      Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
      La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

        15 avril 2024 à 22:16:00

        bonjour et merci de ton repense ^^

        non il n'ya pas de message d'erreur et en fin j'ai résolu le problème  ,

        il avait un problème dans la fonction mimeData qui code le type de donner entre 

        def mimeData(self, indexes):
                mime_data = super().mimeData(indexes)
                item = self.currentItem()
                if item:
                    mime_data.setData('application/custom-type', item.text().encode())
                return mime_data

         je la fais changer pour quelle accepte l'information de mon item 

        def mimeData(self, indexes):
              
                mime_data = super().mimeData(indexes)
                item = self.currentItem()
                
                if item:
                    mime_data.setText(item.text())
                    mime_data.setData('application/custom-type', item.text().encode())
                    print('mime_data',mime_data.text())
                return mime_data


        et j'ai fais quelque modification sur la fonction dropEvent

        def dropEvent(self, event):
                if event.mimeData().hasText():
                    event.setAccepted(True)
                    event_id = event.mimeData().text()
                    
                    
                    draggable_item = DraggableItem(event_id,self.arrow_drawing_mode)
                    
                    pos = self.mapFromGlobal(QCursor.pos())
                    
                    draggable_item.setPos(pos)
                    
                 
                    self.scene.addItem(draggable_item)
                    
                self.update()


        ca fonctionne meme si il ya un mouvement bizarre  de la scene au moment que je lâche l'objet 

        -
        Edité par MouinMohsni 15 avril 2024 à 22:17:33

        • Partager sur Facebook
        • Partager sur Twitter

        problème avec QtWidgets.QGraphicsView pyqt5

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        • Editeur
        • Markdown