Событие PyQt4 MouseMove без MousePress

Мне нужно поймать, когда пользователь перемещает мышь по графическому интерфейсу, но не когда он держит кнопку мыши нажатой (что будет делать что-то другое).

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

MouseMoveEvent вызывается только тогда, когда мышь перемещается, пока нажата левая кнопка мыши, если, конечно, виджет не имеет «отслеживание мыши». Отслеживание мыши не подходит для меня, потому что графический интерфейс должен вести себя по-разному, когда мышь перемещается и нажимается левая кнопка мыши.

Есть ли встроенные методы для этого? (или просто любые умные идеи?)

например: есть ли способ проверить, нажата ли левая кнопка мыши в любой момент?
Или событие "наведения мыши", которое можно применить к QRect (координатам)?

Большое спасибо.


Windows 7 (32)
python 2.7
PyQt4


person Anti Earth    schedule 20.10.2011    source источник


Ответы (4)


Самый простой способ сделать это — установить фильтр событий в qApp:

from PyQt4 import QtGui, QtCore

class Window(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        widget = QtGui.QWidget(self)
        layout = QtGui.QVBoxLayout(widget)
        self.edit = QtGui.QLineEdit(self)
        self.list = QtGui.QListWidget(self)
        layout.addWidget(self.edit)
        layout.addWidget(self.list)
        self.setCentralWidget(widget)

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.MouseMove:
            if event.buttons() == QtCore.Qt.NoButton:
                pos = event.pos()
                self.edit.setText('x: %d, y: %d' % (pos.x(), pos.y()))
            else:
                pass # do other stuff
        return QtGui.QMainWindow.eventFilter(self, source, event)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    win = Window()
    win.show()
    app.installEventFilter(win)
    sys.exit(app.exec_())
person ekhumoro    schedule 20.10.2011
comment
Справедливости ради, вполне приличное решение. Разбавленные виджеты просто сбили меня с толку. - person Anti Earth; 10.11.2011

сначала вызовите метод setMouseTracking(True). Затем mouseMoveEvent будет запущен без нажатия какой-либо кнопки.

person HYRY    schedule 20.10.2011
comment
Я указал, что это не вариант, потому что мне нужно различать ответ в зависимости от того, нажата кнопка или нет. Отслеживание мыши не вариант для меня - person Anti Earth; 20.10.2011

Похоже, вы неправильно поняли, что делает mouseTracking. Это приводит только к срабатыванию mouseMoveEvent, и ничего больше. Другими словами, это именно то, что вам нужно.

Проверьте buttons() события, чтобы узнать, была ли нажата какая-либо кнопка:

Для событий перемещения мыши это все кнопки, которые были нажаты.

person Petr Viktorin    schedule 20.10.2011
comment
Имеет ли значение, является ли виджет, которому требуется отслеживание мыши, QMainWindow? Я не могу найти mouseTracking в ссылке на класс. - person Anti Earth; 20.10.2011
comment
QMainWindow не имеет функции setMouseTracking. Я попробовал предложенную вами процедуру с помощью виджета группового поля, но безуспешно. - person Anti Earth; 20.10.2011
comment
@AntiEarth: у него есть setMouseTracking. Он унаследован от QWidget. Посмотрите под QWidget. - person Avaris; 20.10.2011
comment
Почему у меня это не работает?!?!?! D: Я прибегал к QTimer и многопоточности. - person Anti Earth; 20.10.2011
comment
@AntiEarth Что произойдет, если вы попробуете эту функцию с QMainWindow? - person alexisdm; 20.10.2011
comment
'QMainWindow не имеет атрибута: setMouseTracking' - person Anti Earth; 22.10.2011
comment
@АнтиЗемля. QMainWindow наверняка имеет атрибут setMouseTracking - вы, должно быть, делаете что-то не так. - person ekhumoro; 22.10.2011
comment
Я использую PyQt4? Может ли это иметь значение? - person Anti Earth; 22.10.2011
comment
@АнтиЗемля. Нет. Вы можете легко ответить на подобные вопросы, импортировав модули PyQt4 в интерактивный сеанс python и используя автодополнение табуляции, dir() или что-то вроде hasattr(QMainWindow, 'setMouseTracking'). Это также самый простой способ проверить, что конкретные версии Qt и PyQt (или PySide), на которые вы ориентируетесь, поддерживают интересующие вас функции. - person ekhumoro; 22.10.2011

Как уже говорили люди, правильный подход заключается в вызове setMouseTracking(True) для виджета. Я хотел бы добавить, что, сделав это, вы можете различать движение мыши и перетаскивание мыши следующим образом:

def mouseMoveEvent(self, event):
    if event.buttons() == QtCore.Qt.NoButton:
        print "Simple mouse motion"
    elif event.buttons() == QtCore.Qt.LeftButton:
        print "Left click drag"
    elif event.buttons() == QtCore.Qt.RightButton:
        print "Right click drag"
person MarcTheSpark    schedule 26.03.2015
comment
Эй, когда мне было скучно и я посмотрел на Qt4, я нашел здесь ваш пример - я обнаружил, что вышеприведенное не «работает» для события NoButton, но работает для событий LeftButton и RightButton. Для меня это нормально, я хочу проверить функции мыши, включая щелчки — «перетаскивание» выполняет оба действия. - person Mark Rowlands; 01.05.2015