Qt - 子窗口内嵌到父窗口中
一、QWidget
1、《在QWidget下创建同类型的子窗口》
指定了父对象:w = new WidgetSon(this) 窗口就不是独立的,会嵌入到父窗口里。窗口一起显示。而且显示子窗口可以不用调用显示窗口函数,不调用的话也可以显示子窗口。
不指定父对象:w = new WidgetSon() 窗口是独立的,不会嵌入到父窗口里,先显示子窗口后显示父窗口。要显示子窗口必须调用显示窗口函数,如果不调用的话就不会显示子窗口。
子窗口去标题栏:如果去了标题栏,窗口标识是Qt::Widget,那还是会嵌入到父窗口里。如果去了标题栏,窗口标识是Qt::Dialog,则不会嵌入到父窗口里。
    w = new WidgetSon(this);
    w->setWindowFlags(Qt::Widget | Qt::FramelessWindowHint);//去掉标题栏
示例代码:
widget.h
查看代码
 #ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class WidgetSon;
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
    Ui::Widget *ui;
     WidgetSon* w;
};
#endif // WIDGET_H
widget.cpp
查看代码
 #include "widget.h"
#include "ui_widget.h"
#include "widgetson.h"
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setStyleSheet("background-color: rgb(150,150,150)");
    w = new WidgetSon(this);
    w->setStyleSheet("background-color: rgb(30,150,250)");
    w->show();
}
Widget::~Widget()
{
    delete ui;
}
widgetson.h
查看代码
 #ifndef WIDGETSON_H
#define WIDGETSON_H
#include <QWidget>
namespace Ui {
class WidgetSon;
}
class WidgetSon : public QWidget
{
    Q_OBJECT
public:
    explicit WidgetSon(QWidget *parent = nullptr);
    ~WidgetSon();
private:
    Ui::WidgetSon *ui;
};
#endif // WIDGETSON_H
widgetson.cpp
查看代码
 #include "widgetson.h"
#include "ui_widgetson.h"
WidgetSon::WidgetSon(QWidget *parent) :
QWidget(parent),
    ui(new Ui::WidgetSon)
{
    ui->setupUi(this);
    this->setFixedSize(600,500);
    //注意:子窗口必须要放一些控件进去,否则只有单独的QWidget的话会不显示子窗口。
    //1、代码创建QLabel
    QLabel *pLabel = new QLabel("Hello World",this);
	pLabel->setFixedSize(486 , 388 );
    //2、UI文件中创建QLabel    
    ui->label->setFixedSize(600,500);
}
WidgetSon::~WidgetSon()
{
    delete ui;
}
main.cpp
查看代码
 #include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}
运行效果:


刚刚说到,子窗口必须要放一些控件进去,否则只有单独的QWidget的话会不显示子窗口。原因是子窗口跟随了父窗口,所以要使用以下函数脱离父窗口,这样的话就不用在子窗口里放控件了。
setAttribute(Qt::WA_StyledBackground);//目的是脱离父窗口的样式。
示例代码:
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class WidgetSon;
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
    Ui::Widget *ui;
     WidgetSon* wSon;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "widgetson.h"
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setStyleSheet("background-color: rgb(150,150,150)");
    wSon = new WidgetSon(this);
    wSon->setAttribute(Qt::WA_StyledBackground);//脱离父窗口的样式
    //wSon->setWindowFlags(Qt::FramelessWindowHint);//去掉自带的标题栏
    //子窗口居中显示
    int geometryX = this->geometry().width() / 2;
    int geometryY = this->geometry().height() / 2;
    int W = wSon->width() / 2;
    int H = wSon->height() / 2;
    int x = geometryX - W;
    int y = geometryY - H;
    QPoint point(x, y);
    wSon->move(point);
    //wSon->show();
}
Widget::~Widget()
{
    delete ui;
}
widgetson.h
#ifndef WIDGETSON_H
#define WIDGETSON_H
#include <QWidget>
namespace Ui {
class WidgetSon;
}
class WidgetSon : public QWidget
{
    Q_OBJECT
public:
    explicit WidgetSon(QWidget *parent = nullptr);
    ~WidgetSon();
private:
    Ui::WidgetSon *ui;
};
#endif // WIDGETSON_H
widgetson.cpp
#include "widgetson.h"
#include "ui_widgetson.h"
WidgetSon::WidgetSon(QWidget *parent) :
QWidget(parent),
    ui(new Ui::WidgetSon)
{
    ui->setupUi(this);
    this->setFixedSize(600,500);
    this->setStyleSheet("background-color: rgb(30,150,250)");//给子窗口设置颜色,要不然是默认透明的,会看不见窗口
}
WidgetSon::~WidgetSon()
{
    delete ui;
}
运行效果:

1.1、《在QWidget下创建QDialog类型的子窗口》
1.2、《在QWidget下创建QMainWindow类型的子窗口》
============================================================================
二、QDialog
2、《在QDialog下创建同类型的子窗口》
指定了父对象:d = new DialogSon(this) 窗口是独立的,不会嵌入到父窗口里,先显示父窗口后显示子窗口(不过几乎差不多一起显示的)。而且要显示子窗口必须调用显示窗口函数,如果不调用的话就不会显示子窗口。
不指定父对象:d = new DialogSon() 窗口还是独立的,不会嵌入到父窗口里,先显示子窗口后显示父窗口。也是要显示子窗口必须调用显示窗口函数,如果不调用的话就不会显示子窗口。
子窗口去标题栏:如果去了标题栏,窗口标识是Qt::Dialog,还是不会嵌入到父窗口里。如果去了标题栏,窗口标识是Qt::Widget,也还是不会嵌入到父窗口里。
    d = new DialogSon(this);
    d->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);//去掉标题栏
示例代码:
dialog.h
查看代码
 #ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE
class DialogSon;
class Dialog : public QDialog
{
    Q_OBJECT
public:
    Dialog(QWidget *parent = nullptr);
    ~Dialog();
private:
    Ui::Dialog *ui;
    DialogSon*  d;
};
#endif // DIALOG_H
dialog.cpp
查看代码
 #include "dialog.h"
#include "ui_dialog.h"
#include "dialogson.h"
#include <QMessageBox>
Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{
    ui->setupUi(this);
    this->setStyleSheet("background-color: rgb(150,150,150)");
    d = new DialogSon();
    d->setStyleSheet("background-color: rgb(30,150,250)");
    // 显示信息对话框
    //QMessageBox::information(this, "提示","子窗口显示", QMessageBox::Ok);
    d->show();
}
Dialog::~Dialog()
{
    delete ui;
}
dialogson.h
查看代码
 #ifndef DIALOGSON_H
#define DIALOGSON_H
#include <QDialog>
namespace Ui {
class DialogSon;
}
class DialogSon : public QDialog
{
    Q_OBJECT
public:
    explicit DialogSon(QWidget *parent = nullptr);
    ~DialogSon();
private:
    Ui::DialogSon *ui;
};
#endif // DIALOGSON_H
dialogson.cpp
查看代码
 #include "dialogson.h"
#include "ui_dialogson.h"
DialogSon::DialogSon(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DialogSon)
{
    ui->setupUi(this);
}
DialogSon::~DialogSon()
{
    delete ui;
}
main.cpp
查看代码
 #include "dialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();
    return a.exec();
}
运行效果:

2.1、《在QDialog下创建QWidget类型的子窗口》
2.2、《在QDialog下创建QMainWindow类型的子窗口》
============================================================================
三、QMainWindow
3、《在QMainWindow下创建同类型的子窗口》
指定了父对象:m = new MainWindowSon(this) 窗口是独立的,不会嵌入到父窗口里,先显示父窗口后显示子窗口(不过几乎差不多一起显示的)。而且要显示子窗口必须调用显示窗口函数,如果不调用的话就不会显示子窗口。
不指定父对象:m = new MainWindowSon() 窗口还是独立的,不会嵌入到父窗口里,先显示子窗口后显示父窗口。也是要显示子窗口必须调用显示窗口函数,如果不调用的话就不会显示子窗口。
子窗口去标题栏:如果去了标题栏,窗口标识是Qt::Widget并且指定了父对象,是会嵌入到父窗口里。如果去了标题栏,窗口标识是Qt::Dialog并且指定了父对象,是不会嵌入到父窗口里。
    m = new MainWindowSon(this);
    m->setWindowFlags(Qt::Widget | Qt::FramelessWindowHint);//去掉标题栏
示例代码:
mainwindow.h
查看代码
 #ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindowSon;
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
    MainWindowSon* m;
};
#endif // MAINWINDOW_H
mainwindow.cpp
查看代码
 #include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mainwindowson.h"
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setStyleSheet("background-color: rgb(150,150,150)");
    m = new MainWindowSon();
    m->setStyleSheet("background-color: rgb(30,150,250)");
    m->show();
}
MainWindow::~MainWindow()
{
    delete ui;
}
mainwindowson.h
查看代码
 #ifndef MAINWINDOWSON_H
#define MAINWINDOWSON_H
#include <QMainWindow>
namespace Ui {
class MainWindowSon;
}
class MainWindowSon : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindowSon(QWidget *parent = nullptr);
    ~MainWindowSon();
private:
    Ui::MainWindowSon *ui;
};
#endif // MAINWINDOWSON_H
mainwindowson.cpp
查看代码
 #include "mainwindowson.h"
#include "ui_mainwindowson.h"
MainWindowSon::MainWindowSon(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindowSon)
{
    ui->setupUi(this);
}
MainWindowSon::~MainWindowSon()
{
    delete ui;
}
main.cpp
查看代码
 #include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}
运行效果:

3.1、《在QMainWindow下创建QWidget类型的子窗口》
3.2、《在QMainWindow下创建QDialog类型的子窗口》
四、总结
QWidget:
- 可内嵌到其他窗口的内部(无边框);创建一个窗口指定了父对象;例如WidgetSon* w = new WidgetSon(this)
 - 可以作为独立的窗口显示(有边框);创建一个窗口没有指定父对象;例如WidgetSon* w = new WidgetSon()
 
QDialog:
- 不可以内嵌到其他窗口的内部
 
QMainWindow:
- 不可以内嵌到其他窗口的内部,不过假如你去了标题栏并且指定了父对象那也是可以内嵌到其他窗口内部的。
 
五、其他的内嵌方法
不过以上总结也不是那么绝对的,其实可以通过其他手段来内嵌到父窗口。
方法1、使用布局管理器
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE
class DialogSon;
class Dialog : public QDialog
{
    Q_OBJECT
public:
    Dialog(QWidget *parent = nullptr);
    ~Dialog();
private:
    Ui::Dialog *ui;
    DialogSon*  d;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
#include "dialogson.h"
#include <QBoxLayout>
Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{
    ui->setupUi(this);
    this->setStyleSheet("background-color: rgb(150,150,150)");
    d = new DialogSon(this);
    d->setWindowFlags(Qt::FramelessWindowHint);//去掉标题栏
    d->setStyleSheet("background-color: rgb(30,150,250)");
    //d->show();
    //创建布局
    QHBoxLayout *hlayout = new QHBoxLayout(this);
    hlayout->setContentsMargins(100,90,100,90);
    //把小部件添加到布局
    hlayout->addWidget(d);
    //给当前窗口设置布局
    this->setLayout(hlayout);
}
Dialog::~Dialog()
{
    delete ui;
}
dialogson.h
#ifndef DIALOGSON_H
#define DIALOGSON_H
#include <QDialog>
namespace Ui {
class DialogSon;
}
class DialogSon : public QDialog
{
    Q_OBJECT
public:
    explicit DialogSon(QWidget *parent = nullptr);
    ~DialogSon();
private:
    Ui::DialogSon *ui;
};
#endif // DIALOGSON_H
dialogson.cpp
#include "dialogson.h"
#include "ui_dialogson.h"
DialogSon::DialogSon(QWidget *parent) :QDialog(parent),
    ui(new Ui::DialogSon)
{
    ui->setupUi(this);
}
DialogSon::~DialogSon()
{
    delete ui;
}
main.cpp
#include "dialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();
    return a.exec();
}
运行效果:

方法2、使用提升控件方式
首先自定义一个CustomDialog类,初始化界面。
customdialog.h
#ifndef CUSTOMDIALOG_H
#define CUSTOMDIALOG_H
#include <QDialog>
class CustomDialog: public QDialog
{
    Q_OBJECT
public:
    CustomDialog(QWidget *parent = nullptr);
    ~CustomDialog();
private:
};
#endif // CUSTOMDIALOG_H
customdialog.cpp
#include "customdialog.h"
#include <QPushButton>
CustomDialog::CustomDialog(QWidget *parent):QDialog(parent)
{
    setFixedSize(571,361);
    setWindowFlags(Qt::FramelessWindowHint);//去掉标题栏
    setStyleSheet("background-color: rgb(255,0,0)");
    QPushButton* btn = new QPushButton("关闭窗口",this);
    btn->setGeometry(521,0,50,25);
}
CustomDialog::~CustomDialog()
{
}
然后在 dialog.ui 文件中拖入一个Widget控件。

在ui界面中选中Widget控件。鼠标右击选择"提升为"

输入提升的类名"CustomDialog",之后点击添加。

之后选择列表中的CustomDialog类,点击提升。

可以看到widget就被提升为CustomDialog了。

运行效果:


                
            
        
浙公网安备 33010602011771号