QtWidget: MouseMove bzw. MouseHoverEvent kommt nicht an

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Schnukilein1904
User
Beiträge: 2
Registriert: Donnerstag 15. März 2018, 08:41

Hallo zusammen,

ich habe ein Problem mit den MouseEvents und ich weiß schon nicht mehr weiter. Vielleicht steh ich auch auf dem Schlauch und deswegen wende ich mich an euch, vielleicht könnt ihr mir ja helfen. Ich habe dieses Projekt erst vor kurzem übernommen und kenne mich mit der GUI Programmierung in Python noch nicht so ganz aus.
Zur Erklärung ich hab eine Gui die Module auflistet und auch zeigt, ob zu dem Modul eine Dokumentation vorhanden ist. Dies wird in Form eines kleinen Symbols gekennzeichnet.
Als Beispiel, damit ich seh ob es funktioniert, hab ich mir ein keyPressEvent Funktion geschrieben, dieses Event kommt durch. Das mousePressEvent oder mouseMoveEvent oder mouseHoverEvent kommt einfach nicht durch. ich hoffe ihr könnt mir helfen.

Das ist meine Klasse, meine funktionen stehen unten. Mir geht es hier hauptsächlich darum, dass mouseHoverEvent zu bekommen, wenn ich über das Doc-icon fahre, damit ich da den Mousezeiger ändern kann.

Ich hoffe, dass ich alles verständlich erklärt habe.

Viele Grüße,
Bianca

Code: Alles auswählen

class ModuleLib(CentralWidgetBase, QWidget):
    warnColor='#999900'#Qt.darkYellow
    errColor=Qt.red
    normalColor='#000000'#Qt.darkGreen

    applyFilterSignal = pyqtSignal(name='applyFilterSignal')
    restoreExpansionSignal = pyqtSignal(QModelIndex, dict, name='applyFilterSignal')

    def __init__(self, communicator):
        QWidget.__init__(self)
        CentralWidgetBase.__init__(self, communicator)
        self.sM=self.communicator.getObject('SettingsManager')
        self.urlIcon=images['url'].as_('icon')
        self.buildGui()
        self.cache = {
            'autoUpdatePkgInfo': True,
        }
        self.communicator.registerListener('pkgsInfoReady', self.updateModuleList)
        self.communicator.registerFunction(self.getLastScannedInfoTreeItem,localOnly=True)
        self.lastScannedPkgsInfo={}
        self.lastScannedIndex={}
        self.infoItems={}
        self.filterStr=''
        self.filterChangedDelayTimer=QTimer()
        self.filterChangedDelayTimer.setSingleShot(True)
        self.filterChangedDelayTimer.timeout.connect(self.onApplyFilter)
        self.applyFilterSignal.connect(self.onApplyFilter)
        self.restoreExpansionSignal.connect(self.restoreExpansion)
        self.infoTreeItems={}

    def title(cls):
        return 'Module Library'

    @classmethod
    def functionalPlugin(cls):
        return 'SupervisingPackageManager'

    def getLastScannedInfoTreeItem(self, infoKey):
        return self.infoTreeItems.get(infoKey, None)

    def onPluginsCreated(self, savedInstanceState=None):
        self.packageManager = self.communicator.getObject('SupervisingPackageManager')
        self.setModuleInfoViewMarkPattern=self.communicator.getFunction('setModuleInfoViewMarkPattern')

        if savedInstanceState is not None:
            self.cache.update(savedInstanceState)
        self.updateGui()

    def onSaveInstanceState(self):
        self.cache['autoUpdatePkgInfo'] = self.autoUpdateCheckBox.isChecked()

        return self.cache

    def updateGui(self):
        self.autoUpdateCheckBox.setChecked(self.cache['autoUpdatePkgInfo'])

        pM = self.communicator.getObject('PluginManager')
        editors = pM.getPlugins(PackageEditorBase)
        if len(editors) == 0:
            self.editorsBox.setHidden(True)
        else:
            editorsBoxLayout = FlowLayout()
            self.editorsBox.setLayout(editorsBoxLayout)
            for editor in sorted(editors, key=lambda e: e.pkgExt):
                editBut = QPushButton(editor.pkgExt)
                editorsBoxLayout.addWidget(editBut)
                def editPackages(x, e=editor):
                    CleaningThread(target=e.editPackages).start()
                editBut.clicked.connect(editPackages)

        if self.autoUpdateCheckBox.isChecked():
            self.requestModuleInfo()
        # else:
        #     self.updateModuleList(True, self.packageManager.getLastScannedPkgInfos(), self.packageManager.getLastScannedIndex())

    def requestModuleInfo(self):
        self.communicator.send('pkgsInfoRequest', newThread=True)


    def __generateToolTipMsg(self,notes):
        tooltip=''
        color=None
        pkgWarnString = '\n'.join(note['msg'] for note in notes if note['type'] == 'warning')
        if pkgWarnString != '':
            tooltip = ('warnings:\n' + pkgWarnString).replace('\n', '\n\t')
            color=self.warnColor
        pkgErrString = '\n'.join(note['msg'] for note in notes if note['type'] == 'error')
        if pkgErrString != '':
            tooltip = ('errors:\n' + pkgErrString).replace('\n', '\n\t') + '\n' + tooltip
            color=self.errColor
        return tooltip, color

    def storeExpansion(self, index):
        expansions = {}
        for i in range(self.filterModel.rowCount(index)):
            child = self.filterModel.index(i, 0, index)
            if self.moduleTreeView.isExpanded(child):
                expansions[self.filterModel.data(child,Qt.DisplayRole)] = self.storeExpansion(child)
        return expansions

    def restoreExpansion(self,index, expansions):
        for i in range(self.filterModel.rowCount(index)):
            child = self.filterModel.index(i, 0, index)
            subExpansions=expansions.get(self.filterModel.data(child,Qt.DisplayRole),None)
            if subExpansions is not None:
                self.moduleTreeView.expand(child)
                self.restoreExpansion(child, subExpansions)

    def updateModuleList(self, fullScan, pkgsInfos, index):
        if fullScan:
            self.lastScannedPkgsInfo = pkgsInfos
            self.lastScannedIndex = index
            self.infoTreeItems.clear()
        else:
            DictTools.update(self.lastScannedPkgsInfo, pkgsInfos)
            DictTools.update(self.lastScannedIndex, index)

        libTreeInfo={}
        for pkg, pkgInfo in self.lastScannedPkgsInfo.items():
            pkgInfoItem=InfoTreeItem(key=pkg, value=pkgInfo)
            self.infoItems[pkg]=pkgInfoItem
            pkgPath = pkgInfo['path']
            pkgSearchRoot = pkgInfo['searchRoot']
            lib = path.dirname(pkgPath)[len(pkgSearchRoot)+1:].replace('/',':childs:')
            if lib == '':
                libPkgs = libTreeInfo
                parentLibs = []
            else:
                libInfo = DictTools.get(libTreeInfo,lib)
                if libInfo is None:
                    libInfo = {'childs':{}}
                    DictTools.set(libTreeInfo, libInfo,lib)
                libPkgs=libInfo['childs']
                parentLibs =[libInfo]
                while ':childs:' in lib:
                    lib = lib.rsplit(':childs:',1)[0]
                    parentLibs.append(DictTools.get(libTreeInfo,lib))

            notes=pkgInfo['notes']
            mods={}
            msg,col=self.__generateToolTipMsg(notes)
            for libInfo in parentLibs:
                if col==self.errColor:
                    libInfo['color'] = self.errColor
                elif col==self.warnColor and libInfo.get('color',None)!= self.errColor:
                    libInfo['color'] = self.warnColor
                elif 'color' not in libInfo:
                    libInfo['color'] = self.normalColor
            pkgEntry = {'childs': mods, 'color': col, 'msg': msg, 'type':'pkg', 'infoKey': pkg,'infoItem':pkgInfoItem}
            self.addDocIcon(pkgPath,pkgEntry,pkgInfo)
            self.infoTreeItems[pkg]=pkgInfoItem
            for pkgModuleInfoKey in pkgInfo['moduleInfoKeys']:
                moduleInfoKey = pkg + ':' + pkgModuleInfoKey
                module=DictTools.endKey(moduleInfoKey)
                msg, col = self.__generateToolTipMsg([note for note in notes if module in note.get('possiblyAffectedModules',[])])
                moduleInfoItem=pkgInfoItem.moduleItemList[module]
                mods[module]=modEntry={'color': col, 'msg': msg, 'infoKey': moduleInfoKey, 'type':'mod','infoItem':moduleInfoItem}
                self.addDocIcon(pkgPath, modEntry, DictTools.get(pkgInfo,pkgModuleInfoKey,{}))
                self.infoTreeItems[moduleInfoKey] = moduleInfoItem
            libPkgs[pkg]=pkgEntry

        expansions = self.storeExpansion(self.moduleTreeView.rootIndex())
        self.libDataModel.setPyData(libTreeInfo)
        self.restoreExpansionSignal.emit(self.moduleTreeView.rootIndex(), expansions)
        self.applyFilterSignal.emit()

        self.communicator.send('infoTreeItemsChanged')

    def addDocIcon(self,root, itemInfo,info):
        doc = info.get('doc', None)
        if doc is not None:
            if urllib.parse.urlparse(doc).scheme == "":
                docPath = doc if path.isabs(doc) else (root + '/' + doc)
                if path.exists(docPath):
                    itemInfo['doc'] = docPath
                    itemInfo['docIcon'] = QFileIconProvider().icon(QFileInfo(docPath))
                else:
                    self.communicator.warning('documentation "'+docPath+'" could not be found')
            else:
                itemInfo['doc'] = doc
                itemInfo['docIcon'] = self.urlIcon

    # def onModuleListItemClicked(self,index):
    #     if index.isValid():
    #         moduleListItem=self.filterModel.mapToSource(index).internalPointer()
    #         if moduleListItem.infoItem is not None:
    #             self.setModuleInfoViewRootItem(moduleListItem.infoItem, moduleListItem.key)

    def onFilterChanged(self,filterStr):
        self.filterStr = filterStr.lower()
        self.filterChangedDelayTimer.start(500)

    def onItemDoubleClicked(self,index):
        if not index.isValid():
            return

        info = index.data(Qt.UserRole)
        if index.column() == 0:
            infoKey = info.get('infoKey',None)
            if infoKey is not None:
                splitKey = DictTools.seperatorPattern.split(infoKey)
                pkgInfo = self.lastScannedPkgsInfo[splitKey[0]]
                if len(splitKey) == 1: # package
                    webbrowser.open(pkgInfo['path'])

        elif index.column() == 1:
            doc=info.get('doc',None)
            if doc is not None:
                webbrowser.open(doc)

    def onApplyFilter(self):
        withKey=self.searchInclusiveKeysCheckBox.isChecked()
        pattern = None

        if self.searchRegExCheckBox.isChecked():
            if len(self.filterStr)>0:
                pattern=re.compile(self.filterStr, re.IGNORECASE | re.DOTALL)
                for pkg, pkgInfoItem in self.infoItems.items():
                    pkgInfoItem.countFilterMatchesRegEx(pattern, withKey)
        else:
            filterList = self.filterStr.split()
            for pkg, pkgInfoItem in self.infoItems.items():
                pkgInfoItem.countFilterMatches(filterList, withKey)
            if len(filterList)> 0:
                pattern = re.compile('|'.join(re.escape(word) for word in filterList), re.IGNORECASE)

        if self.libDataModel.rootItem is not None:
            self.libDataModel.rootItem.setFilter(pattern)

        #self.filterModel.invalidateFilter()
        self.filterModel.invalidate()
        self.filterModel.sort(0,Qt.AscendingOrder)
        self.setModuleInfoViewMarkPattern(pattern, withKey)
        self.moduleTreeView.resizeColumnToContents(0)


    def buildGui(self):
        ### main layout
        mainLay = QVBoxLayout(self)
        self.setLayout(mainLay)

        ## first row
        rowLay = QHBoxLayout()
        mainLay.addLayout(rowLay)

        # search box
        rowLay.addWidget(QLabel('filter:'))  # , 0, Qt.AlignLeft)
        self.searchLineEdit = QLineEdit()
        self.searchLineEdit.textChanged.connect(self.onFilterChanged)
        rowLay.addWidget(self.searchLineEdit, 1)  # , Qt.AlignLeft)

        # search in keys checkbox
        self.searchInclusiveKeysCheckBox = QCheckBox('search in keys')
        self.searchInclusiveKeysCheckBox.setChecked(True)
        self.searchInclusiveKeysCheckBox.stateChanged.connect(self.onApplyFilter)
        rowLay.addWidget(self.searchInclusiveKeysCheckBox)  # , 0, Qt.AlignRight)

        self.searchRegExCheckBox = QCheckBox('regEx')
        self.searchRegExCheckBox.setChecked(False)
        self.searchRegExCheckBox.stateChanged.connect(self.onApplyFilter)
        rowLay.addWidget(self.searchRegExCheckBox)  # , 0, Qt.AlignRight)

        # auto update checkbox
        self.autoUpdateCheckBox = QCheckBox('scan modules on startup')
        rowLay.addWidget(self.autoUpdateCheckBox)  # , 0, Qt.AlignRight)

        # update button
        self.updateModuleListButton = QPushButton('scan')
        rowLay.addWidget(self.updateModuleListButton)
        self.updateModuleListButton.clicked.connect(self.requestModuleInfo)

        # module list
        self.moduleTreeView = QTreeView()
        self.moduleTreeView.setUniformRowHeights(True)
        #self.moduleTreeView.header().close()
        self.moduleTreeView.setDragEnabled(True)
        self.moduleTreeView.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.moduleTreeView.collapsed.connect(lambda x: self.moduleTreeView.resizeColumnToContents(0))
        self.moduleTreeView.expanded.connect(lambda x: self.moduleTreeView.resizeColumnToContents(0))
        self.moduleTreeView.setExpandsOnDoubleClick(False)
        #self.moduleTreeView.clicked.connect(lambda x: self.moduleTreeView.collapse(x) if self.moduleTreeView.isExpanded(x) else self.moduleTreeView.expand(x))
        self.moduleTreeView.doubleClicked.connect(self.onItemDoubleClicked)
        self.moduleTreeView.setMouseTracking(True)
        #self.setCursor(Qt.PointingHandCursor)
        self.libDataModel = ModuleLibTreeModel()
        self.filterModel=ModuleLibTreeFilter()
        self.filterModel.setSourceModel(self.libDataModel)
        self.filterModel.setDynamicSortFilter(True)
        self.moduleTreeView.setModel(self.filterModel)
        mainLay.addWidget(self.moduleTreeView)

        # editors
        self.editorsBox = QGroupBox('edit packages')
        mainLay.addWidget(self.editorsBox)

    def keyPressEvent(self, keyEvent):
        if keyEvent.matches(QKeySequence.Delete):
            self.communicator.log('jawoll')
        else:
            self.communicator.log('moeeep')
            super().keyPressEvent(keyEvent)

    def mousePressEvent(self, mouseEvent):
        if mouseEvent.button() == Qt.LeftButton:
            self.communicator.log('jawoll')
        elif mouseEvent.button() == Qt.RightButton:
            self.communicator.log('rechts')
            super().mousePressEvent(mouseEvent)
Schnukilein1904
User
Beiträge: 2
Registriert: Donnerstag 15. März 2018, 08:41

so, hab mein Problem selbst gelöst, für alle die es interessiert:

als ersters musste ich das Attribut

Code: Alles auswählen

Qt.WA_MouseTracking
setzten, da das über die Funktion QWidget.setMouseTracking(True) irgendwie nicht funktioniert hat. Mit dem

Code: Alles auswählen

Qt.WA_Hover
wurde dieser Event freigeschalten und man konnte es in der Funktion abfragen.

Das Hover Event hab ich wie folgt abgefangen:

Code: Alles auswählen

def event(self, event):
    if event.type() == QEvent.HoverMove:
        self.communicator.log('hover') (oder bei anderen eben print)

return QWidget.event(self, event)
das Mouse move event habe ich wie folgt abgefangen:

Code: Alles auswählen

def mouseMoveEvent(self, mouseEvent):
    oPoint = mouseEvent.pos()
    index = self.moduleTreeView.indexAt(oPoint)
    self.communication.log('index')

return QWidget.mouseMoveEvent(self, mouseEvent)
Antworten