C++ 如何修复:自定义QGraphicsItem延迟/延迟接收MousePresseEvent坐标?

C++ 如何修复:自定义QGraphicsItem延迟/延迟接收MousePresseEvent坐标?,c++,qt,qgraphicsitem,qgraphicsrectitem,C++,Qt,Qgraphicsitem,Qgraphicsrectitem,我有一个“标准”的Qt5 QWidgets应用程序,在QtCreator中创建的MainWindow.ui中有一个包含QGraphicsView的主窗口。该QGraphicsView将其场景设置为QGraphicscene的一个简单子类,该子类的背景中有一个大矩形,该矩形是QGraphicsRecitem的一个子类,该子类重新实现QGraphicsRecitem的MousePresseEvent()和mouseReleaseEvent()处理程序。在Ubuntu18.04上运行,这不重要,只是以

我有一个“标准”的Qt5 QWidgets应用程序,在QtCreator中创建的MainWindow.ui中有一个包含QGraphicsView的主窗口。该QGraphicsView将其场景设置为QGraphicscene的一个简单子类,该子类的背景中有一个大矩形,该矩形是QGraphicsRecitem的一个子类,该子类重新实现QGraphicsRecitem的MousePresseEvent()和mouseReleaseEvent()处理程序。在Ubuntu18.04上运行,这不重要,只是以防万一

一切正常,除了。。。第二次及以后我按下鼠标左键(或任意)时,mousePressEvent的QGraphicsSceneMouseEvent buttonDownScenePos中报告的坐标是“过时的”-与上一次鼠标单击相同,而不是发生新单击时鼠标所在的新位置。mouseReleaseEvent按预期报告坐标

有没有办法让mousePressEvent的buttonDownScenePos在单击时与鼠标的实际位置保持一致,而不是与以前的鼠标位置保持一致

我觉得我在过去处理过一个类似的问题,它与双击处理有关,即在知道双击是否发生之前报告事件。在本例中,双击事件并不重要,但是如果能够在单击发生时立即响应,而不是等待发布事件,那就更好了

相关代码:

主窗口

#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
董事会现场

#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
在运行后的第一次单击中,报告的坐标与网格上单击鼠标的位置非常吻合,无论是按下还是释放,它们都显示了按钮按下的位置

但是,在第二次和以后的单击中,mousePressEvent报告与前一次mousePress和Release事件相同的坐标,而mouseReleaseEvent报告当前事件中鼠标按钮“下降”的坐标

最后一点奇怪之处是:单击左键、右键、再单击左键时,mousePressEvent为第二次左键单击报告的坐标是上一次左键单击坐标,跳过右键单击坐标返回到上次左键单击时鼠标按钮按下的位置


有什么想法吗?谢谢。

我有一个应用程序使用相同的组件:一个qgraphicsview和一个QGraphicscene,由一些QGraphicsSitem组成。这是一个以防万一,你想看看代码。在我的例子中,所有的QGraphicsSitem(钢琴键)都有
setAcceptedMouseButtons(Qt::NoButton)
,并且鼠标事件在场景级别而不是图形项目上处理。我从未观察到像您这样的问题。

qgraphicscanemouseevent::buttonDownPos(Qt::MouseButton button)

返回鼠标光标在项目坐标中的位置,其中 已单击指定的按钮

它返回您正在单击的图形项的坐标(如文档所示)。也许你只是在同一个地方点击? 如果需要场景位置,只需使用
maptosene
qgraphicscenemouseevent::buttonDownScenePos(Qt::MouseButton button)
event->scenePos()

附言。
并使用
QPointF::x()
QPointF::y()
而不是
rx()
ry()
。您不需要参考和操纵位置。

我有一个问题,您希望鼠标按哪个坐标?屏幕坐标、视口坐标、场景坐标、项目坐标等?QGraphicsView和QGraphicscene处理不同的坐标系,我想要场景坐标中的坐标,这就是我得到的,但只是以第二次和以后的press事件所描述的奇怪方式,显示了先前的鼠标向下位置。FWIW,行为在Windows10中完全相同。
#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
#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 );
    }
}
#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
#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();
}