【问题标题】:Drawing on a main class's subclass in Qt在 Qt 中绘制主类的子类
【发布时间】:2017-09-20 15:32:09
【问题描述】:

我创建了一个名为 widget.cpp 的主类,它继承了 QFrame。我从 widget.cpp 创建了一个名为 frame.cpp 的子类,在其中我重新实现了用于绘制图像的 paintEvent() 方法。问题是,当我尝试通过为它创建一个paintEvent 方法直接通过widget.cpp 绘制图像时,它工作正常。但在另一种情况下,当我在子类 frame.cpp 中实现它时,它不能正常工作。我在这里做错了什么吗。

小部件.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QFrame>
#include <QPainter>
#include "frame.h"

class frame;
namespace Ui {
    class Widget;
}
class Widget : public QFrame
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private:
    Ui::Widget *ui;
    frame * f;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    f = new frame(ui->frame);
    f->show();
}

Widget::~Widget()
{
    delete ui;
}

frame.h

#ifndef FRAME_H
#define FRAME_H

#include <QObject>
#include <QWidget>
#include <QPainter>

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

protected:
    void paintEvent(QPaintEvent *p);

signals:

public slots:
};

#endif // FRAME_H

frame.cpp

#include "frame.h"

frame::frame(QWidget *parent) : QWidget(parent)
{

}

void frame::paintEvent(QPaintEvent *p)
{
    QPainter* pPainter = new QPainter(this);
    QImage img(":/left.png");
    Q_ASSERT(!img.isNull());
    QRect source(0,0,20,10);
    QRect target(50,50,20,10);
    pPainter->drawImage(target, img,source);
    QWidget::paintEvent(p);
    QWidget::update();
}

如果我在上面的代码中使用 QRect target(0,0,20,10),图像就会被绘制出来。

testImage.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = testImage
TEMPLATE = app

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += main.cpp\
        widget.cpp \
    frame.cpp

HEADERS  += widget.h \
    frame.h

FORMS    += widget.ui

RESOURCES += \
    src.qrc

DISTFILES +=

widget.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>823</width>
    <height>468</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Widget</string>
  </property>
  <widget class="QFrame" name="frame">
   <property name="geometry">
    <rect>
     <x>200</x>
     <y>60</y>
     <width>420</width>
     <height>300</height>
    </rect>
   </property>
   <property name="minimumSize">
    <size>
     <width>420</width>
     <height>300</height>
    </size>
   </property>
   <property name="maximumSize">
    <size>
     <width>420</width>
     <height>306</height>
    </size>
   </property>
   <property name="frameShape">
    <enum>QFrame::StyledPanel</enum>
   </property>
   <property name="frameShadow">
    <enum>QFrame::Raised</enum>
   </property>
  </widget>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

【问题讨论】:

  • 从第一印象看,您似乎忘记将paintEvent 声明为virtual 和/或使用override 关键字。
  • @PhilippLudwig 不需要使用覆盖
  • @Som 您可以包含 .ui 文件以便能够重现您的代码,这意味着:无法正常工作。 ?
  • 这有点令人困惑,因为当我将行的值保留在“QRect target(50,50,20,10);”中时从 0 到 80,图像显示正确。之后它会缩小然后消失,图像分辨率只有20 * 10,小部件大约是500 * 400。 @PhilippLudwig virtual 没有做任何改变。
  • @eyllanesc 你是对的,我的错。

标签: c++ qt qt5 qframe


【解决方案1】:

如果您想替换 X 类小部件,您必须创建一个继承自该类的类,在您的情况下,框架必须继承自 QFrame 而不是直接继承自 QWidget,因为 Qt Designer 将使用 QFrame 方法QWidget 没有,而是一个继承自 QFrame 的类(如果有的话)。

因此,您应该更改代码中的下一部分。

frame.h

class frame : public QFrame
{
   ...

frame.cpp

frame::frame(QWidget *parent) : QFrame(parent)
{

}

在您的代码中观察到的另一个错误是您在paintEvent() 中调用了update(),这可能会生成一个无限循环,因为update() 间接调用了paintEvent()。还有一个小部件你的一个绘画空间,这个空间我们可以通过rect()的方法得到,如果你在那个空间之外绘制什么都没有。另一个不好的做法是创建一个指向QPainter 的指针,因为它会不断地被调用到该方法,并且除了正确消除它之外,您还将创建内存。从上面我提出以下代码:

void frame::paintEvent(QPaintEvent *p)
{
    QWidget::paintEvent(p);
    QPainter pPainter(this);
    QImage img(":/left.png");
    Q_ASSERT(!img.isNull());
    QRect source(0,0,20,10);
    QRect target(50,50,20,10);
    pPainter.drawImage(target, img, source);
}

最重要的是,当您运行 f = new frame(ui-&gt;frame); 时,您正在创建一个新小部件,默认情况下该小部件相对于父级具有一个位置,这就是您看到图像的原因,但这不合适,您应该做的是提升小部件。

要提升在QtDesigner 中的QFrame 上单击鼠标右键,将显示一个菜单,选择Promoted Widgets,打开一个对话框窗口,在其中您必须在Promoted class name 中输入您的班级名称在您的情况下创建了 frame ,在头文件中创建了您的类的 .h 文件,在您的情况下为 frame.h,然后按添加按钮,然后按升级按钮。如下图所示:

编译您的项目后,作为最终建议,将框架的 Qt Designer 中的小部件名称更改为另一个名称,例如 myFrame,以免与类名称混淆。

完整的例子可以看下面的link

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    相关资源
    最近更新 更多