【问题标题】:QPainter black trace when moving QWidget移动QWidget时QPainter黑色痕迹
【发布时间】:2015-04-15 11:58:52
【问题描述】:

我创建了一个带有 2 个小部件的小型测试应用程序,一个在另一个里面。 我重新实现了内部小部件的鼠标移动、按下和释放事件,以便能够通过拖放将其移动到更大的父级中。

但是,当我移动它时,从顶部和左侧出现黑色痕迹。看起来是这样的:

这是我的代码:

ma​​in.cpp

#include <QApplication>

#include "widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Widget w;
    w.show();

    return a.exec();
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPaintEvent>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void paintEvent(QPaintEvent *e);
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "innerwidget.h"

#include <QPainter>

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
    new InnerWidget(this);

    resize(400, 200);
}

Widget::~Widget()
{
}

void Widget::paintEvent(QPaintEvent* e)
{
    QPainter p(this);
    p.setBrush(Qt::lightGray);
    p.drawRect(e->rect());
}

innerwidget.h

#ifndef INNERWIDGET_H
#define INNERWIDGET_H

#include <QWidget>
#include <QPaintEvent>

class InnerWidget : public QWidget
{
    Q_OBJECT
public:
    explicit InnerWidget(QWidget *parent = 0);
    ~InnerWidget();

protected:
    void mousePressEvent(QMouseEvent *e);
    void mouseReleaseEvent(QMouseEvent *e);
    void mouseMoveEvent(QMouseEvent *e);
    void paintEvent(QPaintEvent *e);

private:
    bool m_leftButtonPressed;
    QPoint m_mousePosOnBar;
};

#endif // INNERWIDGET_H

innerwidget.cpp

#include "innerwidget.h"

#include <QPainter>
#include <QPaintEvent>
#include <QStyleOption>

InnerWidget::InnerWidget(QWidget *parent) : QWidget(parent)
{
    setGeometry(10, 10, 100, 100);
    setStyleSheet("background-color: red");
}

InnerWidget::~InnerWidget()
{

}

void InnerWidget::mousePressEvent(QMouseEvent* e)
{
    if(e->button() == Qt::LeftButton)
    {
        m_mousePosOnBar = e->pos();
        m_leftButtonPressed = true;
    }

    e->accept();
}

void InnerWidget::mouseReleaseEvent(QMouseEvent* e)
{
    if(e->button() == Qt::LeftButton)
    {
        m_leftButtonPressed = false;
    }

    e->accept();
}

void InnerWidget::mouseMoveEvent(QMouseEvent* e)
{
    if(m_leftButtonPressed)
    {
        move(e->pos().x() - m_mousePosOnBar.x() + geometry().x(),
             e->pos().y() - m_mousePosOnBar.y() + geometry().y());
    }


    e->accept();
}

void InnerWidget::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e)

    QPainter p(this);

    QStyleOption opt;
    opt.init(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

编辑: 当我调用Widget::repaint 时,跟踪消失了,但是我必须在InnerWidget 上安装一个事件过滤器,并在每次移动时重新绘制。我想要一个更干净的解决方案,而不必使用事件过滤器......

谁能告诉我到底发生了什么?

【问题讨论】:

  • 小部件没有擦除其先前绘制的位置。在 mouseMoveEvent 中添加对小部件的 update() 函数的调用:doc.qt.io/qt-5/qwidget.html#update
  • @TheDarkKnight 感谢您的关注!这并不能解决它,因为我必须更新Widget,而不是InnerWidget。但是,我可以在Widget 内为InnerWidget 安装一个事件过滤器,并在那里调用updaterepaint,但我想以更清洁/优雅的方式解决它......你还有其他想法吗? :(
  • “这不能解决问题” - 你试过了吗?我希望这会有所帮助。正如 Update() 中的文档所述,“Qt 通常会在调用 paintEvent() 之前擦除小部件的区域”
  • 或者,您可以调用parentWidget()-&gt;update();,而不是弄乱事件过滤器。
  • QGraphicsView 用于此类任务。如果你想在QWidget 上实现它的功能,我强烈建议你研究它的来源。

标签: c++ qt qwidget qpainter qmouseevent


【解决方案1】:

Widget::paintEvent 中调用QWidget::update() 解决了这个问题:

void Widget::paintEvent(QPaintEvent* e)
{
    QPainter p(this);
    p.setBrush(Qt::lightGray);
    p.drawRect(e->rect());

    update();
}

【讨论】:

    猜你喜欢
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    相关资源
    最近更新 更多