2

I'm trying to update a QLineEdit when I do a wheel move on the mouse and if I press a number on the keyboard at the same time. Unfortunatly, I don't see a mouse wheel event for QLineEdit widget so I don't understand how I can set a signal to each QLineEdit. The other issue I have is as the QLineEdit are already in a scroll bar environment, I cannot detect all wheel event because the scroll is done first.

For instance with this code:

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys


class SurfViewer(QMainWindow):
    def __init__(self, parent=None):
        super(SurfViewer, self).__init__()
        self.parent = parent

        self.centralTabs= QTabWidget()
        self.setCentralWidget(self.centralTabs)
        self.setFixedWidth(200)
        self.setFixedHeight(200)

        #tab Model selection
        self.tab_ModelSelect = QWidget()
        self.centralTabs.addTab(self.tab_ModelSelect,"Label")


        self.groupscrolllayouttest = QHBoxLayout() ####
        self.groupscrollbartest = QGroupBox() ####


        self.mainHBOX_param_scene = QVBoxLayout()
        for i in range(10):
            LineEdit = QLineEdit(str(i))
            LineEdit.setFixedWidth(200)
            self.mainHBOX_param_scene.addWidget(LineEdit) 
        self.installEventFilter(self)

        scroll = QScrollArea()
        widget = QWidget(self)
        widget.setLayout(QVBoxLayout())
        widget.layout().addWidget(self.groupscrollbartest)
        scroll.setWidget(widget)
        scroll.setWidgetResizable(True)
        self.groupscrollbartest.setLayout(self.mainHBOX_param_scene)
        self.groupscrolllayouttest.addWidget(scroll)

        self.tab_ModelSelect.setLayout(self.groupscrolllayouttest)

    def eventFilter(self, widget, event):
        if (event.type() == QEvent.Wheel) :
            # get which key is pressed 
            # if the key is a number, put the number in 'num' variable
            # get on which QLineEdit the wheel was make
            # set the text of that QLineEdit to previous value +- num

            event.ignore()
        return QWidget.eventFilter(self, widget, event) 

def main():
    app = QApplication(sys.argv)
    ex = SurfViewer(app)
    ex.setWindowTitle('window')
    # ex.showMaximized()
    ex.show()
    sys.exit(app.exec_( ))


if __name__ == '__main__':
    main()  

I tried to something with wheelevent but as mention, I don't enter in this function because the scroll bar is activated first. I tried to test if the wheel event happend on a QLineEdit but I even struggle to do that...

What I'm seeking to do is when I do a wheelevent with the mouse on a QlineEdit with the '5' key pressed, I want increase or decrease the QLineEdit text by 5 according to the direction of the mouse wheel.

I red some post with eventfilter (as How to get Click Event of QLineEdit in Qt?) but I don't understand how does this work.

In my eventFilter function, I need to do several step:

# get which key is pressed 
# if the key is a number, put the number in 'num' variable
# get on which QLineEdit the wheel was make
# set the text of that QLineEdit to previous value +- num

but I don't know how to make them. In particular getting the pressed key and knowing on which QlineEdit the wheel was made.

ymmx
  • 4,769
  • 5
  • 32
  • 64

1 Answers1

3

If you wish that all QLineEdit have that behavior then it is appropriate that you create your own class and overwrite the necessary events, to avoid that when you move the scroll when the pointer is inside the QLineEdit and pressing an established key, we accept the event so that it does not propage.

Another recommendation is not to use the 5 key since this is a text that QLineEdit can handle causing problems, for this you can use the SHIFT key:

class LineEdit(QLineEdit):
    KEY = Qt.Key_Shift
    def __init__(self, *args, **kwargs):
        QLineEdit.__init__(self, *args, **kwargs)
        self.isKeyPressed = False

    def keyPressEvent(self, event):
        if event.key() == LineEdit.KEY:
            self.isKeyPressed = True
        QLineEdit.keyPressEvent(self, event)

    def keyReleaseEvent(self, event):
        if event.key() == LineEdit.KEY:
            self.isKeyPressed = False
        QLineEdit.keyReleaseEvent(self, event)

    def wheelEvent(self, event):
        if self.isKeyPressed:
            delta = 1 if event.angleDelta().y() > 0 else -1
            fn = self.font()
            fn.setPointSize(fn.pointSize() +  delta)
            self.setFont(fn)
            event.accept()

The complete example:

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys

class LineEdit(QLineEdit):
    KEY = Qt.Key_Shift
    def __init__(self, *args, **kwargs):
        QLineEdit.__init__(self, *args, **kwargs)
        self.isKeyPressed = False

    def keyPressEvent(self, event):
        if event.key() == LineEdit.KEY:
            self.isKeyPressed = True
        QLineEdit.keyPressEvent(self, event)

    def keyReleaseEvent(self, event):
        if event.key() == LineEdit.KEY:
            self.isKeyPressed = False
        QLineEdit.keyReleaseEvent(self, event)

    def wheelEvent(self, event):
        if self.isKeyPressed:
            delta = 1 if event.angleDelta().y() > 0 else -1
            fn = self.font()
            fn.setPointSize(fn.pointSize() +  delta)
            self.setFont(fn)
            event.accept()

class SurfViewer(QMainWindow):
    def __init__(self, parent=None):
        super(SurfViewer, self).__init__()
        self.parent = parent

        self.centralTabs= QTabWidget()
        self.setCentralWidget(self.centralTabs)
        self.setFixedWidth(200)
        self.setFixedHeight(200)

        #tab Model selection
        self.tab_ModelSelect = QWidget()
        self.centralTabs.addTab(self.tab_ModelSelect,"Label")


        self.groupscrolllayouttest = QHBoxLayout() ####
        self.groupscrollbartest = QGroupBox() ####


        self.mainHBOX_param_scene = QVBoxLayout()
        for i in range(10):
            le = LineEdit(str(i))
            le.setFixedWidth(200)
            self.mainHBOX_param_scene.addWidget(le) 
        self.installEventFilter(self)

        scroll = QScrollArea()
        widget = QWidget(self)
        widget.setLayout(QVBoxLayout())
        widget.layout().addWidget(self.groupscrollbartest)
        scroll.setWidget(widget)
        scroll.setWidgetResizable(True)
        self.groupscrollbartest.setLayout(self.mainHBOX_param_scene)
        self.groupscrolllayouttest.addWidget(scroll)
        self.tab_ModelSelect.setLayout(self.groupscrolllayouttest)

def main():
    app = QApplication(sys.argv)
    ex = SurfViewer(app)
    ex.setWindowTitle('window')
    # ex.showMaximized()
    ex.show()
    sys.exit(app.exec_( ))


if __name__ == '__main__':
    main()  
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • oh, nice ! Not exactly what I was expecting because I need to click on the `QLineEdit` for it to consider the key events. So if I maintain the key down and release it outside the `QLineEdit` it just don't consider the `keyReleaseEvent`. Maybe using the wheel + a Key together was a bad idea. – ymmx Feb 13 '18 at 15:08
  • @ymmx Do you want all QLineEdit to change size with a single event? I understood that you wanted it to be done one by one. please explain me in more detail of what you want. – eyllanesc Feb 13 '18 at 15:12
  • What i would like is: when the mouse is on a particular QlineEdit and the mouse wheel is activated (event), if a key is also pressed (the shift key for instance) at the moment the wheel was activated, then I want upade the text of the particular QLineEdit the mouse being over (just this one). Therefore, the only issue in your example is that the `isKeyPressed` boolean is not updated when the key is kept pressed and the mouse is changing of QLineEdit position. – ymmx Feb 13 '18 at 16:12
  • @ymmx I do not understand you, my code does just what you say. You could explain the mouse. isKeyPressed should not change since the key is still pressed, the keyPressEvent event is called when the key is pressed, and the keyReleaseEvent event is triggered when the key is released. Why do you want to change isKeyPressed? – eyllanesc Feb 13 '18 at 16:19
  • for instance if the mouse is inside the first QLineEdit end I press the key, I enter in the `keyPressEvent` function (of the first QLineEdit), but if I maintain the key pressed and I move the mouse outside the first QLineEdit (to the second one) then the `keyReleaseEvent` is not call for the first QLineEdit. If then I go back with the mouse to the first QLineEdit, I don't need to press the key to resize the font because `self.isKeyPressed` is still True (for the first QLineEdit I mean). maybe the keyEvent should be part of the parent of QLineEdits and not part of the class `LineEdit`? – ymmx Feb 14 '18 at 08:01
  • I found something that will do the trick. `def wheelEvent(self, event): if QApplication.keyboardModifiers() == Qt.ControlModifier:` so instead updating each time a key is pressed, I look at the keyboardModifiers if the ctrl key is pressed. When using that, I don't have the previous issue anymore. – ymmx Feb 14 '18 at 11:51