为什么QMouseEvent在QWidget上传递单个事件的多个事件?
我正在实现简单的拖动效果,但是结果不是我期望的。
以下代码会将小部件移到新位置,但立即将其移回到原始位置。
customwidget.h
#ifndef CUSTOMWIDGET_H
#define CUSTOMWIDGET_H
#include <QWidget>
#include <fstream>
class CustomWidget : public QWidget
{
Q_OBJECT
public:
explicit CustomWidget(QWidget *parent = nullptr);
~CustomWidget();
protected:
// define the painting agorithm to see the area of this widget
void paintEvent(QPaintEvent* ev);
// handle the pressing event to initialize the dragging algorithm
// and to track the start of moving event
void mousePressEvent(QMouseEvent* ev);
// implement the dragging algorithm
void mouseMoveEvent(QMouseEvent* ev);
// handle the releasing event to track the end of moving event
void mouseReleaseEvent(QMouseEvent* ev);
private:
std::ofstream fout; // open file "debug.txt"
QPoint prev; // to save the previous point of cursor.
};
#endif // CUSTOMWIDGET_H
customwidget.cpp
#include "customwidget.h"
#include <QMouseEvent>
#include <QPaintEvent>
#include <QPainter>
#include <QBrush>
CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
// open file for output
fout.open("debug.txt");
// set the widget size and position
setGeometry(0, 0, 100, 100);
}
CustomWidget::~CustomWidget()
{
// close file when program ended
fout.close();
}
void CustomWidget::paintEvent(QPaintEvent *ev)
{
// draw the area with blue color
QPainter painter(this);
QBrush brush(Qt::GlobalColor::blue);
painter.setBrush(brush);
painter.setBackground(brush);
painter.drawRect(ev->rect());
}
void CustomWidget::mousePressEvent(QMouseEvent *ev)
{
ev->accept();
// debug output
fout << "pressed at (" << ev->x() << ',' << ev->y() << ')' << std::endl;
// initialize the dragging start point
prev = ev->pos();
}
void CustomWidget::mouseMoveEvent(QMouseEvent *ev)
{
ev->accept();
// get the cursor position of this event
const QPoint& pos = ev->pos();
// debug output
fout << "moved from (" << prev.x() << ',' << prev.y() << ") to ("
<< pos.x() << ',' << pos.y() << ')' << std::endl;
// calculate the cursor movement
int dx = pos.x() - prev.x();
int dy = pos.y() - prev.y();
// move the widget position to match the direction of the cursor.
move(geometry().x() + dx, geometry().y() + dy);
// update the cursor position for the next event
prev = pos;
}
void CustomWidget::mouseReleaseEvent(QMouseEvent *ev)
{
ev->accept();
fout << "released at (" << ev->x() << ',' << ev->y() << ')' << std::endl;
}
main.cpp
#include "customwidget.h"
#include <QApplication>
#include <QMainWindow>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// generate simple main window.
QMainWindow w;
// set the size of the window.
w.setGeometry(0, 0, 800, 800);
// generate the CustomWidget
CustomWidget *widget = new CustomWidget(&w);
// display the window containing the widget
w.show();
return a.exec();
}
并且光标一动,debug.txt的结果就是
CustomWidget pressed at (79,83)
CustomWidget moved from (79,83) to (79,83)
CustomWidget moved from (79,83) to (80,83)
CustomWidget moved from (80,83) to (79,83)
CustomWidget released at (80,83)
结果是将小部件移到新位置一会儿,然后再将其移回到其原始位置。
该程序的外观几乎看起来像是该部件永远不会被移动,无论您如何拖动该部件。
我的理论是事件管理器在您移动光标时传递事件。但 在处理完第一个事件后,管理器将传递另一个与小部件的新位置和光标当前位置有关的事件。然后,该过程会将小部件移回原来的位置。
尽管我可以更改从中获取光标位置的方法
ev->pos()
到
ev->globalPos()
解决问题。
但是仍然想知道为什么事件管理器会那样做。
答案 0 :(得分:0)
您必须执行以下操作:
代码(草稿)可能类似于:
void CustomWidget::mousePressEvent(QMouseEvent* event)
{
// m_offset is a member variable of CustomWidget
m_offset = event->globalPos() - pos();
QWidget::mousePressEvent(event);
}
void CustomWidget::mouseMoveEvent(QMouseEvent* event)
{
if (!m_offset.isNull()) {
move(event->globalPos() - m_offset);
}
QWidget::mouseMoveEvent(event);
}
void CustomWidget::mouseReleaseEvent(QMouseEvent* event)
{
// Reset the offset value to prevent the movement.
m_offset = QPoint();
QWidget::mouseReleaseEvent(event);
}