QSlider Problem

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Henri
User
Beiträge: 1
Registriert: Donnerstag 14. April 2016, 16:42

Moin,

ich bin neu hier im Forum und freue mich, dabei zu sein. Kurze Vorstellung: Ich bin selbstständiger IT-Consulter, programmiere seit vielen Jahren, bin aber ein Python / PyQT Neuling, ich komme sonst eher aus der Delphi und PHP Ecke. Ich möchte aber Python / PyQT erlernen (weil plattformübergreifend) und daher lese und probiere ich derzeit ziemlich viel.
Als Test für mich bastel ich derzeit an einem Mediaplayer und da kommt dann auch schon mein kleines Problem:

Ich habe einen Positions-Slider, der mit der aktuellen Media-Position mitläuft und den ich verschieben kann. Das hatte ich erst reinrassig mit einem QSlider realisiert. Der hat aber (meines Wissens nach) keine Mausklick - Event, wo man auf eine beliebige Position des Sliders klickt und dann dementsprechend die Media-Position ändert. Also flugs eine Subclass vom QSlider gebastelt (per Google gefunden):

Code: Alles auswählen

class mySlider(QSlider):
    
    def mousePressEvent(self, nPos):
        self.setValue(QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), nPos.x(), self.width()))

    def mouseMoveEvent(self, nPos):
        self.setValue(QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), nPos.x(), self.width()))
und dann innerhalb meiner Playerklasse diesen instanziiert:

Code: Alles auswählen

self.positionSlider = mySlider(Qt.Horizontal)
self.positionSlider.setRange(0, 0) #Range wird nach Einlesen des MediaContent gesetzt
self.positionSlider.sliderMoved.connect(self.setPosition)
Jetzt kann ich mit der Maus auf eine Position des Slider klicken, ganz wunderbar, ABER:

Das doofe Ding reagiert nicht mehr auf den "sliderMoved" Event !!!!! Sollte nicht die Subclass alle Methoden / Events der übergeordneten Klasse erben?

Hier mein Event-Handler:

Code: Alles auswählen

def setPosition(self, position):
        print('Arrived at SetPosition') #Debug only
        self.mediaPlayer.setPosition(position)
Aber da kommt das Sackprogramm nie hin.... Wieso denn nich???

Wenn ich anstatt meiner Subclass wieder die QSlider Klasse nehm, dann funzt das, aber dann geht ja der Mausklick nich.....

Vielleicht hat da ja einer eine Idee, danke schon mal im voraus.

Gruß und frohes Schaffen

Henri
BlackJack

@Henri: Ja, es werden alle Methoden und Signale geerbt. Ein sicherer Grund: `sliderMoved()` löst nicht aus wenn einfach nur der Wert geändert wurde. Lies Dir mal die Dokumentation zu den Bedingungen für dieses Signal durch.

Ein möglicher Grund: Du überschreibst zwei Methoden die auch `QSlider` implementiert und die werden nicht mehr ausgeführt wenn Du sie durch eigene Implementierungen verdeckst. Ziemlich wahrscheinlich sorgt mindestens eines dieser Originale dafür, dass die Bedingung(en) erfüllt ist/sind die `sliderMoved()` auslösen.
BlackJack

Um es mal mit Code zu unterfüttern:

Code: Alles auswählen

from __future__ import absolute_import, division, print_function
import sys
from PyQt4.QtCore import Qt
from PyQt4.QtGui import (
    QApplication, QHBoxLayout, QSlider, QStyle, QStyleOptionSlider, QWidget
)



class Slider(QSlider):
    
    def mousePressEvent(self, event):
        style_option = QStyleOptionSlider()
        self.initStyleOption(style_option)
        handle_rect = self.style().subControlRect(
            QStyle.CC_Slider, style_option, QStyle.SC_SliderHandle, self
        )
        if (
            event.button() == Qt.LeftButton
            and not handle_rect.contains(event.pos())
        ):
            if self.orientation == Qt.Vertical:
                factor = (self.height() - event.y()) / self.height()
            else:
                factor = event.x() / self.width()
            value = self.minimum() + (self.maximum() - self.minimum()) * factor
            
            if self.invertedAppearance():
                value = self.maximum() - value
            
            self.setValue(value)
            event.accept()

        QSlider.mousePressEvent(self, event)


class MainWidget(QWidget):

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        layout = QHBoxLayout(self)
        slider = Slider(Qt.Horizontal, self)
        layout.addWidget(slider)


def main():
    app = QApplication(sys.argv)
    window = MainWidget()
    window.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
Das ruft nicht nur die überschriebene Methode auf, sondern führt den Sprung auch nur dann aus, wenn man sich mit der Maus nicht über dem Anfasser vom Schieberegler befindet, damit die normale Funktonalität von dem Widget erhalten bleibt.
Antworten