Обновите QLineEdit в WheelEvent, когда полоса прокрутки уже установлена

Я пытаюсь обновить QLineEdit, когда я вращаю колесико мыши и одновременно нажимаю цифру на клавиатуре. К сожалению, я не вижу события колеса мыши для виджета QLineEdit, поэтому я не понимаю, как я могу установить сигнал для каждого QLineEdit. Другая проблема, с которой я столкнулся, заключается в том, что QLineEdit уже находятся в среде полосы прокрутки, я не могу обнаружить событие с полным колесом, потому что сначала выполняется прокрутка.

Например, с этим кодом:

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

Я пытался что-то сделать с wheelevent, но, как уже упоминалось, я не вхожу в эту функцию, потому что сначала активируется полоса прокрутки. Я пытался проверить, произошло ли событие с колесом на QLineEdit, но мне даже трудно это сделать ...

То, что я пытаюсь сделать, - это когда я выполняю событие с указателем мыши на QlineEdit с нажатой клавишей «5», я хочу увеличить или уменьшить текст QLineEdit на 5 в соответствии с направлением колеса мыши.

Я красил сообщение с eventfilter (как Как получить событие щелчка для QLineEdit в Qt?), но я не понимаю, как это работает.

В моей функции eventFilter мне нужно сделать несколько шагов:

# 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

но я не знаю, как их сделать. В частности, получение нажатой клавиши и знание того, на каком QlineEdit было создано колесо.


person ymmx    schedule 13.02.2018    source источник


Ответы (1)


Если вы хотите, чтобы все QLineEdit имели такое поведение, тогда целесообразно создать свой собственный класс и перезаписать необходимые события, чтобы избежать этого, когда вы перемещаете прокрутку, когда указатель находится внутри QLineEdit и нажимаете установленную клавишу, мы принимаем событие так что он не распространяется.

Другая рекомендация - не использовать клавишу 5, поскольку это текст, который QLineEdit может обрабатывать, вызывая проблемы, для этого вы можете использовать клавишу SHIFT:

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

Полный пример:

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()  
person eyllanesc    schedule 13.02.2018
comment
о, классно ! Не совсем то, что я ожидал, потому что мне нужно щелкнуть QLineEdit, чтобы он рассмотрел ключевые события. Так что, если я буду держать ключ нажатым и отпущу его за пределами QLineEdit, он просто не учитывает keyReleaseEvent. Возможно, использование колеса и ключа вместе было плохой идеей. - person ymmx; 13.02.2018
comment
@ymmx Вы хотите, чтобы все QLineEdit изменяли размер одним событием? Я понял, что вы хотели, чтобы это делали по одному. пожалуйста, объясните мне подробнее, что вы хотите. - person eyllanesc; 13.02.2018
comment
Я бы хотел: когда мышь находится на определенном QlineEdit и колесико мыши активировано (событие), если также была нажата клавиша (например, клавиша Shift) в момент активации колеса, тогда я хочу, чтобы текст конкретного QLineEdit, над которым находится курсор (только этого). Следовательно, единственная проблема в вашем примере заключается в том, что логическое значение isKeyPressed не обновляется, когда клавиша удерживается нажатой, а мышь меняет положение QLineEdit. - person ymmx; 13.02.2018
comment
@ymmx Я вас не понимаю, мой код делает именно то, что вы говорите. Вы могли бы объяснить мышь. isKeyPressed не должен изменяться, поскольку клавиша все еще нажата, событие keyPressEvent вызывается при нажатии клавиши, а событие keyReleaseEvent запускается при отпускании клавиши. Почему вы хотите изменить isKeyPressed? - person eyllanesc; 13.02.2018
comment
например, если мышь находится внутри первого конца QLineEdit, я нажимаю клавишу, я вхожу в функцию keyPressEvent (первого QLineEdit), но если я сохраняю нажатой клавишу и перемещаю мышь за пределы первого QLineEdit (ко второму ), то keyReleaseEvent не является вызовом для первого QLineEdit. Если затем я вернусь с помощью мыши к первому QLineEdit, мне не нужно будет нажимать клавишу, чтобы изменить размер шрифта, потому что self.isKeyPressed все еще имеет значение True (я имею в виду для первого QLineEdit). может быть, keyEvent должен быть частью родительского элемента QLineEdits, а не класса LineEdit? - person ymmx; 14.02.2018
comment
Я нашел кое-что, что поможет. def wheelEvent(self, event): if QApplication.keyboardModifiers() == Qt.ControlModifier: поэтому вместо обновления при каждом нажатии клавиши я смотрю на keyboardModifiers, если нажата клавиша ctrl. Когда я использую это, у меня больше нет предыдущей проблемы. - person ymmx; 14.02.2018