新建一个QMainWindow的空项目
(懒得看又臭又长直接到最后复制整段代码)
先新建一个QMainWindow的空项目,不使用.ui文件。
这时候mainwindow.h文件中没有成员变量
#pragmaexecution_character_set("utf-8")#include"mainwindow.h"#include<QDockWidget>#include<QVBoxLayout>#include<QHBoxLayout>#include<QTextEdit>MainWindow::MainWindow(QWidget *parent):QMainWindow(parent){
QDockWidget *leftdock =new QDockWidget;
leftdock->setWindowTitle("左布局窗口");
QWidget* leftwidget =newQWidget();//左侧停靠窗口内部的widget
QVBoxLayout *leftlayout =newQVBoxLayout(leftwidget);//左侧停靠窗口widget中的布局器
QTextEdit* text1 =newQTextEdit("这里是第一个窗口的内容");
leftlayout->addWidget(text1);//左侧添加了一个控件
leftdock->setWidget(leftwidget);this->addDockWidget(Qt::LeftDockWidgetArea, leftdock);//添加到左侧窗口,标志位Qt手册里找
QDockWidget *rightdock1 =new QDockWidget;
rightdock1->setWindowTitle("右侧布局一");
QWidget* rightwidget1 =newQWidget();//左侧停靠窗口内部的widget
QVBoxLayout *rightlayout1 =newQVBoxLayout(rightwidget1);//左侧停靠窗口widget中的布局器
QTextEdit* text2 =newQTextEdit("这里是第二个窗口的内容");
rightlayout1->addWidget(text2);//左侧添加了一个控件
rightdock1->setWidget(rightwidget1);this->addDockWidget(Qt::RightDockWidgetArea, rightdock1);//添加右侧窗口
QDockWidget *rightdock2 =new QDockWidget;
rightdock2->setWindowTitle("右侧布局二");
QWidget* rightwidget2 =newQWidget();//左侧停靠窗口内部的widget
QVBoxLayout *rightlayout2 =newQVBoxLayout(rightwidget2);//左侧停靠窗口widget中的布局器
QTextEdit* text3 =newQTextEdit("这里是第二个窗口的内容");
rightlayout2->addWidget(text3);//左侧添加了一个控件
rightdock2->setWidget(rightwidget2);this->addDockWidget(Qt::RightDockWidgetArea, rightdock2);//添加右侧窗口}
运行结果应该是:这时候布局左右五五分,右边上下五五分
如下图:
注意:如果项目工程里有一个空的.ui文件,并且使用了.ui文件编辑出来的.h文件,设置了Ui再手写界面,放大主程序全屏,三个停靠窗口就不会是全屏的,就是三个窗口无法自适应大小。
解决方式一:左右中间加上一个临时的控件也行。不建议用,因为不利于设置窗口比例。
// QWidget *tempWidget = new QWidget();// tempWidget->setFixedSize(0,0);// setCentralWidget(tempWidget);
设置停靠窗的比例
解决方式二:将三个QDockWidget类停靠窗临时变量提升至QMainWindow的成员变量,写在.h中
再重写resizeEvent()虚函数;
这时候mainwindow.h文件代码:
#include<QMainWindow>#include<QDockWidget>classMainWindow:publicQMainWindow{
Q_OBJECT
public:MainWindow(QWidget *parent =nullptr);~MainWindow();protected:voidresizeEvent(QResizeEvent *event);private:
QDockWidget *leftdock,*rightdock1,*rightdock2;};
再废话一句,mainwindow.cpp中的三个new变量写法改这样,一定要给对象起名字哦,要不然后面没办法保存对象信息:
leftdock =new QDockWidget;
leftdock->setObjectName("leftdock");//...
rightdock1 =new QDockWidget;
rightdock1->setObjectName("rightdock1");//...
rightdock2 =new QDockWidget;
rightdock2->setObjectName("rightdock2");
mainwindow.cpp中的resizeEvent()函数的实现如下:
voidMainWindow::resizeEvent(QResizeEvent *event){int width1 =int(this->width()*0.15);//左边的停靠窗宽是主界面的0.15倍int width2 =int(this->width()*0.85);//右边的停靠窗宽是主界面的0.85倍this->resizeDocks({rightdock1,rightdock2},{10,40},Qt::Vertical);//右侧上下布局一四分this->resizeDocks({leftdock,rightdock1,rightdock2},{width1,width2,width2},Qt::Horizontal);//左右水平布局015:0.85}
运行结果如下:
QDockWidget停靠窗设置比例的部分写完了,再想加一个上方的菜单栏按钮
保存布局和恢复布局
mainwindow.h中添加以下代码:
private:
QAction *save_layout,*restart_layout;
QSettings *setting;//保存布局用的配置文件类,也可以用别的方式保存public slots:voidslot_save_layout();voidslot_restart_layout();
mainwindow.cpp构造函数MainWindow::MainWindow中添加以下代码:
QMenuBar *menuBar =newQMenuBar(this);this->setMenuBar(menuBar);//设置菜单条
QMenu *menu =this->menuBar()->addMenu("布局设置");
save_layout =newQAction("保存布局");connect(save_layout,&QAction::triggered,this,&MainWindow::slot_save_layout);
menu->addAction(save_layout);
restart_layout =newQAction("恢复布局");connect(restart_layout,&QAction::triggered,this,&MainWindow::slot_restart_layout);
menu->addAction(restart_layout);//exe执行程序旁边生成一个配置文件,用来寸界面布局QDockWidget类成员的信息,文件名随便取,格式随便写
setting =newQSettings(QCoreApplication::applicationDirPath()+"/layout_config.txt",QSettings::IniFormat);
setting->setIniCodec(QTextCodec::codecForName("utf-8"));//文件字节编码设置成utf-8
mainwindow.cpp最后中添加两个保存布局和恢复布局的槽函数:
voidMainWindow::slot_save_layout(){
setting->setValue("LAYOUT/geometry",saveGeometry());//保存QDockWidget类成员的形状和大小
setting->setValue("LAYOUT/state",saveState());//保存QDockWidget类成员的状态有的
setting->sync();//立刻写入磁盘文件中}voidMainWindow::slot_restart_layout(){//下面读取形状大小和读取状态可以选择一个读取,根据喜好可以注释一行restoreGeometry(setting->value("LAYOUT/geometry").toByteArray());restoreState(setting->value("LAYOUT/state").toByteArray());
QList<QDockWidget*> dwList =this->findChildren<QDockWidget*>();foreach(QDockWidget* dw,dwList){restoreDockWidget(dw);}}
左上角多了一个菜单条:
测试一下:先点把界面拖拽改变布局比例,点击保存布局菜单按钮,再将三个停靠窗随意拖拽或者独立出来,或者删除一个停靠窗,点上方的菜单栏的恢复布局,测试成功后,再试试恢复布局槽函数中,restoreGeometry()和restoreState()随机注销一个,再保存、恢复是什么效果。
如图:
整段的代码
mainwindow.h:
#ifndefMAINWINDOW_H#defineMAINWINDOW_H#include<QMainWindow>#include<QDockWidget>#include<QAction>#include<QSettings>classMainWindow:publicQMainWindow{
Q_OBJECT
public:MainWindow(QWidget *parent =nullptr);~MainWindow();protected:voidresizeEvent(QResizeEvent *event);private:
QDockWidget *leftdock,*rightdock1,*rightdock2;
QAction *save_layout,*restart_layout;
QSettings *setting;public slots:voidslot_save_layout();voidslot_restart_layout();};#endif// MAINWINDOW_H
mainwindow.cpp:
#pragmaexecution_character_set("utf-8")#include"mainwindow.h"#include<QDockWidget>#include<QVBoxLayout>#include<QHBoxLayout>#include<QTextEdit>#include<QMenuBar>#include<QCoreApplication>#include<QTextCodec>MainWindow::MainWindow(QWidget *parent):QMainWindow(parent){
leftdock =new QDockWidget;
leftdock->setObjectName("leftdock");
leftdock->setWindowTitle("左窗口");
QWidget* leftwidget =newQWidget();//左侧停靠窗口内部的widget
QVBoxLayout *leftlayout =newQVBoxLayout(leftwidget);//左侧停靠窗口widget中的布局器
QTextEdit* text1 =newQTextEdit("这里是第一个窗口的内容");
leftlayout->addWidget(text1);//左侧添加了一个控件
leftdock->setWidget(leftwidget);this->addDockWidget(Qt::LeftDockWidgetArea, leftdock);//添加到左侧窗口,标志位Qt手册里找
rightdock1 =new QDockWidget;
rightdock1->setObjectName("rightdock1");
rightdock1->setWindowTitle("右窗口一");
QWidget* rightwidget1 =newQWidget();//左侧停靠窗口内部的widget
QVBoxLayout *rightlayout1 =newQVBoxLayout(rightwidget1);//左侧停靠窗口widget中的布局器
QTextEdit* text2 =newQTextEdit("这里是第二个窗口的内容");
rightlayout1->addWidget(text2);//左侧添加了一个控件
rightdock1->setWidget(rightwidget1);this->addDockWidget(Qt::RightDockWidgetArea, rightdock1);//添加右侧窗口
rightdock2 =new QDockWidget;
rightdock2->setObjectName("rightdock2");
rightdock2->setWindowTitle("右窗口二");
QWidget* rightwidget2 =newQWidget();//左侧停靠窗口内部的widget
QVBoxLayout *rightlayout2 =newQVBoxLayout(rightwidget2);//左侧停靠窗口widget中的布局器
QTextEdit* text3 =newQTextEdit("这里是第三个窗口的内容");
rightlayout2->addWidget(text3);//左侧添加了一个控件
rightdock2->setWidget(rightwidget2);this->addDockWidget(Qt::RightDockWidgetArea, rightdock2);//添加右侧窗口
QMenuBar *menuBar =newQMenuBar(this);this->setMenuBar(menuBar);//设置菜单条
QMenu *menu =this->menuBar()->addMenu("布局设置");
save_layout =newQAction("保存布局");connect(save_layout,&QAction::triggered,this,&MainWindow::slot_save_layout);
menu->addAction(save_layout);
restart_layout =newQAction("恢复布局");connect(restart_layout,&QAction::triggered,this,&MainWindow::slot_restart_layout);
menu->addAction(restart_layout);//exe执行程序旁边生成一个配置文件,用来寸界面布局QDockWidget类成员的信息,文件名随便取,格式随便写
setting =newQSettings(QCoreApplication::applicationDirPath()+"/layout_config.txt",QSettings::IniFormat);
setting->setIniCodec(QTextCodec::codecForName("utf-8"));//文件字节编码设置成utf-8}MainWindow::~MainWindow(){}voidMainWindow::resizeEvent(QResizeEvent *event){int width1 =int(this->width()*0.15);//左边的停靠窗宽是主界面的0.15倍int width2 =int(this->width()*0.85);//右边的停靠窗宽是主界面的0.85倍this->resizeDocks({rightdock1,rightdock2},{10,40},Qt::Vertical);//右侧上下布局一四分this->resizeDocks({leftdock,rightdock1,rightdock2},{width1,width2,width2},Qt::Horizontal);//左右水平布局015:0.85}voidMainWindow::slot_save_layout(){
setting->setValue("LAYOUT/geometry",saveGeometry());//保存QDockWidget类成员的形状和大小
setting->setValue("LAYOUT/state",saveState());//保存QDockWidget类成员的状态有的
setting->sync();//立刻写入磁盘文件中}voidMainWindow::slot_restart_layout(){//下面读取形状大小和读取状态可以选择一个读取,根据喜好可以注释一行restoreGeometry(setting->value("LAYOUT/geometry").toByteArray());restoreState(setting->value("LAYOUT/state").toByteArray());
QList<QDockWidget*> dwList =this->findChildren<QDockWidget*>();foreach(QDockWidget* dw,dwList){restoreDockWidget(dw);}}
版权归原作者 黄猿欲度愁攀援 所有, 如有侵权,请联系我们删除。