网络知识 娱乐 Qt中QDockWidget停靠窗之设置布局比例,保存布局和恢复布局

Qt中QDockWidget停靠窗之设置布局比例,保存布局和恢复布局

新建一个QMainWindow的空项目

(懒得看又臭又长直接到最后复制整段代码)

先新建一个QMainWindow的空项目,不使用.ui文件。
这时候mainwindow.h文件中没有成员变量

#pragma execution_character_set("utf-8")
#include "mainwindow.h"
#include 
#include 
#include 
#include 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QDockWidget *leftdock = new QDockWidget;
    leftdock->setWindowTitle("左布局窗口");
    QWidget* leftwidget = new QWidget();//左侧停靠窗口内部的widget
    QVBoxLayout *leftlayout = new QVBoxLayout(leftwidget);//左侧停靠窗口widget中的布局器
    QTextEdit* text1 = new QTextEdit("这里是第一个窗口的内容");
    leftlayout->addWidget(text1);//左侧添加了一个控件
    leftdock->setWidget(leftwidget);
    this->addDockWidget(Qt::LeftDockWidgetArea, leftdock);//添加到左侧窗口,标志位Qt手册里找

    QDockWidget *rightdock1 = new QDockWidget;
    rightdock1->setWindowTitle("右侧布局一");
    QWidget* rightwidget1 = new QWidget();//左侧停靠窗口内部的widget
    QVBoxLayout *rightlayout1 = new QVBoxLayout(rightwidget1);//左侧停靠窗口widget中的布局器
    QTextEdit* text2 = new QTextEdit("这里是第二个窗口的内容");
    rightlayout1->addWidget(text2);//左侧添加了一个控件
    rightdock1->setWidget(rightwidget1);
    this->addDockWidget(Qt::RightDockWidgetArea, rightdock1);//添加右侧窗口

    QDockWidget *rightdock2 = new QDockWidget;
    rightdock2->setWindowTitle("右侧布局二");
    QWidget* rightwidget2 = new QWidget();//左侧停靠窗口内部的widget
    QVBoxLayout *rightlayout2 = new QVBoxLayout(rightwidget2);//左侧停靠窗口widget中的布局器
    QTextEdit* text3 = new QTextEdit("这里是第二个窗口的内容");
    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 
#include 
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    void resizeEvent(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()函数的实现如下:


void MainWindow::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:
    void slot_save_layout();
    void slot_restart_layout();

mainwindow.cpp构造函数MainWindow::MainWindow中添加以下代码:


    QMenuBar *menuBar = new QMenuBar(this);
    this->setMenuBar(menuBar);//设置菜单条
    QMenu *menu = this->menuBar()->addMenu("布局设置");

    save_layout = new QAction("保存布局");
    connect(save_layout,&QAction::triggered,this,&MainWindow::slot_save_layout);
    menu->addAction(save_layout);

    restart_layout = new QAction("恢复布局");
    connect(restart_layout,&QAction::triggered,this,&MainWindow::slot_restart_layout);
    menu->addAction(restart_layout);

    //exe执行程序旁边生成一个配置文件,用来寸界面布局QDockWidget类成员的信息,文件名随便取,格式随便写
    setting = new QSettings(QCoreApplication::applicationDirPath() + "/layout_config.txt",QSettings::IniFormat);
    setting->setIniCodec(QTextCodec::codecForName("utf-8"));//文件字节编码设置成utf-8

mainwindow.cpp最后中添加两个保存布局和恢复布局的槽函数:


void MainWindow::slot_save_layout()
{
    setting->setValue("LAYOUT/geometry",saveGeometry());//保存QDockWidget类成员的形状和大小
    setting->setValue("LAYOUT/state",saveState());//保存QDockWidget类成员的状态有的
    setting->sync();//立刻写入磁盘文件中
}

void MainWindow::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:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include 
#include 
#include 
#include 
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    void resizeEvent(QResizeEvent *event);

private:
    QDockWidget *leftdock,*rightdock1,*rightdock2;
    QAction *save_layout,*restart_layout;
    QSettings *setting;

public slots:
    void slot_save_layout();
    void slot_restart_layout();

};
#endif // MAINWINDOW_H

mainwindow.cpp:

#pragma execution_character_set("utf-8")
#include "mainwindow.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    leftdock = new QDockWidget;
    leftdock->setObjectName("leftdock");
    leftdock->setWindowTitle("左窗口");
    QWidget* leftwidget = new QWidget();//左侧停靠窗口内部的widget
    QVBoxLayout *leftlayout = new QVBoxLayout(leftwidget);//左侧停靠窗口widget中的布局器
    QTextEdit* text1 = new QTextEdit("这里是第一个窗口的内容");
    leftlayout->addWidget(text1);//左侧添加了一个控件
    leftdock->setWidget(leftwidget);
    this->addDockWidget(Qt::LeftDockWidgetArea, leftdock);//添加到左侧窗口,标志位Qt手册里找

    rightdock1 = new QDockWidget;
    rightdock1->setObjectName("rightdock1");
    rightdock1->setWindowTitle("右窗口一");
    QWidget* rightwidget1 = new QWidget();//左侧停靠窗口内部的widget
    QVBoxLayout *rightlayout1 = new QVBoxLayout(rightwidget1);//左侧停靠窗口widget中的布局器
    QTextEdit* text2 = new QTextEdit("这里是第二个窗口的内容");
    rightlayout1->addWidget(text2);//左侧添加了一个控件
    rightdock1->setWidget(rightwidget1);
    this->addDockWidget(Qt::RightDockWidgetArea, rightdock1);//添加右侧窗口

    rightdock2 = new QDockWidget;
    rightdock2->setObjectName("rightdock2");
    rightdock2->setWindowTitle("右窗口二");
    QWidget* rightwidget2 = new QWidget();//左侧停靠窗口内部的widget
    QVBoxLayout *rightlayout2 = new QVBoxLayout(rightwidget2);//左侧停靠窗口widget中的布局器
    QTextEdit* text3 = new QTextEdit("这里是第三个窗口的内容");
    rightlayout2->addWidget(text3);//左侧添加了一个控件
    rightdock2->setWidget(rightwidget2);
    this->addDockWidget(Qt::RightDockWidgetArea, rightdock2);//添加右侧窗口

    QMenuBar *menuBar = new QMenuBar(this);
    this->setMenuBar(menuBar);//设置菜单条
    QMenu *menu = this->menuBar()->addMenu("布局设置");

    save_layout = new QAction("保存布局");
    connect(save_layout,&QAction::triggered,this,&MainWindow::slot_save_layout);
    menu->addAction(save_layout);

    restart_layout = new QAction("恢复布局");
    connect(restart_layout,&QAction::triggered,this,&MainWindow::slot_restart_layout);
    menu->addAction(restart_layout);

    //exe执行程序旁边生成一个配置文件,用来寸界面布局QDockWidget类成员的信息,文件名随便取,格式随便写
    setting = new QSettings(QCoreApplication::applicationDirPath() + "/layout_config.txt",QSettings::IniFormat);
    setting->setIniCodec(QTextCodec::codecForName("utf-8"));//文件字节编码设置成utf-8
}

MainWindow::~MainWindow()
{
}

void MainWindow::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
}

void MainWindow::slot_save_layout()
{
    setting->setValue("LAYOUT/geometry",saveGeometry());//保存QDockWidget类成员的形状和大小
    setting->setValue("LAYOUT/state",saveState());//保存QDockWidget类成员的状态有的
    setting->sync();//立刻写入磁盘文件中
}

void MainWindow::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);
    }
}