pythonpyqt5signals-slotsqplaintexteditqscrollbar

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.


Solution

  • 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_())