Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt GUI _ Перехватить все события мыши

Автор: Obey-Kun 31.1.2011, 4:19

Здравствуйте. Проблема такая. У меня в одном виджете есть ручной скроллинг. Зажали правую кнопку → тащим. Оно прокручивается. Причём когда курсор достигает края экрана, он перепрыгивает на противоположную его (экрана) сторону — как в Okular.

Теперь хочу реализовать прокрутку с зажатым пробелом. То есть так: зажали пробел → двигаем курсором. Проблема в том, что если мы зажимаем на виджете кнопку мыши и водим курсором, то он ловит все события с неё — даже если она выйдет за края окна. Как можно заставить его делать так же в случае с пробелом?

Кто-нибудь такое реализовывал?

upd: вот только что нашёл по теме http://forum.sources.ru/index.php?showtopic=302429 (правда, у него там ничего и не получилось, вроде).

Автор: Алексей1153 31.1.2011, 10:43

>>Как можно заставить его делать так же в случае с пробелом?

Цитата
void QWidget::grabMouse ()
Grabs the mouse input.

This widget receives all mouse events until releaseMouse() is called; other widgets get no mouse events at all. Keyboard events are not affected. Use grabKeyboard() if you want to grab that.

Warning: Bugs in mouse-grabbing applications very often lock the terminal. Use this function with extreme caution, and consider using the -nograb command line option while debugging.

It is almost never necessary to grab the mouse when using Qt, as Qt grabs and releases it sensibly. In particular, Qt grabs the mouse when a mouse button is pressed and keeps it until the last button is released.

Note: Only visible widgets can grab mouse input. If isVisible() returns false for a widget, that widget cannot call grabMouse().

Note: (Mac OS X developers) For Cocoa, calling grabMouse() on a widget only works when the mouse is inside the frame of that widget. For Carbon, it works outside the widget's frame as well, like for Windows and X11.

See also releaseMouse(), grabKeyboard(), and releaseKeyboard().


вроде это :)

во избежание залочивания по ошибке можно запустить таумер, который будет проверять, не отпустили ли пробел. Если отпустили - релизим мышь, останавливаем таймер

Автор: igor_bogomolov 31.1.2011, 10:48

Цитата(Алексей1153 @ 31.1.2011, 10:43) *
который будет проверять, не отпустили ли пробел. Если отпустили - релизим мышь, останавливаем таймер
ты думаешь всё так просто ;) Попробуй сделать такой эксперимент

Автор: Алексей1153 31.1.2011, 11:07

igor_bogomolov, а что именно должно быть не просто ? Ну а так - на Qt не делал ещё подобное.


Автор: igor_bogomolov 31.1.2011, 11:20

Цитата(Алексей1153 @ 31.1.2011, 11:07) *
igor_bogomolov, а что именно должно быть не просто ? Ну а так - на Qt не делал ещё подобное.
нет возможности средствами Qt узнать нажат ли пробел, или любая другая кнопка, за исключением модификаторов. Да и события от клавиатуры посмотри как генерируются. Если ты нажмёшь пробел, тебе с частотой 400мс (это настраивается) быдут последовательно приходить события keyPressEvent, keyReleaseEvent. Т.е. я так с ходу не могу даже сообразить как свою таблицу состояний клавиатуры сделать. Видимо здесь без использования API системы не обойтись.

Всё это конечно лишь моё мнение, возможно я что то упустил в документации.

Автор: Алексей1153 31.1.2011, 11:23

igor_bogomolov, при отпускании должна вызваться keyReleaseEvent, там следует сбросить флаг нажатости (просто мембер класса), взведённый по началу grab

Таймер увидит, что флаг сброшен и релизнет мышку + сам себя остановит. Вроде всё логично

Автор: igor_bogomolov 31.1.2011, 11:25

ты опять меня не понял. keyReleaseEvent будет приходить каждые 400мс, даже когда кнопка нажата

Автор: Алексей1153 31.1.2011, 11:27

как так

щас проверю

Автор: igor_bogomolov 31.1.2011, 11:33

ну ё моё, ну Алексей, ты что? События нажатия кнопки мыши будет повторяться пока ты не отпустишь кнопку. Открой любой текстовый редактор, нажми букву какую-нибудь и держи. Сколько раз она напечатается? Дофига, она будет печататься пока не отпустишь кнопку. Так же и в программе, ты будешь с оределённым интервалом получать события keyPressEvent, keyReleaseEvent. И будет это происходить пока ты не отпустишь кнопку. Последнее событие будет конечно же keyReleaseEvent

Автор: Алексей1153 31.1.2011, 11:38

оть :)

#include <QtDebug>
void CMy::keyPressEvent(QKeyEvent *e)
{
    qDebug()<<"press";    
}

void CMy::keyReleaseEvent(QKeyEvent *e)
{
    if(!e->isAutoRepeat())
    {
        qDebug()<<"release";    
    }
    else
    {
        qDebug()<<"repeating release";    
    }
}


Цитата
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
release


Цитата(igor_bogomolov @ 31.1.2011, 13:33) *
События нажатия кнопки мыши будет повторяться пока ты не отпустишь кнопку

мыши ?

Автор: igor_bogomolov 31.1.2011, 11:39

Цитата(Алексей1153 @ 31.1.2011, 11:38) *
мыши ?
очепятка, клавиатуры конечно

Автор: Алексей1153 31.1.2011, 11:40

ну неважно - способ я только что нашёл и проверил. :)

Автор: igor_bogomolov 31.1.2011, 11:45

Цитата(Алексей1153 @ 31.1.2011, 11:38) *
e->isAutoRepeat()
ага, уже что то. Это я упустил.
Осталось проверить, что будет если при нажатии на пробел генерировать mousePressEvent, а при отпускании mouseReleaseEvent

Автор: Алексей1153 31.1.2011, 11:56

ага

void CMy::mousePressEvent(QMouseEvent *)
{
    qDebug()<<"MOUSE press";    
}

void CMy::mouseReleaseEvent(QMouseEvent *)
{
    qDebug()<<"MOUSE release";    
}


Цитата
press
repeating release
press
repeating release
press
...
repeating release
press
repeating release
press
MOUSE press
repeating release
press
repeating release
press
MOUSE release
repeating release
press
repeating release
press
...

Автор: igor_bogomolov 31.1.2011, 12:00

Цитата(Алексей1153 @ 31.1.2011, 11:56) *
ага
вот только события перемещения мыши при этом не приходят. Мне, по крайней мере этого добиться не удалось пока

Автор: Алексей1153 31.1.2011, 12:10

да ну, всё приходит. Я ж не выводил их

void CMy::mouseMoveEvent(QMouseEvent *)
{
    qDebug()<<"MOUSE move";    
}



Цитата
press
MOUSE move
MOUSE move
repeating release
press
MOUSE move
MOUSE move
MOUSE move
repeating release
press
MOUSE move
MOUSE move
repeating release


вот лог без всякой правки, что нужно - всё засветилось

Раскрывающийся текст
Цитата
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
MOUSE press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
MOUSE move
repeating release
press
MOUSE move
MOUSE move
repeating release
press
MOUSE move
MOUSE move
repeating release
press
MOUSE move
MOUSE move
MOUSE move
repeating release
press
MOUSE move
repeating release
press
repeating release
press
MOUSE move
MOUSE move
repeating release
press
MOUSE move
MOUSE move
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
MOUSE release
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
repeating release
press
release
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move
MOUSE move

Автор: igor_bogomolov 31.1.2011, 12:22

Алексей1153, мышкой где водишь, над формой? Приложи код.

Автор: Алексей1153 31.1.2011, 12:52

да, над формой. Я же не грабил мышь. Пробовал в рабочем проекте, весь код для этого лога я привёл. Вечером попробую реализовать задачу ТС, если время будет

Автор: igor_bogomolov 31.1.2011, 13:00

Цитата(Алексей1153 @ 31.1.2011, 12:52) *
да, над формой.
ну так в этом вся соль. Читай первое сообщение и как задача поставлена. Нужно ловить сообщения мыши когда она находится в не формы

Автор: Алексей1153 31.1.2011, 13:35

Цитата(Алексей1153 @ 31.1.2011, 12:43) *
void QWidget::grabMouse ()
Grabs the mouse input.

This widget receives all mouse events until releaseMouse() is called; other widgets get no mouse events at all


да, я помню :)

Автор: igor_bogomolov 31.1.2011, 13:40

Цитата(Алексей1153 @ 31.1.2011, 13:35) *
да, я помню :)
Ок. Жду готовый пример. У меня так ничего и не получилось.


Автор: Алексей1153 31.1.2011, 14:30

вот по ТЗ ТС (каламбур прям)

даже таймер не понадобился ) Релизиться будет всегда по щелчку мыши, если что

чорд, опять рар не прицепился

 scrolltest.zip ( 3.25 килобайт ) : 85
 

Автор: Obey-Kun 31.1.2011, 14:30

grabMouse() пробовал. Почему-то после этого виджет, в котором я это вызвал, вообще перестаёт реагировать на мышь, т.е. вообне не входит в mouseMoveEvent... Есть идеи?

Автор: Алексей1153 31.1.2011, 14:31

Obey-Kun, я подправил пост - там аттач смотри

Автор: Obey-Kun 31.1.2011, 14:49

Ок. Сейчас в метро буду ехать — посмотрю :).

Автор: Алексей1153 31.1.2011, 14:55

Obey-Kun, только вагоны не двигай )))

Автор: igor_bogomolov 31.1.2011, 14:55

Алексей1153, понял почему у меня не получалось. Сам всех ругаю что не внимательно читают документацию, а сам такой же.

Цитата
In particular, Qt grabs the mouse when a mouse button is pressed and keeps it until the last button is released.
Я grabMouse() в конструкторе еще вызывал, поэтому у меня ничего не работало.

Автор: Алексей1153 31.1.2011, 14:57

igor_bogomolov, я в винде использовал SetCapture()/ReleaseCapture() - вот я по аналогии всё и сделал. Там все те же самые проблемы возникают

Автор: Obey-Kun 31.1.2011, 17:59

А! Понял, почему не работало! Я делал grabMouse() во view (qgraphicsview), а надо делать во view->viewport().

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)