Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: vintik от Июнь 04, 2013, 18:03



Название: [РЕШЕНО почти] grabMouse in QDialog
Отправлено: vintik от Июнь 04, 2013, 18:03
Всем привет, столкнулся с проблемой, самостоятельно решить не могу.

Конечная цель уметь вызывать в приложении диалог, который бы перехватывал и обрабатывал все события мыши (в частности события колёсика).

Делаю примерно так (хотя пробовал по-всякому - но работать заставить не удалось)

Код:
void MainWindow::on_menuModal_dialog_triggered(QAction *action)
{
    modal_dialog_wrapper dialog;
    dialog.exec();
}

где:

Код:
int modal_dialog_wrapper::exec()
{
    show(); // это из-за того что в хелпе написано Note: Only visible widgets can grab mouse input. If isVisible() returns false for a widget, that widget cannot call grabMouse().
    grabMouse();
    int ret = QDialog::exec();
    releaseMouse();
    return ret;
}

Не работает и всё тут.
Попробовал написать совсем простой пример

Код:
#include <QApplication>
#include <QWidget>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.show();
    w.grabMouse();
    // w.grabMouse();
    // w.grabMouse();
    // w.grabMouse();
    // w.grabMouse();
    // w.grabMouse();
    return a.exec();
}

Не работает. Однако если раскомментить повторные вызовы w.grabMouse(); - работает.

Юзаю Qt-4.8.3. Ось kubuntu 12.10


Название: Re: grabMouse in QDialog
Отправлено: gil9red от Июнь 04, 2013, 18:12
Код:
#include <QApplication>
#include <QWidget>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.exec();
    return a.exec();
}


Название: Re: grabMouse in QDialog
Отправлено: vintik от Июнь 04, 2013, 18:26
Код:
#include <QApplication>
#include <QWidget>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.exec();
    return a.exec();
}

Не понял ответа - тут просто будет создан виджет и всё. Никаким захватом мыши и не пахнет.
Ведь смысл перехватывать ВСЕ нажатия, даже мимо виджета.


Название: Re: grabMouse in QDialog
Отправлено: gil9red от Июнь 04, 2013, 18:29
Тьфу, не обратил внимание
замените QWidget на QDialog
и вызовите у него метод exec()

Код:
QDialog w;
w.exec();

окно станет модальным


Название: Re: grabMouse in QDialog
Отправлено: vintik от Июнь 04, 2013, 18:39
Ок, усложняем задачу. Такой код
Код:
#include <QApplication>
#include "widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

Код:
#ifndef WIDGET_H
#define WIDGET_H

#include <QtGui>

namespace Ui {
class Widget;
}

class Widget : public QDialog
{
    Q_OBJECT
   
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    void mousePressEvent(QMouseEvent *event);
    void wheelEvent(QWheelEvent *event);
private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

Код:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->frame->show();
    ui->frame->grabMouse();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "mousePressEvent";
}

void Widget::wheelEvent(QWheelEvent *event)
{
    qDebug() << "wheelEvent";
}


ui файл - просто виджет, внутри которого установлен QFrame (ui->frame)
Под kubuntu 12.10 мышь не будет захвачена


Название: Re: grabMouse in QDialog
Отправлено: gil9red от Июнь 04, 2013, 19:16
Уберите этот код
Код:
    ui->frame->show();
    ui->frame->grabMouse();


main.cpp:
Код:
#include <QApplication>
#include "widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.exec();

    return a.exec();
}


Или я вообще ничего не могу понять :)


Название: Re: grabMouse in QDialog
Отправлено: vintik от Июнь 04, 2013, 19:31
мне необходимо, чтобы после отображения на экране диалога любые события мыши были перехвачены.
Даже если делается клик мимо диалога или колесо вращается не над ним мне нужно отловить это событие в этом диалоге.
Согласно докам для этого служит метод grabMouse, но вот как его заставить правильно работать - я не понимаю


Название: Re: grabMouse in QDialog
Отправлено: GreatSnake от Июнь 04, 2013, 20:36
QWidget::show() асинхронный вызов, т.е. наличие окна после него не является обязательным.
Перегрузи QWidget::showEvent() и уже в нём делай граб.


Название: Re: grabMouse in QDialog
Отправлено: vintik от Июнь 05, 2013, 00:43
QWidget::show() асинхронный вызов, т.е. наличие окна после него не является обязательным.
Перегрузи QWidget::showEvent() и уже в нём делай граб.

Это интересно, спасибо, не знал

попробовал сделать так, но не заработало

Код:
void Widget::showEvent(QShowEvent *event)
{
    ui->frame->grabMouse();
}

Вообще, в доке написано, что это событие (showEvent) - если оно non spontaneous - приходит до появления окна (а оно именно non spontaneous).
А как бы получить уведомление от оконной системы, что окно уже реально видимо?
Кстати, попробовал сделать grabMouse() с задержкой

Код:
QTimer::singleShot(100, this, SLOT(timeout_slot())); // в timeout_slot() делаю ui->frame->grabMouse()

и так вот работает. Так что мы на верном пути, осталось понять как его "завершить"