how to detect scroll bar move down in QPlainTextEdit

I am writing a slot method for the signal of scrolling down a scrollbar in QPlainTextEdit.

I only found this signalQPlainTextEdit.verticalScrollBar().valueChanged.

I tested this signal and it returned the position number when scrolls to a new position.

My purpose is that when the scrollbar move down and trigger the slot method. But in that signal when move up it also triggeres the slot. I read the document but I couldn’t find other signals.

Answer

A possible solution is to save the previous position and compare with the new position using sliderPosition property:

from PyQt5.QtWidgets import QApplication, QPlainTextEdit


class PlainTextEdit(QPlainTextEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.last_position = self.verticalScrollBar().sliderPosition()
        self.verticalScrollBar().sliderMoved.connect(self.handle_value_changed)

    def handle_value_changed(self, position):
        if position > self.last_position:
            print("down")
        else:
            print("up")
        self.last_position = position


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    w = PlainTextEdit()
    w.show()

    sys.exit(app.exec_())

Another possible option is to implement a use of the mousePressEvent and mouseMoveEvent events of the QScrollBar:

from PyQt5.QtCore import QPoint, Qt
from PyQt5.QtWidgets import QApplication, QPlainTextEdit, QScrollBar


class ScrollBar(QScrollBar):
    last_pos = QPoint()

    def mousePressEvent(self, event):
        self.last_pos = event.pos()
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        super().mouseMoveEvent(event)
        if event.pos().y() > self.last_pos.y():
            print("down")
        else:
            print("up")
        self.last_pos = event.pos()


class PlainTextEdit(QPlainTextEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.vertical_scrollbar = ScrollBar(Qt.Vertical)
        self.setVerticalScrollBar(self.vertical_scrollbar)


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    w = PlainTextEdit()
    w.show()

    sys.exit(app.exec_())

OR:

from PyQt5.QtCore import QEvent, QPoint
from PyQt5.QtWidgets import QApplication, QPlainTextEdit


class PlainTextEdit(QPlainTextEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.last_pos = QPoint()
        self.verticalScrollBar().installEventFilter(self)

    def eventFilter(self, obj, event):
        if obj is self.verticalScrollBar():
            if event.type() == QEvent.MouseButtonPress:
                self.last_pos = event.pos()
            elif event.type() == QEvent.MouseMove:
                if event.pos().y() > self.last_pos.y():
                    print("down")
                else:
                    print("up")
                self.last_pos = event.pos()
        return super().eventFilter(obj, event)


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    w = PlainTextEdit()
    w.show()

    sys.exit(app.exec_())