Russian Qt Forum
Май 16, 2024, 15:35 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО] QGraphicsScene - захват событий мыши.  (Прочитано 8588 раз)
CriDos
Гость
« : Март 27, 2016, 07:24 »

Здравствуйте.
Имеется сцена QGraphicsScene, на сцену добавляется объект класса Item.
Класс Item наследуется от QGraphicsRectItem и у него переопределён метод hoverEnterEvent.
Также у Item в конструкторе задаётся setAcceptHoverEvents(true), т.к. в дальнейшем предполагается взаимодействие с этим объектом с помощью мыши.
Проблема в том, что если нажать мышью на сцене и не отпуская кнопки, провести курсором над объектом Item, метод hoverEnterEvent у объекта Item не будет вызван, более того, объекту вообще не будут отправляться события (bool QGraphicsItem::sceneEvent(QEvent *event)).
После более детального изучения вопроса, понял что после действия mousePressEvent, происходит захват мыши.
Т.е. получается, события в любом случае получает только объект с grabberMouse.
Есть ли более-менее простой способ, захватить мышь и другими объектами сцены?

Пример в аттаче.
« Последнее редактирование: Март 28, 2016, 12:22 от CriDos » Записан
CriDos
Гость
« Ответ #1 : Март 27, 2016, 08:42 »

Нужное поведение сцены и объектов реализовано в проекте Fritzing (https://github.com/fritzing/fritzing-app), который на Qt с открытыми сорцами.
Пример.gif
Но в Fritzing, если я ничего не путаю, реализовано это с помощью ручного слежения за событиями мыши и своих реализаций hover*Item в наследниках QGraphicsView... Грустный
Код:
void SketchWidget::hoverEnterItem(QGraphicsSceneHoverEvent * event, ItemBase * item) {
if(m_infoViewOnHover || currentlyInfoviewed(item)) {
InfoGraphicsView::hoverEnterItem(event, item);
}

Wire * wire = dynamic_cast<Wire *>(item);
if (wire != NULL) {
if (canChainWire(wire)) {
bool segment = wire->connector0()->chained() && wire->connector1()->chained();
bool disconnected = wire->connector0()->connectionsCount() == 0 &&  wire->connector1()->connectionsCount() == 0;
statusMessage(QString("%1 to add a bendpoint %2")
.arg(disconnected ? tr("Double-click") : tr("Drag or double-click"))
.arg(segment ? tr("or alt-drag to move the segment") : tr("")));
m_lastHoverEnterItem = item;
}
}
}
« Последнее редактирование: Март 27, 2016, 08:46 от CriDos » Записан
CriDos
Гость
« Ответ #2 : Март 27, 2016, 11:08 »

Не всё так просто. Грустный
QGraphicsItem does not become a mouse grabber
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Март 27, 2016, 11:56 »

Демонстрация (стандартное приложение Qt Widgets, mainwindow.cpp):
Желание покопаться быстро исчезает если надо выцапарывать Ваш текст, создавать проект и.т.п. Выкладывайте компилябельный проект в zip
Есть ли более-менее простой способ, захватить мышь и другими объектами сцены?
Неясно какого поведения Вы хотите добиться. Юзер нажал на место в сцене где нет айтема и тащит мышь. Что должно происходить?
Записан
CriDos
Гость
« Ответ #4 : Март 27, 2016, 12:09 »

Выкладывайте компилябельный проект в zip
Предполагал что так будет легче, ибо создать проект и вставить текст проще (имхо), чем скачать, распаковать, открыть и настроить проект Улыбающийся
Записан
CriDos
Гость
« Ответ #5 : Март 27, 2016, 12:16 »

Цитировать
Неясно какого поведения Вы хотите добиться. Юзер нажал на место в сцене где нет айтема и тащит мышь. Что должно происходить?
Немного переработал демонстрационный пример.
На сцене 2 объекта.
Задача: при нажатии ЛКМ (mousePressEvent) на одном из объектов/сцене, без последующего отжатия кнопки (mouseReleaseEvent), оба объекта должны продолжать получать события hoverEnterEvent и hoverLeaveEvent при перемещении курсора мыши над ними.
« Последнее редактирование: Март 27, 2016, 12:34 от CriDos » Записан
CriDos
Гость
« Ответ #6 : Март 28, 2016, 02:46 »

Вопрос решён.
Судя по исходникам QGraphicsScene: https://github.com/qtproject/qtbase/blob/9c1d3bc253abd4418f3050d19ec5f05bef3ada97/src/widgets/graphicsview/qgraphicsscene.cpp
Код:
void QGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    Q_D(QGraphicsScene);
    if (d->mouseGrabberItems.isEmpty()) {
        if (mouseEvent->buttons())
            return;
        QGraphicsSceneHoverEvent hover;
        _q_hoverFromMouseEvent(&hover, mouseEvent);
        mouseEvent->setAccepted(d->dispatchHoverEvent(&hover));
        return;
    }

    // Forward the event to the mouse grabber
    d->sendMouseEvent(mouseEvent);
    mouseEvent->accept();
}
дело не в граббере а банальной проверке нажатых кнопок мыши во время движения мыши...
Код:
if (mouseEvent->buttons())
    return;
Т.е. для того, чтобы события мыши продолжали отправляться объектам, даже при зажатой кнопке мыши, достаточно в перегруженном методе QGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) указать event->setButtons(Qt::NoButton).
Или в QGraphicsView::mouseMoveEvent(QMouseEvent *event) передавать предку свой QMouseEvent:
Код:
    QMouseEvent customEvent(event->type(), event->pos(), Qt::NoButton, Qt::NoButton, event->modifiers());
    QGraphicsView::mouseMoveEvent(&customEvent);
« Последнее редактирование: Март 28, 2016, 03:51 от CriDos » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.051 секунд. Запросов: 22.