我有一个“标准”Qt5 QWidgets 应用程序,它的 MainWindow 包含在 QtCreator 中创建的 mainwindow.ui 中的 QGraphicsView。QGraphicsView 将其场景设置为 QGraphicsScene 的一个简单子类,它在背景中有一个大矩形,它是 QGraphicsRectItem 的子类,它重新实现了 QGraphicsRectItem 的 mousePressEvent() 和 mouseReleaseEvent() 处理程序。在 Ubuntu 18.04 上运行,这无关紧要,但只是以防万一......
一切正常,除了...第二次和以后我按下鼠标左键(或任何)时,mousePressEvent 的 QGraphicsSceneMouseEvent buttonDownScenePos 中报告的坐标是“陈旧的” - 与上一次鼠标单击相同,而不是新位置鼠标是新点击发生的时间。mouseReleaseEvent 按预期报告坐标。
有没有办法让 mousePressEvent 的 buttonDownScenePos 在单击时保持当前鼠标的实际位置,而不是之前的鼠标位置?
我觉得我过去处理过一个与双击处理有关的类似问题,即在知道是否发生双击之前报告事件。在这种情况下,双击事件并不重要,但是能够在单击发生时立即响应它会很好,而不是等待释放事件。
相关代码:
主窗口.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
主窗口.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();
}
在运行后第一次单击时,报告的坐标与单击鼠标的网格位置非常吻合,无论是按下还是释放 - 它们都显示了按钮按下的位置。
但是,在第 2 次及以后的单击中,mousePressEvent 报告与之前的 mousePress 和 Release 事件相同的坐标,而 mouseReleaseEvent 报告当前事件中鼠标按钮“向下”的坐标。
最后一点奇怪:当单击左,右,再左时,mousePressEvent 报告的第二次左单击的坐标是之前的左单击坐标,跳过右键单击坐标回到鼠标按钮按下的位置在最后一次左键单击。
有任何想法吗?谢谢。