如何通过B类在A窗口中画图
在A(widget)中调用Class B创建的对象,B类中的paintevent重写函数没有触发怎么解决。其中B没有自己的UI,通过传参把A的指针传递给B中paintevent函数中的Qpainter painter(*A)进行绘画。
#ifndef MBEZIER04_H
#define MBEZIER04_H
#include <QWidget>
class MBezier04 : public QWidget
{
Q_OBJECT
public:
explicit MBezier04(QWidget * parent = nullptr);
//**重写构造函数
MBezier04(QWidget * ms_parent = nullptr, QPoint ms_q1 = QPoint(0,0), QPoint ms_q2 = QPoint(0,0), QPoint ms_q3 = QPoint(0,0), QPoint ms_q4 = QPoint(0,0));
//**析构函数
~MBezier04();
//**重写鼠标事件
void mousePressEvent(QMouseEvent * event)override;
void mouseMoveEvent(QMouseEvent * event)override;
void mouseReleaseEvent(QMouseEvent * event)override;
protected:
//**重写绘图事件。
virtual void paintEvent(QPaintEvent *event)override;
private:
//**创建指针用于接收外部坐标参数
QWidget * m_widget;
//**创建指针用于接收外部坐标参数
QPoint m_startPoint, m_control1, m_control2, m_endPoint;
//**创建指针用于接收外部矩形参数
QRect m_startRect, m_control1Rect, m_control2Rect, m_endRect;
//**鼠标左键按下标记
bool m_leftDown = false;
//**是否选中控制点
bool m_selected = false;
//**选中控制点的坐标指针
QPoint m_selectPoint;
void m_DrawBeser(QPainter & ms_painter);
signals:
};
#endif // MBEZIER04_H
#include "mbezier04.h"
#include <QPainter>
#include <QDebug>
#include <QLabel>
#include <QMouseEvent>
MBezier04::MBezier04(QWidget *parent) : QWidget(parent)
{
}
//**析构函数
MBezier04::~MBezier04()
{
}
//**重写构造函数
MBezier04::MBezier04(QWidget * ms_parent, QPoint ms_q1 , QPoint ms_q2, QPoint ms_q3, QPoint ms_q4 ) : QWidget(ms_parent)
{
//**接收画面地址
m_widget = ms_parent;
//**接收外部坐标参数
m_startPoint = ms_q1;
m_control1 = ms_q2;
m_control2 = ms_q3;
m_endPoint = ms_q4;
m_startRect.setRect(m_startPoint.x()-5,m_startPoint.y()-5,10,10);
m_control1Rect.setRect(m_control1.x()-5,m_control1.y()-5,10,10);
m_control2Rect.setRect(m_control2.x()-5,m_control2.y()-5,10,10);
m_endRect.setRect(m_endPoint.x()-5,m_endPoint.y()-5,10,10);
this->setMouseTracking(true);
qDebug()<<3;
}
//**重写绘图事件。
void MBezier04::paintEvent(QPaintEvent * event)
{
QPainter m_painter(m_widget);
m_painter.setRenderHint(QPainter::Antialiasing, true);
QPen m_pen;
m_pen.setWidth(2);
m_pen.setCapStyle(Qt::RoundCap);
m_pen.setJoinStyle(Qt::RoundJoin);
m_pen.setStyle(Qt::DashDotLine);
m_pen.setColor(QColor(110, 122, 130));
//**将画笔属性给到画家
m_painter.setPen(QPen(m_pen));
m_DrawBeser(m_painter);
qDebug()<<1;
}
//**画曲线
void MBezier04::m_DrawBeser(QPainter & ms_painter)
{
//**创建一个路径
QPainterPath m_bezierpath;
ms_painter.save();
ms_painter.drawEllipse(m_startPoint, 2, 2);
ms_painter.drawEllipse(m_endPoint, 2, 2);
ms_painter.drawEllipse(m_control1, 2, 2);
ms_painter.drawEllipse(m_control2, 2, 2);
m_bezierpath.moveTo(m_startPoint);
m_bezierpath.cubicTo(m_control1, m_control2, m_endPoint);
//**百分之比的点
QPointF m_pointPercent;
m_pointPercent = m_bezierpath.pointAtPercent(0.0);
ms_painter.drawEllipse(m_pointPercent, 5, 5);
ms_painter.drawPath(m_bezierpath);
ms_painter.restore();
qDebug()<<2;
}
//**重写鼠标按下事件
void MBezier04::mousePressEvent(QMouseEvent * event)
{
if(event->button() == Qt::LeftButton)
{
m_leftDown = true;
}
update();
}
//**重写鼠标移动事件
void MBezier04::mouseMoveEvent(QMouseEvent *event)
{
QPoint m_pos = event->pos();
if (m_leftDown)
{
if (m_selected)
{
m_selectPoint.setX(m_pos.x());
m_selectPoint.setY(m_pos.y());
}
}
else
{
if (m_startRect.contains(m_pos))
{
QPen m_pen;
m_pen.setWidth(4);
m_selected = true;
m_selectPoint = m_startPoint;
}
else if (m_endRect.contains(m_pos))
{
QPen m_pen;
m_pen.setWidth(4);
m_selected = true;
m_selectPoint = m_endPoint;
}
else if (m_control1Rect.contains(m_pos))
{
QPen m_pen;
m_pen.setWidth(4);
m_selected = true;
m_selectPoint = m_control1;
}
else if (m_control2Rect.contains(m_pos))
{
QPen m_pen;
m_pen.setWidth(4);
m_selected = true;
m_selectPoint = m_control2;
}
else
{
m_selected = false;
QPen m_pen;
m_pen.setWidth(2);
}
}
update();
}
//**重写鼠标弹起事件
void MBezier04::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_leftDown = false;
}
else if (event->button() == Qt::RightButton)
{
}
update();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
virtual void paintEvent(QPaintEvent *);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mbezier04.h"
#include <QPainter>
#include <QDebug>
#include <QMouseEvent>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
MBezier04 m_mb1(this,QPoint(100,100),QPoint(200,200),QPoint(300,300),QPoint(400,400));
MBezier04 m_mb2(this,QPoint(500,500),QPoint(600,600),QPoint(700,700),QPoint(800,800));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::paintEvent(QPaintEvent *)
{
QPainter m_painter(this);
m_painter.drawPixmap(1200,0,500,800,QString(":/PngResource/device9021D.png"));
QPen m_pen;
m_pen.setStyle(Qt::DashDotLine);
m_pen.setWidth(3);
m_pen.setCapStyle(Qt::RoundCap);
m_pen.setJoinStyle(Qt::RoundJoin);
m_pen.setColor(QColor(110, 122, 130));
m_painter.setPen(QPen(m_pen));
QPainterPath m_pointPath;
m_pointPath.moveTo(1350,280);
m_pointPath.lineTo(1200,280);
m_pointPath.lineTo(1200,100);
m_pointPath.lineTo(1100,100);
m_painter.drawPath(m_pointPath);
m_painter.drawEllipse(QPointF(1350,280),2,2);
m_painter.drawEllipse(QPointF(1100,100),2,2);
}
思路有问题,代码写的也有问题,修改了一下请参照:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QDebug>
#include <QMouseEvent>
#include <QHBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_mb1 = new MBezier04(this,QPoint(100,100),QPoint(200,200),QPoint(300,300),QPoint(400,400));
m_mb2 = new MBezier04 (this,QPoint(500,500),QPoint(600,600),QPoint(700,700),QPoint(800,800));
}
MainWindow::~MainWindow()
{
delete m_mb1;
delete m_mb2;
delete ui;
}
void MainWindow::paintEvent(QPaintEvent *)
{
QPainter m_painter(this);
m_painter.drawPixmap(1200,0,500,800,QString(":/PngResource/device9021D.png"));
QPen m_pen;
m_pen.setStyle(Qt::DashDotLine);
m_pen.setWidth(3);
m_pen.setCapStyle(Qt::RoundCap);
m_pen.setJoinStyle(Qt::RoundJoin);
m_pen.setColor(QColor(110, 122, 130));
m_painter.setPen(QPen(m_pen));
m_mb1->paintEvent(&m_painter);
m_mb2->paintEvent(&m_painter);
QPainterPath m_pointPath;
m_pointPath.moveTo(1350,280);
m_pointPath.lineTo(1200,280);
m_pointPath.lineTo(1200,100);
m_pointPath.lineTo(1100,100);
m_painter.drawPath(m_pointPath);
m_painter.drawEllipse(QPointF(1350,280),2,2);
m_painter.drawEllipse(QPointF(1100,100),2,2);
}
#include "mbezier04.h"
#include <QPainter>
#include <QDebug>
#include <QLabel>
#include <QMouseEvent>
MBezier04::MBezier04(QWidget *parent) : QWidget(parent)
{
}
//**析构函数
MBezier04::~MBezier04()
{
}
//**重写构造函数
MBezier04::MBezier04(QWidget * ms_parent, QPoint ms_q1 , QPoint ms_q2, QPoint ms_q3, QPoint ms_q4 ) : QWidget(ms_parent)
{
//**接收画面地址
m_widget = ms_parent;
//**接收外部坐标参数
m_startPoint = ms_q1;
m_control1 = ms_q2;
m_control2 = ms_q3;
m_endPoint = ms_q4;
m_startRect.setRect(m_startPoint.x()-5,m_startPoint.y()-5,10,10);
m_control1Rect.setRect(m_control1.x()-5,m_control1.y()-5,10,10);
m_control2Rect.setRect(m_control2.x()-5,m_control2.y()-5,10,10);
m_endRect.setRect(m_endPoint.x()-5,m_endPoint.y()-5,10,10);
this->setMouseTracking(true);
qDebug()<<3;
}
//**重写绘图事件。
void MBezier04::paintEvent(QPainter* paint)
{
QPainter& m_painter = *paint;
m_painter.setRenderHint(QPainter::Antialiasing, true);
QPen m_pen;
m_pen.setWidth(2);
m_pen.setCapStyle(Qt::RoundCap);
m_pen.setJoinStyle(Qt::RoundJoin);
m_pen.setStyle(Qt::DashDotLine);
m_pen.setColor(QColor(110, 122, 130));
//**将画笔属性给到画家
m_painter.setPen(QPen(m_pen));
m_DrawBeser(m_painter);
qDebug()<<1;
}
//**画曲线
void MBezier04::m_DrawBeser(QPainter & ms_painter)
{
//**创建一个路径
QPainterPath m_bezierpath;
ms_painter.save();
ms_painter.drawEllipse(m_startPoint, 2, 2);
ms_painter.drawEllipse(m_endPoint, 2, 2);
ms_painter.drawEllipse(m_control1, 2, 2);
ms_painter.drawEllipse(m_control2, 2, 2);
m_bezierpath.moveTo(m_startPoint);
m_bezierpath.cubicTo(m_control1, m_control2, m_endPoint);
//**百分之比的点
QPointF m_pointPercent;
m_pointPercent = m_bezierpath.pointAtPercent(0.0);
ms_painter.drawEllipse(m_pointPercent, 5, 5);
ms_painter.drawPath(m_bezierpath);
ms_painter.restore();
qDebug()<<2;
}
//**重写鼠标按下事件
void MBezier04::mousePressEvent(QMouseEvent * event)
{
if(event->button() == Qt::LeftButton)
{
m_leftDown = true;
}
update();
}
//**重写鼠标移动事件
void MBezier04::mouseMoveEvent(QMouseEvent *event)
{
QPoint m_pos = event->pos();
if (m_leftDown)
{
if (m_selected)
{
m_selectPoint.setX(m_pos.x());
m_selectPoint.setY(m_pos.y());
}
}
else
{
if (m_startRect.contains(m_pos))
{
QPen m_pen;
m_pen.setWidth(4);
m_selected = true;
m_selectPoint = m_startPoint;
}
else if (m_endRect.contains(m_pos))
{
QPen m_pen;
m_pen.setWidth(4);
m_selected = true;
m_selectPoint = m_endPoint;
}
else if (m_control1Rect.contains(m_pos))
{
QPen m_pen;
m_pen.setWidth(4);
m_selected = true;
m_selectPoint = m_control1;
}
else if (m_control2Rect.contains(m_pos))
{
QPen m_pen;
m_pen.setWidth(4);
m_selected = true;
m_selectPoint = m_control2;
}
else
{
m_selected = false;
QPen m_pen;
m_pen.setWidth(2);
}
}
update();
}
//**重写鼠标弹起事件
void MBezier04::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_leftDown = false;
}
else if (event->button() == Qt::RightButton)
{
}
update();
}
以下回答参考GPT并且由Bony-整理:
如果想要在A窗口中画出B类中的图形,可以在A类的paintEvent函数中创建B类的对象,然后调用B类的paintEvent函数,并将B类的画家指定为A类的画家。
下面是示例代码:
void A::paintEvent(QPaintEvent *event)
{
// 创建B类对象
B b(this);
// 调用B类的paintEvent函数
b.paintEvent(event);
}
在B类的paintEvent函数中,可以将画家设置为A窗口的画家。
void B::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
// 设置画家为A窗口的画家
painter.setDevice(QPaintDevice::fromWinId((WId)A->winId()));
// 绘制图形
// ...
}
注意,这里使用了QPaintDevice::fromWinId
函数将A窗口的句柄转换为画家对象。在B类中需要声明A类的指针以便于访问。
此外,需要注意在创建B类对象时,需要将A类的指针作为参数传递给B类的构造函数。这样,在B类中就可以通过A类的指针访问A类的成员变量和成员函数了。
在MainWindow的paintEvent函数中创建了两个MBezier04对象,但是没有调用它们的paintEvent函数,因此B类中的paintevent重写函数没有被触发。解决方法是在MainWindow的paintEvent函数中调用每个MBezier04对象的QWidget::paintEvent函数,例如:m_mb1.paintEvent(nullptr); m_mb2.paintEvent(nullptr);
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
要在A窗口中画出B类对象的图形,可以在A类的paintEvent函数中调用B类对象的paintEvent函数。但是在您提供的代码中,B类的paintEvent函数并没有被调用,这可能是因为B类对象没有被正确地创建或添加到A类中。以下是一些可能的解决方案:
1.在A类的构造函数中创建B类对象,并将其添加到A类的布局中。
2.将B类对象作为A类的成员变量,并在A类的构造函数中初始化它。
3.在A类的paintEvent函数中,创建一个B类对象并调用它的paintEvent函数。
示例代码:
MainWindow类的构造函数:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
MBezier04* m_mb1 = new MBezier04(this,QPoint(100,100),QPoint(200,200),QPoint(300,300),QPoint(400,400));
MBezier04* m_mb2 = new MBezier04(this,QPoint(500,500),QPoint(600,600),QPoint(700,700),QPoint(800,800));
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(m_mb1);
layout->addWidget(m_mb2);
ui->centralwidget->setLayout(layout);
}
注意:这个解决方案中,您需要在A类的析构函数中删除B类对象,否则可能会出现内存泄漏。
如果您选择第二个解决方案,您需要将MBezier04类对象作为MainWindow类的成员变量:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
virtual void paintEvent(QPaintEvent *);
private:
Ui::MainWindow *ui;
MBezier04* m_mb1;
MBezier04* m_mb2;
};
MainWindow类的构造函数:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_mb1 = new MBezier04(this,QPoint(100,100),QPoint(200,200),QPoint(300,300),QPoint(400,400));
m_mb2 = new MBezier04(this,QPoint(500,500),QPoint(600,600),QPoint(700,700),QPoint(800,800));
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(m_mb1);
layout->addWidget(m_mb2);
ui->centralwidget->setLayout(layout);
}
注意:这个解决方案中,您需要在MainWindow类的析构函数中删除MBezier04类对象,否则可能会出现内存泄漏。
如果您选择第三个解决方案,您需要在A类的paintEvent函数中创建B类对象,并调用它的paintEvent函数:
void MainWindow::paintEvent(QPaintEvent *)
{
QPainter m_painter(this);
m_painter.drawPixmap(1200,0,500,800,QString(":/PngResource/device9021D.png"));
QPen m_pen;
m_pen.setStyle(Qt::DashDotLine);
m_pen.setWidth(3);
m_pen.setCapStyle(Qt::RoundCap);
m_pen.setJoinStyle(Qt::RoundJoin);
m_pen.setColor(QColor(110, 122, 130));
m_painter.setPen(QPen(m_pen));
QPainterPath m_pointPath;
m_pointPath.moveTo(1350,280);
m_pointPath.lineTo(1200,280);
m_pointPath.lineTo(1200,100);
m_pointPath.lineTo(1100,100);
m_painter.drawPath(m_pointPath);
m_painter.drawEllipse(QPointF(1350,280),2,2);
m_painter.drawEllipse(QPointF(1100,100),2,2);
MBezier04 m_mb(this,QPoint(100,100),QPoint(200,200),QPoint(300,300),QPoint(400,400));
m_mb.paintEvent(nullptr);
}
但是,这个解决方案中的B类对象没有被添加到A类中,因此它不能与其他窗口小部件一起布局和管理。
总之,第一个解决方案是最好的选择,因为它能够很好地管理B类对象,并防止内存泄漏。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
再mainWindow.h中,把m_mb1和m_mb2声明为成员变量:
MBezier04* m_mb1,*m_mb2;
在mainWindow.cpp的构造函数中,修改如下:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_mb1 = new MBezier04(this,QPoint(100,100),QPoint(200,200),QPoint(300,300),QPoint(400,400));
m_mb2 = new MBezier04(this,QPoint(500,500),QPoint(600,600),QPoint(700,700),QPoint(800,800));
m_mb1->setFixedSize(100,100); //如果没有这一句,窗口大小是0!!!!!你的鼠标响应函数也就没有任何作用
m_mb2->setFixedSize(100,100);
m_mb1->show();
m_mb2->show();
}
这样是可以调用paintEvent()的,但是仍然会报错。如下:
你这么设计是有问题的。
MBezier04是一个独立的窗口,它应该在自己的绘图资源里绘制,而不是让它在父窗口中绘制。而且,在其窗口中绘制后,这个窗口本身的大小是0 * 0!!!!你的鼠标响应函数也就不会有响应。你完全可以让MBezier04在自己的窗口里绘制,然后把MBezier04窗口设为透明就可以了!
引用chatGPT作答,您的问题可能是您没有正确传递A窗口的指针给B类。在B类中,您应该保存一个指向A的指针,以便在paintEvent函数中使用。在A类中创建B类的对象时,请将A的指针作为参数传递给B类的构造函数。以下是一种可能的解决方案:
// 在A类中调用B类的对象
void A::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
B b(this); // 创建B类的对象,并将A的指针传递给它
b.paintEvent(&painter); // 在B类中调用paintEvent函数
}
// 在B类中保存A的指针,并在paintEvent函数中使用它
class B {
public:
B(A *a) : a(a) {} // 构造函数中保存A的指针
void paintEvent(QPainter *painter) {
painter->drawLine(0, 0, a->width(), a->height()); // 使用A的指针绘图
}
private:
A *a;
};
在A窗口中调用B类创建的对象并绘制,需要按照以下步骤进行:
在A窗口中调用B类创建的对象,可以通过在A窗口中添加一个成员变量或者在A窗口的构造函数中new一个B类的对象来实现。
为了在A窗口中绘制B类的对象,需要在A窗口中重新实现paintEvent函数,在该函数中创建QPainter对象,并且在该对象中调用B类的方法进行绘制。
代码示例:
首先在A窗口中添加一个成员变量指向B类的对象:
class A : public QWidget
{
public:
A(QWidget *parent = nullptr);
~A();
private:
B *bObject;
};
在A窗口的构造函数中创建B类的对象:
A::A(QWidget *parent)
: QWidget(parent)
{
bObject = new B(this);
}
重新实现A窗口中的paintEvent函数,在该函数中创建QPainter对象,并且在该对象中调用B类的方法绘制:
void A::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
bObject->paint(&painter, this);
// 绘制A窗口的其他内容
}
在B类中需要添加一个paint函数,该函数接收一个QPainter对象和一个QWidget对象参数,利用这些参数完成绘制。
代码示例:
class B : public QObject
{
public:
void paint(QPainter *painter, QWidget *widget);
private:
// 其他成员函数和变量
};
void B::paint(QPainter *painter, QWidget *widget)
{
// 在这里完成B类的绘制
painter->setPen(Qt::red);
painter->setBrush(Qt::yellow);
painter->drawRect(10, 10, 100, 100);
}