【问题标题】:How to draw rectangle on custom video widget t in QT?如何在 QT 中的自定义视频小部件 t 上绘制矩形?
【发布时间】:2018-10-27 16:38:27
【问题描述】:

我想在自定义视频小部件上选择一个区域并在所选区域上绘制矩形。

到目前为止,我可以使用 QRubberband 选择一个区域,但我在释放左键后无法绘制矩形。

每当我单击拖动然后释放以绘制矩形时,它都会出现此错误:

QBackingStore::endPaint() 在 backingstore 绘制设备上使用活动绘制器调用

程序意外结束。

这是我的代码:

myvideoobject.h

#ifndef MYVIDEOOBJECT_H
#define MYVIDEOOBJECT_H

#include <QObject>
#include <QVideoWidget>
#include <QRubberBand>
#include <QPainter>
#include <QPen>
#include <QPaintEvent>
#include <QRect>
#include <QMouseEvent>
#include <QDebug>

class MyVideoObject : public QVideoWidget
{
    Q_OBJECT
public:
    explicit MyVideoObject(QWidget *parent = 0);

    void mouseMoveEvent(QMouseEvent *ev);
    void mousePressEvent(QMouseEvent *ev);
    void mouseReleaseEvent(QMouseEvent *ev);
    void paintEvent(QPaintEvent *ev);

private:
    QRubberBand* rubberBand;
    QPainter* painter;
    //QRect *rectangle;

    QPoint origin;
    QPoint endPoint;

};

#endif // MYVIDEOOBJECT_H

myvideoobject.cpp

#include "myvideoobject.h"

MyVideoObject::MyVideoObject(QWidget* parent) :
QVideoWidget(parent)
{
    rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
    rubberBand->setGeometry(0,0,50,50);//ileride silebilrisin

}

void MyVideoObject::mouseMoveEvent(QMouseEvent *ev)
{
    rubberBand->setGeometry(QRect(origin,ev->pos()).normalized());
}

void MyVideoObject::mousePressEvent(QMouseEvent *ev)
{
    origin = ev->pos();
    if(!rubberBand)
         rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
    rubberBand->setGeometry(QRect(origin,QSize()));
    rubberBand->show();
}

void MyVideoObject::mouseReleaseEvent(QMouseEvent *ev)
{
    rubberBand->hide();

    endPoint = ev->pos();

    painter->begin(this);
    painter->drawRect(QRect(origin,endPoint));

}

void MyVideoObject::paintEvent(QPaintEvent *ev)
{
    QRect rect = ev->rect();
    painter = new QPainter(this);
    painter->setRenderHint(QPainter::Antialiasing);
    painter->setPen(Qt::black);
    painter->drawText(rect,Qt::AlignCenter,"Data");
    painter->drawRect(rect);

//painter->setPen(Qt::red);
}

我没有添加 mainwindow.cpp 和 mainwindow.h 因为除了使用 openfiledialog 选择视频之外没有太多代码。

【问题讨论】:

    标签: c++ qt widget paintevent


    【解决方案1】:

    当你创建一个指针:QPainter *painter,它可以指向任何内存,因为它有垃圾。因此,当您执行painter-&gt;begin(this) 时,您正在访问未初始化的内存,这就是您收到该错误的原因。另一方面,在QWidget 中,例如QVideoWidget,只能在方法paintEvent 中绘制,策略是使用变量来保存您要绘制的状态,例如QRect,以及调用 update 来绘制它。

    myvideoobject.h

    #ifndef MYVIDEOOBJECT_H
    #define MYVIDEOOBJECT_H
    
    #include <QVideoWidget>
    
    class QRubberBand;
    
    class MyVideoObject : public QVideoWidget
    {
    public:
        MyVideoObject(QWidget *parent = nullptr);
    protected:
        void mouseMoveEvent(QMouseEvent *ev);
        void mousePressEvent(QMouseEvent *ev);
        void mouseReleaseEvent(QMouseEvent *ev);
        void paintEvent(QPaintEvent *ev);
    private:
        QRubberBand *rubberBand;
        QPoint origin;
        QRect rect;
    };
    
    #endif // MYVIDEOOBJECT_H
    

    myvideoobject.cpp

    #include "myvideoobject.h"
    
    #include <QMouseEvent>
    #include <QPainter>
    #include <QRubberBand>
    
    MyVideoObject::MyVideoObject(QWidget *parent):
        QVideoWidget(parent),
        rubberBand(nullptr){}
    
    void MyVideoObject::mousePressEvent(QMouseEvent *ev)
    {
        origin = ev->pos();
        if(!rubberBand)
            rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
        rubberBand->setGeometry(QRect(origin,QSize()));
        rubberBand->show();
        QVideoWidget::mousePressEvent(ev);
    }
    
    void MyVideoObject::mouseMoveEvent(QMouseEvent *ev)
    {
        rubberBand->setGeometry(QRect(origin,ev->pos()).normalized());
        QVideoWidget::mouseMoveEvent(ev);
    }
    
    void MyVideoObject::mouseReleaseEvent(QMouseEvent *ev)
    {
        rect = rubberBand->geometry();
        update();
        QVideoWidget::mouseReleaseEvent(ev);
    }
    
    void MyVideoObject::paintEvent(QPaintEvent *ev)
    {
        QVideoWidget::paintEvent(ev);
        QPainter painter(this);
        painter.save();
        painter.setBrush(Qt::red);
        if(!rect.isNull())
            painter.drawRect(rect);
        painter.restore();
    }
    

    【讨论】:

    • 谢谢!然而,即使这用 QRubberband 绘制矩形。它没有画出我想要的红色矩形。它现在也发出警告QWidget::paintEngine: Should no longer be called
    • @onurcevik 警告:QWidget::paintEngine: Should no longer be called 很常见,不要在意,另一方面 QVideoWidget 是一个特殊的小部件,所以它好像通用的解决方法不行,我只好用别的方法了,
    • 我还将QMediaPlayerMyVideoObject 定义为mainwindow.cpp 中的指针,这可能是问题的根源吗?
    • @onurcevik 与此无关,我也遇到过类似的问题,我已经能够通过一个技巧解决它们,我正在实施解决方案,请稍等。
    • 嘿,已经 2 小时了 :) 您还在尝试实施解决方案吗?如果不能,请告诉我您的“技巧”,以便我可以尝试自己解决问题?
    猜你喜欢
    • 2018-09-29
    • 2017-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多