Tcarp
Tcarp

Reputation: 7

Inheriting from Pyqt slider doesn't inherit paintEvent nor use my overloaded version

I'm building a python app to view and QA some video files. Reading the videos with CV2, and Qslider is used to track progress through the video.

Due to pipeline issues I've written it using python 2.7.18. It wouldn't be impossible to write this in python 3 but I kept it in line with everything else till pipeline can be updated.

Here's the issue, I need to add random ticks on the trackbar, to denote points on interest in the video during QA. I found this I need to put several marks on a Qslider which seemed like it would work.

When Implement it however it doesn't seem like it's properly inheriting everything from Qslider. It seems almost as if paintevent is never called at all. The track bar no longer moves in sync with the video, or at all for that matter unless I click and drag, and the button I connected to the AddTick function gets called but doesn't add a tick, which is part of what suggests to me that paintevent isn't being called.

I've been going over it but I do not see what it is that I've missed in doing this. Any assistance is much appreciated. Below is relevant code. The UI is actually built using pyqt's QT Designer tool, so the reference to self.hsTrack references the item found in the ui file.

class NewSlider(QtWidgets.QSlider):
    valueChanged = QtCore.pyqtSignal(int)
    def __init__(self):
        super(NewSlider, self).__init__()
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(0, 12, 0, 0)
        layout.setSpacing(0)
        self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal, maximum=101)
        layout.addWidget(self.slider)

        # link slider functions; be aware that this is not usually advised
        # and you should better write specific functions that call the actual
        # slider methods
        self.value = self.slider.value
        self.setValue = self.slider.setValue
        self.minimum = self.slider.minimum
        self.setMinimum = self.slider.setMinimum
        self.maximum = self.slider.maximum
        self.setMaximum = self.slider.setMaximum

        self.ticks = set()
        self.slider.valueChanged.connect(self.valueChanged)

    def addTick(self, value=None):
        if isinstance(value, bool) or value is None:
            value = self.slider.value()
        if not value in self.ticks and self.minimum() <= value <= self.maximum():
            self.ticks.add(value)
            self.update()

    def removeTick(self, value=None):
        if isinstance(value, bool) or value is None:
            value = self.slider.value()
        if value in self.ticks:
            self.ticks.discard(value)
            self.update()

    def paintEvent(self, event):
        if not self.ticks:
            return
        sliderMin = self.slider.minimum()
        sliderMax = self.slider.maximum()
        style = self.style()
        opt = QtWidgets.QStyleOptionSlider()
        self.slider.initStyleOption(opt)
        sliderLength = style.pixelMetric(
            style.PM_SliderLength, opt, self.slider)
        span = style.pixelMetric(
            style.PM_SliderSpaceAvailable, opt, self.slider)

        qp = QtGui.QPainter(self)
        qp.translate(opt.rect.x() + sliderLength / 2, 0)
        y = self.slider.y() - 2
        for value in sorted(self.ticks):
            x = style.sliderPositionFromValue(
                sliderMin, sliderMax, value, span)
            qp.drawLine(x, 0, x, y)


class Window(QtWidgets.QMainWindow):

    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)

       # ...

        self.btnMarker.clicked.connect(self.AddMarker)

        self.hsTrack = NewSlider()
        # ...

    def AddMarker(self):
        self.hsTrack.addTick(self.hsTrack.value())

        pass

Track bar need to work as it did originally, tracking the progress of the video, and allow me to add random tick marks as needed.

Upvotes: 0

Views: 21

Answers (0)

Related Questions