Я создал основной класс с именем widget.cpp, который наследует QFrame. А из widget.cpp я создаю подкласс с именем frame.cpp, в котором я переопределяю метод paintEvent () для рисования изображения. Проблема в том, что когда я пытаюсь нарисовать изображение напрямую через widget.cpp, создав для него метод paintEvent, он работает нормально. Но в другом случае, когда я реализую его в подклассе frame.cpp, он не работает нормально. Есть ли что-то, что я делаю не так здесь?
widget.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 (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>
Если вы хотите заменить виджет класса X, вы должны создать класс, который наследуется от этого класса, в вашем случае фрейм должен наследовать от QFrame
а не прямо из QWidget
, так как Qt Designer будет использовать QFrame
методы, которые QWidget
не имеет, вместо этого класс, который наследует от QFrame
если будет их.
Таким образом, вы должны изменить следующую часть в вашем коде.
frame.h
class frame : public QFrame
{
...
frame.cpp
frame::frame(QWidget *parent) : QFrame(parent)
{
}
Другая ошибка, которая наблюдается в вашем коде, это то, что вы звоните update()
внутри paintEvent()
, это может генерировать бесконечный цикл, так как 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->frame);
вы создаете новый виджет, который по умолчанию занимает позицию относительно родителя, поэтому вы видите изображение, но это не подходит, вам нужно продвигать виджет.
Для продвижения правой кнопкой мыши на QFrame
это в QtDesigner
, и будет отображаться меню, выберите «Продвигаемые виджеты», открыв диалоговое окно, в котором вы должны указать в названии «Продвигаемого класса» имя класса, который вы создали, в вашем случае Рамка , и в заголовочном файле .h файл вашего класса, в вашем случае frame.h, затем нажмите кнопку добавления, а затем кнопку продвижения. Как показано на следующих изображениях:
После компиляции вашего проекта в качестве окончательной рекомендации измените имя виджета в Qt Designer фрейма на другое, например, myFrame, чтобы не было путаницы с именем класса.
Полный пример можно найти в следующем ссылка на сайт
Других решений пока нет …