首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >单次移动QMouseEvent在QWidget上的实现

单次移动QMouseEvent在QWidget上的实现
EN

Stack Overflow用户
提问于 2018-10-22 07:57:56
回答 1查看 1.1K关注 0票数 0

为什么QMouseEvent在QWidget上为单个移动传递多个事件?

我正在实现简单的拖放效果,但结果与我所期望的不一样。

下面的代码将小部件移动到新位置,但立即将其移回原来的位置。

customwidget.h

代码语言:javascript
运行
复制
#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

代码语言:javascript
运行
复制
#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

代码语言:javascript
运行
复制
#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的结果是

代码语言:javascript
运行
复制
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)

其结果是将小部件移动到新位置一段时间,然后将其移回原来的位置。

这个程序的外观看起来就像小部件永远不会被移动,不管你如何拖拽小部件。

我的理论是,当您移动光标时,事件管理器传递事件。但是,在处理第一个事件之后,管理器传递另一个与小部件的新位置和光标当前位置相关的事件。然后,流程将小部件移回原来的位置。

虽然我可以更改获取光标位置的方法

代码语言:javascript
运行
复制
ev->pos()

代码语言:javascript
运行
复制
ev->globalPos()

来解决这个问题。

但仍然想知道为什么事件经理会这么做。

EN

回答 1

Stack Overflow用户

发布于 2018-10-22 08:15:50

你必须做以下工作:

  • 在鼠标按事件存储鼠标光标相对于小部件的偏移量时,
  • 移动小部件,使鼠标光标始终保持初始的非零偏移量,
  • 在鼠标释放事件上重置偏移量。

代码(草案)看起来可能如下:

代码语言:javascript
运行
复制
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);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52924687

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档