QT C++ Widget应用中通过PushButton从子窗口返回主窗口的实现问题
Hey there! Let's fix this issue step by step. First, let's break down what's going wrong with your current code, then I'll show you two reliable ways to implement the "return to main window" functionality that fits Qt's best practices (and works correctly).
What's Wrong with Your Current Code?
Your line mainwindow = new MainWindow(this); is causing two key problems:
- Type Mismatch Error: The compiler error tells us that
MainWindow's constructor expects a parameter of typeWidget, but you're passingthis(a pointer to yourCreditichild window, which is aQWidgetsubclass). This mismatch is why the error pops up. - Unnecessary New Window: Even if the error was fixed, creating a new
MainWindowinstance would open a brand new main window instead of showing the original one you had before opening the child window. That's not what you want—you just need to go back to the existing main window!
Method 1: Use Signals & Slots (Qt's Recommended Approach)
This is the cleanest way because it keeps your main window and child window decoupled (they don't need direct knowledge of each other's internal details). Here's how to do it:
Step 1: Add a Signal to Your Child Window (Crediti)
Edit your crediti.h file to define a custom signal that the child window will emit when the "return" button is clicked:
#ifndef CREDITI_H #define CREDITI_H #include <QWidget> namespace Ui { class Crediti; } class Crediti : public QWidget { Q_OBJECT public: explicit Crediti(QWidget *parent = nullptr); ~Crediti(); // Add this signal declaration signals: void returnToMain(); private slots: void on_pushButton_clicked(); private: Ui::Crediti *ui; }; #endif // CREDITI_H
Step 2: Emit the Signal in the Child Window's Button Slot
Update crediti.cpp to emit the signal and close the child window when the button is clicked:
#include "crediti.h" #include "ui_crediti.h" Crediti::Crediti(QWidget *parent) : QWidget(parent), ui(new Ui::Crediti) { ui->setupUi(this); } Crediti::~Crediti() { delete ui; } void Crediti::on_pushButton_clicked() { // Emit the signal to tell the main window to show itself emit returnToMain(); // Close the child window this->close(); }
Step 3: Connect the Signal in the Main Window
When you open the child window from MainWindow, connect the child's returnToMain signal to the main window's show() slot. Update your main window's button slot (the one that opens the child window) in mainwindow.cpp:
#include "mainwindow.h" #include "ui_mainwindow.h" #include "crediti.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_openCreditiBtn_clicked() { // Create the child window (no parent needed here) Crediti *creditiWindow = new Crediti(); // Connect the child's signal to our main window's show() slot connect(creditiWindow, &Crediti::returnToMain, this, &MainWindow::show); // Hide the main window temporarily this->hide(); // Show the child window creditiWindow->show(); // Make sure the child window is deleted when closed to avoid memory leaks creditiWindow->setAttribute(Qt::WA_DeleteOnClose); }
Method 2: Pass the Main Window Pointer to the Child (Simpler for Beginners)
If you want a more straightforward approach (with a bit more coupling between windows), you can pass the main window's pointer to the child window when you create it. Here's how:
Step 1: Update the Child Window's Header
Modify crediti.h to store a pointer to the main window:
#ifndef CREDITI_H #define CREDITI_H #include <QWidget> // Forward declare MainWindow to avoid circular includes class MainWindow; namespace Ui { class Crediti; } class Crediti : public QWidget { Q_OBJECT public: // Update constructor to accept the main window pointer explicit Crediti(MainWindow *mainWin, QWidget *parent = nullptr); ~Crediti(); private slots: void on_pushButton_clicked(); private: Ui::Crediti *ui; MainWindow *m_mainWindow; // Store the main window pointer }; #endif // CREDITI_H
Step 2: Initialize the Pointer in the Child Window's Constructor
Update crediti.cpp to save the main window pointer and use it in the button slot:
#include "crediti.h" #include "ui_crediti.h" #include "mainwindow.h" // Now we can include the main window header Crediti::Crediti(MainWindow *mainWin, QWidget *parent) : QWidget(parent), ui(new Ui::Crediti), m_mainWindow(mainWin) // Initialize the main window pointer { ui->setupUi(this); } Crediti::~Crediti() { delete ui; } void Crediti::on_pushButton_clicked() { // Show the original main window m_mainWindow->show(); // Close the child window this->close(); }
Step 3: Pass the Main Window Pointer When Creating the Child
Update your main window's button slot to pass this (the main window pointer) when creating the child:
void MainWindow::on_openCreditiBtn_clicked() { // Pass the main window pointer to the child Crediti *creditiWindow = new Crediti(this); this->hide(); creditiWindow->show(); creditiWindow->setAttribute(Qt::WA_DeleteOnClose); }
Both methods will fix your issue and let you return to the original main window when clicking the button in the child window. The first method (signals & slots) is more aligned with Qt's design principles, but the second is easier to wrap your head around as a beginner.
内容的提问来源于stack exchange,提问作者Marco Agnese

