Как исправить: пользовательский QGraphicsItem, получающий координаты mousePressEvent поздно / запаздывает? - PullRequest
0 голосов
/ 28 сентября 2019

У меня есть «стандартное» приложение QW5 Qt5 с MainWindow, которое включает QGraphicsView в mainwindow.ui, созданном в QtCreator.Этот QGraphicsView имеет свою сцену, установленную на простой подкласс QGraphicsScene, который имеет большой прямоугольник на заднем плане, который является подклассом QGraphicsRectItem, который переопределяет обработчики mousePressEvent () и mouseReleaseEvent () QGraphicsRectItem.Запуск на Ubuntu 18.04, который не должен иметь значения, но только в случае ...

Все работает, кроме ... 2-го и последующих раз, когда я нажимаю левую (или любую) кнопку мыши, сообщаются координатыв QGraphicsSceneMouseEvent mousePressEvent buttonDownScenePos «устарели» - так же, как и предыдущий щелчок мыши, а не в новом месте, где находится мышь, когда произошел новый щелчок.MouseReleaseEvent сообщает координаты, как и ожидалось.

Есть ли способ получить buttonDownScenePos mousePressEvent, чтобы он оставался текущим с фактическим положением мыши при нажатии вместо прежнего местоположения мыши?

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

Соответствующий код:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

class Board;
class BoardScene;
#include <QMainWindow>
#include <QPointer>
#include "board.h"
#include "boardscene.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{ Q_OBJECT
public:
    explicit  MainWindow(QWidget *parent = nullptr);
             ~MainWindow();
        void  drawBoard();

private:
     Ui::MainWindow *ui;
     QPointer<Board> board;
QPointer<BoardScene> boardScene;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    board      = new Board( this );
    boardScene = new BoardScene( board, this );
    ui->boardView->setScene( boardScene );
    ui->boardView->setDragMode( QGraphicsView::ScrollHandDrag );
    ui->boardView->scale( 40.0, 40.0 );
    drawBoard();
}

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

void MainWindow::drawBoard()
{ }

boardscene.h

#ifndef BOARDSCENE_H
#define BOARDSCENE_H

class Board;
#include <QGraphicsScene>
#include "board.h"
#include "boardrect.h"

class BoardScene : public QGraphicsScene
{ Q_OBJECT
public:
            BoardScene( Board *pbp, QObject *parent = nullptr );
      void  drawGrid();

     Board *bp;
    QBrush  backBrush,blackBrush,whiteBrush;
      QPen  linePen;
};

#endif // BOARDSCENE_H

boardscene.cpp

#include "boardscene.h"
#include <QGraphicsLineItem>
#include <QGraphicsRectItem>

BoardScene::BoardScene( Board *pbp, QObject *parent ) : QGraphicsScene ( parent )
{ bp = pbp;
  backBrush  = QBrush( QColor( 224,152, 64 ) );
  blackBrush = QBrush( QColor(   0,  0,  0 ) );
  whiteBrush = QBrush( QColor( 255,255,255 ) );
  linePen    = QPen  ( QColor(   0,  0,  0 ) );
  linePen.setWidth( 0 );
  drawGrid();
}

void BoardScene::drawGrid()
{ QGraphicsLineItem *lip;
  BoardRect *rip;
  setBackgroundBrush( blackBrush );
  rip = new BoardRect( QRectF( -2.0, -2.0, (qreal)(bp->Xsize +3), (qreal)(bp->Ysize + 3) ), nullptr );
  rip->setBrush( backBrush );
  rip->setPen( linePen );
  addItem( rip );

  for ( int x = 0; x < bp->Xsize; x++ )
    { lip = addLine( QLineF( (qreal)x, 0.0, (qreal)x, (qreal)(bp->Ysize - 1) ), linePen );
      lip->setAcceptedMouseButtons( Qt::NoButton );
    }
  for ( int y = 0; y < bp->Ysize; y++ )
    { lip = addLine( QLineF( 0.0, (qreal)y, (qreal)(bp->Xsize - 1), (qreal)y ), linePen );
      lip->setAcceptedMouseButtons( Qt::NoButton );
    }
}

boardrect.h

#ifndef BOARDRECT_H
#define BOARDRECT_H

#include <QGraphicsRectItem>
#include <QGraphicsSceneMouseEvent>


class BoardRect : public QGraphicsRectItem
{
public:
          BoardRect( const QRectF &rect, QGraphicsItem *parent = nullptr );
         ~BoardRect() {}

protected:
    void  mousePressEvent(QGraphicsSceneMouseEvent *event);
    void  mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};

#endif // BOARDRECT_H

boardrect.cpp

#include "boardrect.h"

BoardRect::BoardRect( const QRectF &rect, QGraphicsItem *parent ) : QGraphicsRectItem( rect, parent )
{}

void  BoardRect::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ QString msg = QString("press %1 %2").arg(event->buttonDownScenePos(event->button()).rx())
                                      .arg(event->buttonDownScenePos(event->button()).ry());
  qDebug( qPrintable( msg ) );
  QGraphicsRectItem::mousePressEvent(event);
  event->accept();
}

void  BoardRect::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ QString msg = QString("release %1 %2").arg(event->buttonDownScenePos(event->button()).rx())
                                        .arg(event->buttonDownScenePos(event->button()).ry());
  qDebug( qPrintable( msg ) );
  QGraphicsRectItem::mousePressEvent(event);
  event->accept();
}

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

Однако при втором и последующих щелчках mousePressEvent сообщает те же координаты, что и предыдущие события mousePress и Release, а mouseReleaseEvent сообщаеткоординаты, где кнопка мыши «пошла вниз» в текущем событии.

Последний бит странности: при нажатии влево, затем вправо, затем снова влево координата, сообщаемая mousePressEvent для 2-го левого щелчка - это предыдущая координата левого щелчка, пропуская координату правого щелчка, чтобы вернуться туда, где кнопка мыши нажала последний левый щелчок.

Есть идеи?Спасибо.

Ответы [ 2 ]

0 голосов
/ 30 сентября 2019

QGraphicsSceneMouseEvent::buttonDownPos(Qt::MouseButton button)

Возвращает положение курсора мыши в координатах элемента, где была нажата указанная кнопка.

Возвращает координаты графического элемента, по которому вы щелкаетена (как сказано в документации).Может быть, вы просто нажмите в том же месте?Если вы хотите положение сцены, просто используйте mapToScene или QGraphicsSceneMouseEvent::buttonDownScenePos(Qt::MouseButton button) или event->scenePos().

PS.и используйте QPointF::x() и QPointF::y() вместо rx() и ry().Вам не нужна ссылка и манипулирование позицией.

0 голосов
/ 30 сентября 2019

У меня есть приложение, использующее те же компоненты: qgraphicsview и qgraphicsscene, составленные из некоторого числа qgraphicsitems.Это виртуальная MIDI фортепианная клавиатура на тот случай, если вы захотите взглянуть на код.В моем случае все элементы qgraphics (клавиши пианино) имеют setAcceptedMouseButtons(Qt::NoButton), а события мыши обрабатываются на уровне сцены, а не на графическом элементе.Я никогда не наблюдал такой проблемы, как ваша.

...