[Python] PyQt6 on Windows : qtquickcontrols2windowsstyleimplplugin.dll: The specified module...

Discussão em 'Python' iniciado por Stack, Abril 11, 2025.

  1. Stack

    Stack Membro Participativo

    i am trying to test some code using PyQt6. When I try to display en MenuBar in my main.qml, i have this error :

    QQmlApplicationEngine failed to load component
    file:///C:/Users/[blablabla]/GUIt/main.qml:11:9: Type Menu unavailable
    qrc:/qt-project.org/imports/QtQuick/Controls/Windows/Menu.qml:32:15: Type MenuItem unavailable
    qrc:/qt-project.org/imports/QtQuick/Controls/Windows/MenuItem.qml:7:1: Impossible de charger la bibliothÞque C:\Users\[blablabla]\Python\Python313\Lib\site-packages\PyQt6\Qt6\qml\QtQuick\Controls\Windows\impl\qtquickcontrols2windowsstyleimplplugin.dllá: Le module spÚcifiÚ est introuvable.


    (Sorry i'm french so my errors too, but "Le module spÚcifiÚ est introuvable." means "The specified module could not be found")

    I could not find any solved issue similar to my problem so i try my luck here.

    I am on Windows 11, and I am using Python3.13.3 (not the native Windows installation)

    Here is my code : main.py :

    from PyQt6.QtWidgets import QApplication
    from PyQt6.QtQml import QQmlApplicationEngine
    from backend import Backend

    app = QApplication([])
    engine = QQmlApplicationEngine()

    backend = Backend()
    engine.rootContext().setContextProperty("pybackend", backend)

    engine.load("main.qml")

    if not engine.rootObjects():
    import sys
    sys.exit(-1)

    app.exec()


    backend.py :

    from PyQt6.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
    from PyQt6.QtWidgets import QFileDialog
    from git import Repo
    from models.CommitList import CommitListModel

    class Backend(QObject):
    repoPathChanged = pyqtSignal()
    repoNameChanged = pyqtSignal()
    commitListChanged = pyqtSignal()

    def __init__(self):
    super().__init__()
    self._commit_list = CommitListModel()
    self._repo_path = ""
    self.repo = None
    self._repo_name = ""

    @pyqtProperty(str, notify=repoPathChanged)
    def repoPath(self):
    return self._repo_path

    @pyqtProperty(str, notify=repoNameChanged)
    def repoName(self):
    return self._repo_name

    @pyqtProperty(QObject, notify=commitListChanged)
    def commitList(self):
    return self._commit_list

    @pyqtSlot()
    def chooseAndLoadRepo(self):
    dialog = QFileDialog()
    dialog.setFileMode(QFileDialog.FileMode.Directory)
    dialog.setOption(QFileDialog.Option.ShowDirsOnly, True)
    if dialog.exec():
    selected_dirs = dialog.selectedFiles()
    if selected_dirs:
    self.loadRepo(selected_dirs[0]) # charge le dossier sélectionné

    @pyqtSlot()
    def loadRepo(self, path = "C:/Users/lucie/Hesias/B2/MajorProject/major-project-b2"):
    try:
    self.repo = Repo(path)
    self._repo_path = path
    self._repo_name = path.split("/")[-1]
    self.repoPathChanged.emit()
    self.repoNameChanged.emit()
    except Exception as e:
    print(f"Erreur : {e}")

    @pyqtSlot()
    def loadCommits(self):
    try:
    commits = [f"{c.hexsha[:7]}: {c.summary}" for c in self.repo.iter_commits()]
    print(commits)
    self._commit_list.setCommits(commits)
    self.commitListChanged.emit()
    except Exception as e:
    self._commit_list.setCommits([f"Erreur : {e}"])


    models/CommitList.py :

    from PyQt6.QtCore import QAbstractListModel, Qt, QModelIndex

    class CommitListModel(QAbstractListModel):
    def __init__(self, commits=None):
    super().__init__()
    self._commits = commits or []

    def data(self, index, role):
    if role == Qt.ItemDataRole.DisplayRole and index.isValid():
    return self._commits[index.row()]
    return None

    def rowCount(self, index):
    return len(self._commits)

    def setCommits(self, commits):
    self.beginResetModel()
    self._commits = commits
    self.endResetModel()


    main.qml :

    import QtQuick
    import QtQuick.Controls

    ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("GUIt")

    MenuBar {
    Menu {
    title: "Fichier"

    Action {
    text: "Charger un dépôt"
    onTriggered: pybackend.chooseAndLoadRepo()
    }

    // Tu peux ajouter plus d'actions ici
    // Action {
    // text: "Autre option"
    // onTriggered: { /* action ici */ }
    // }
    }

    // Ajoute un menu "Édition"
    Menu {
    title: "Édition"

    Action {
    text: "Option 1"
    onTriggered: { /* action ici */ }
    }

    Action {
    text: "Option 2"
    onTriggered: { /* action ici */ }
    }
    }
    }


    Column {
    anchors.centerIn: parent
    spacing: 10

    Text {
    text: pybackend.repoPath !== "" ? "Repo actuel : " + pybackend.repoName : "Aucun dépôt chargé"
    font.pixelSize: 20
    }

    Button {
    text: "Charger le dépôt"
    // onClicked: pybackend.loadRepo()
    onClicked: pybackend.chooseAndLoadRepo()
    }

    Button {
    text: "Charger les commits"
    onClicked: pybackend.loadCommits()
    enabled: pybackend.repoPath !== ""
    }

    ListView {
    width: parent.width
    height: 300
    model: pybackend.commitList
    delegate: Text {
    text: model.display // ou juste `modelData` si le rôle par défaut est utilisé
    font.pixelSize: 14
    padding: 4
    }
    }
    }
    }

    Continue reading...

Compartilhe esta Página