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_())
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)
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)