如何通过B类在A窗口中画图

如何通过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()的,但是仍然会报错。如下:

img

你这么设计是有问题的。
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;
};

  • 以下回答由chatgpt基于相关博客总结生成:

    在A窗口中调用B类创建的对象并绘制,需要按照以下步骤进行:

    1. 在A窗口中调用B类创建的对象,可以通过在A窗口中添加一个成员变量或者在A窗口的构造函数中new一个B类的对象来实现。

    2. 为了在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);
    }