본문 바로가기
Solution/Qt Programming

[Qt] GLWidget class inherited from MDIWindow and MainWindow

by 이센 2023. 9. 28.
Now I defined public member variables in glwidget class in Qt, and the public member variables are accessed to put some values after defining glwidget A; in mainwindow.cpp. but I want to draw a figure with opengl on sub-windows through  mdimainwindow class and I want to reuse A variable used in mainwindow.cpp. But I can't find the way. please show me related code in detail.   

 

In Qt, it's generally not recommended to define public member variables in a class, as it breaks encapsulation principles. Instead, you should use getter and setter methods (accessor methods) to access and modify the member variables. However, if you have a specific reason for using public member variables, you can still access them in different parts of your application.

Here's a basic example of how you can access a public member variable in a GLWidget class from both mainwindow.cpp and mdimainwindow.cpp:

Define a GLWidget class with a public member variable in glwidget.h:

// glwidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QOpenGLWidget>

class GLWidget : public QOpenGLWidget
{
public:
    GLWidget(QWidget *parent = nullptr);
    
    // Public member variable
    float someValue;
    
    // Add any OpenGL drawing logic here
    void paintGL() override;
};

#endif // GLWIDGET_H

Access the GLWidget in mainwindow.cpp:

// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "glwidget.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Create a GLWidget instance
    GLWidget *A = new GLWidget(this);

    // Access and modify the public member variable
    A->someValue = 42.0f;

    // Add GLWidget to the main window or layout
    // (assuming you have a layout or container widget to hold it)
    ui->someLayout->addWidget(A);
}

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

Access the GLWidget in mdimainwindow.cpp:

 
 
I want to draw a figure with GLWidget in subwindow2 defined QMdiSubWindow, how can I correct the above code.

To draw a figure with a GLWidget in QMdiSubWindow, you can modify the code as follows:

Create a new QMdiSubWindow in mdimainwindow.cpp and add a GLWidget to it:

// mdimainwindow.cpp
#include "mdimainwindow.h"
#include "ui_mdimainwindow.h"
#include "glwidget.h"

MDIMainWindow::MDIMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MDIMainWindow)
{
    ui->setupUi(this);

    // Create a QMdiArea to hold subwindows
    QMdiArea *mdiArea = new QMdiArea(this);
    setCentralWidget(mdiArea);

    // Create subwindow 1 (example)
    QMdiSubWindow *subWindow1 = new QMdiSubWindow;
    GLWidget *A1 = new GLWidget(subWindow1);
    subWindow1->setWidget(A1);
    mdiArea->addSubWindow(subWindow1);

    // Access the GLWidget instance created in MainWindow
    GLWidget *A2 = dynamic_cast<GLWidget*>(centralWidget());

    if (A2) {
        // Access and modify the public member variable
        float value = A2->someValue;
        qDebug() << "Value from GLWidget A2: " << value;
    }

    // Create subwindow 2 and add GLWidget to it
    QMdiSubWindow *subWindow2 = new QMdiSubWindow;
    GLWidget *A3 = new GLWidget(subWindow2);
    subWindow2->setWidget(A3);
    mdiArea->addSubWindow(subWindow2);

    // Show subwindows
    subWindow1->show();
    subWindow2->show();
}

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

In this modified code, we create a QMdiSubWindow named subWindow2 and add a GLWidget named A3 to it. A3 will be responsible for drawing figures in the second subwindow. You can customize and add OpenGL drawing logic to A3 as needed. Remember to set the layout and positioning of the subwindows according to your requirements.

 

I didn't use ui in mainwindow.cpp and mdimainwindow.cpp, how can I correct both codes?
// mainwindow.cpp
#include "mainwindow.h"
#include "glwidget.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    // Create a GLWidget instance
    GLWidget *A = new GLWidget(this);

    // Access and modify the public member variable
    A->someValue = 42.0f;

    // Add GLWidget to the main window or layout
    // (assuming you have a layout or container widget to hold it)
    setCentralWidget(A);
}

MainWindow::~MainWindow()
{
    // No need to delete A here if it's set as the central widget, 
    // as Qt will handle its destruction.
}
// mdimainwindow.cpp
#include "mdimainwindow.h"
#include "glwidget.h"

MDIMainWindow::MDIMainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    // Create a QMdiArea to hold subwindows
    QMdiArea *mdiArea = new QMdiArea(this);
    setCentralWidget(mdiArea);

    // Create subwindow 1 (example)
    QMdiSubWindow *subWindow1 = new QMdiSubWindow;
    GLWidget *A1 = new GLWidget(subWindow1);
    subWindow1->setWidget(A1);
    mdiArea->addSubWindow(subWindow1);

    // Access the GLWidget instance created in MainWindow
    GLWidget *A2 = dynamic_cast<GLWidget*>(centralWidget());

    if (A2) {
        // Access and modify the public member variable
        float value = A2->someValue;
        qDebug() << "Value from GLWidget A2: " << value;
    }

    // Create subwindow 2 and add GLWidget to it
    QMdiSubWindow *subWindow2 = new QMdiSubWindow;
    GLWidget *A3 = new GLWidget(subWindow2);
    subWindow2->setWidget(A3);
    mdiArea->addSubWindow(subWindow2);

    // Show subwindows
    subWindow1->show();
    subWindow2->show();
}

MDIMainWindow::~MDIMainWindow()
{
    // No need to delete anything here; Qt will handle it.
}

In these modified codes, we're directly creating the GLWidget instances and adding them to the main window and subwindows, respectively, without using the ui object. The setCentralWidget method is used to set the central widget in both MainWindow and MDIMainWindow without relying on the ui object.

 

Thanks then If I use GLWidget A = new GLWidget(this); instead GLWidget *A = new GLWidget(this); in mainwindow, how can I change code in mdimainwindow.cpp.


If you change the declaration of A in mainwindow.cpp from GLWidget *A = new GLWidget(this); to GLWidget A = new GLWidget(this);, you'll be creating an instance of GLWidget on the stack instead of on the heap, and you won't need to delete it explicitly because it will be automatically destroyed when it goes out of scope.

Here's how you can adapt the code in mdimainwindow.cpp to work with GLWidget A created on the stack in mainwindow.cpp:

 

// mdimainwindow.cpp
#include "mdimainwindow.h"
#include "glwidget.h"

MDIMainWindow::MDIMainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    // Create a QMdiArea to hold subwindows
    QMdiArea *mdiArea = new QMdiArea(this);
    setCentralWidget(mdiArea);

    // Access the GLWidget instance created in MainWindow
    GLWidget *A2 = dynamic_cast<GLWidget*>(centralWidget());

    if (A2) {
        // Access and modify the public member variable
        float value = A2->someValue;
        qDebug() << "Value from GLWidget A2: " << value;
    }

    // Create subwindow 2 and add GLWidget to it
    QMdiSubWindow *subWindow2 = new QMdiSubWindow;
    // Since GLWidget A is created on the stack in mainwindow.cpp,
    // you can't pass it directly to subWindow2
    // Instead, you should create another instance of GLWidget for subWindow2
    GLWidget *A3 = new GLWidget(subWindow2);
    subWindow2->setWidget(A3);
    mdiArea->addSubWindow(subWindow2);

    // Show subwindows
    subWindow2->show();
}

MDIMainWindow::~MDIMainWindow()
{
    // No need to delete anything here; Qt will handle it.
}

In this modified code, we create a new GLWidget instance A3 for subWindow2 as GLWidget *A3 = new GLWidget(subWindow2); because you can't directly pass the stack-allocated GLWidget A from mainwindow.cpp to another widget like subWindow2.

 


In the line GLWidget *A2 = dynamic_cast<GLWidget*>(centralWidget()); , several things are happening:


Certainly! In the line GLWidget *A2 = dynamic_cast<GLWidget*>(centralWidget());, several things are happening:
centralWidget() is a function provided by the QMainWindow class in Qt. It returns a pointer to the central widget that has been set using setCentralWidget(). This central widget occupies the main content area of the QMainWindow.

dynamic_cast is a C++ language feature that is used for performing type-safe downcasting between polymorphic classes in C++. In this case, it's being used to cast the pointer returned by centralWidget() to a pointer of type GLWidget*.

Here's a breakdown of what the line does:
centralWidget() returns a pointer to the current central widget of the QMainWindow.
dynamic_cast<GLWidget*>(...) attempts to cast this pointer to a GLWidget* type.
If the cast is successful (i.e., if the central widget is actually an instance of GLWidget or a subclass of it), A2 will now point to the central widget as a GLWidget*.
If the cast is unsuccessful (i.e., if the central widget is not a GLWidget or a subclass of it), A2 will be assigned a nullptr.

This code is useful for checking whether the central widget of the QMainWindow is of the expected type (GLWidget in this case) before performing operations on it. It helps ensure type safety and avoid runtime errors when working with widgets in complex user interface hierarchies.