qt实现手动切换多种布局的完美方案-kb88凯时官网登录

来自:网络
时间:2024-09-10
阅读:
免费资源网,https://freexyz.cn/

引言

之前写了一个手动切换多个布局的程序,下面来记录一下。
程序运行效果如下:

qt实现手动切换多种布局的完美方案

示例

需求

通过点击程序界面上不同的布局按钮,使主工作区呈现出不同的页面布局,多个布局之间可以通过点击不同布局按钮切换。支持的最多的窗口为9个。不同布局下窗口数随之变化。

开发环境

使用的qtcreator12.0.2,基于qt5.15.2库开发。

代码实现

创建基于qapplication的应用程序。
下面是实现代码:
main.cpp

#include "manullayoutdialog.h"
#include 
int main(int argc, char *argv[])
{
    qapplication a(argc, argv);
    manullayoutdialog w;
    w.show();
    objectpooling*m_pool = objectpooling::getinstance(9);
    return a.exec();
}

objectpooling.h

#ifndef objectpooling_h
#define objectpooling_h
#include 
#include 
#include 
class objectpooling:public qobject
{
    q_object
private:
    objectpooling(qint32 num);
    objectpooling(const objectpooling &) = delete;
    objectpooling& operator=(const objectpooling&)=delete;
public:
    static objectpooling *getinstance(qint32 num);
    ~objectpooling();
    qwidget* takeout();
    void putin(qwidget *pwidget);
    int getsize()const;
private:
    qvector m_vecwidget;
};
#endif // objectpooling_h

objectpooling.cpp

#include "objectpooling.h"
#include 
objectpooling::objectpooling(qint32 num):qobject() {
    for(int i = 0; i < num;  i){
        qwidget *pwidget = new qwidget;
        if(pwidget){
            pwidget->setstylesheet("background-color:back;");
            m_vecwidget.push_back(pwidget);
        }
    }
}
objectpooling *objectpooling::getinstance(qint32 num)
{
    static objectpooling instance(num);
    return &instance;
}
objectpooling::~objectpooling()
{
    if(m_vecwidget.size()<1)
        return;
    for(auto it = m_vecwidget.begin();it != m_vecwidget.end();  it){
        if(*it){
            delete *it;
            (*it) = nullptr;
        }
    }
    m_vecwidget.clear();
}
qwidget *objectpooling::takeout()
{
    if(m_vecwidget.size()){
       qwidget*pwidget = m_vecwidget.back();
//        qdebug()<<"takeout-befor : "<

manullayoutdialog.h

#ifndef manullayoutdialog_h
#define manullayoutdialog_h
#include 
#include "objectpooling.h"
qt_begin_namespace
namespace ui {
class manullayoutdialog;
}
qt_end_namespace
class manullayoutdialog : public qdialog
{
    q_object
public:
    manullayoutdialog(qwidget *parent = nullptr);
    ~manullayoutdialog();
private:
    void initlayout();
    void clearlastlayout(int n);//n——新的布局中窗口的总数
    void threecolumnlayout(int r,int c);//r——行数,c——列数
private slots:
    void on_pushbutton_clicked();
    void on_pushbutton_2_clicked();
    void on_pushbutton_3_clicked();
    void on_pushbutton_4_clicked();
    void on_pushbutton_5_clicked();
private:
    ui::manullayoutdialog *ui;
    qint32 m_n;//布局中窗口的总个数
    qvector m_vecwidget;//保存布局中的窗口
    objectpooling* m_pool;
};
#endif // manullayoutdialog_h

manullayoutdialog.cpp

#include "manullayoutdialog.h"
#include "ui_manullayoutdialog.h"
#include 
manullayoutdialog::manullayoutdialog(qwidget *parent)
    : qdialog(parent)
    , ui(new ui::manullayoutdialog)
{
    ui->setupui(this);
    initlayout();
}
manullayoutdialog::~manullayoutdialog()
{
    for(qwidget *pwidget:m_vecwidget){
        pwidget->setparent(nullptr);//不设置被回收的窗口父对象为空,会被再次释放
        objectpooling::getinstance(9)->putin(pwidget);
    }
    m_vecwidget.clear();
    delete ui;//若被回收的窗口没有设置父对象为空,这里会析构该窗口,回收到对象池后会再次析构
}
void manullayoutdialog::initlayout()
{
    qhboxlayout *phlayout = new qhboxlayout(ui->widget);
    phlayout->setcontentsmargins(0,0,0,0);
    qwidget *pwidget = objectpooling::getinstance(9)->takeout();
    phlayout->addwidget(pwidget);
    m_n = 1;
    m_vecwidget.push_back(pwidget);
    m_pool = objectpooling::getinstance(9);
}
void manullayoutdialog::clearlastlayout(int n)
{
    qlayout *playout = ui->widget->layout();
//    qdebug()<<"移除前的窗口数m_vecwidget: "<n){
        for(int i =0; i removewidget(pwidget);
                pwidget->setparent(nullptr);
                m_vecwidget.pop_back();
            }
            // if(playout){qdebug()<<"布局不为空 ";}
            // if(pwidget){qdebug()<<"窗口不为空 ";}
            // qwidget *fwidget = pwidget->parentwidget();
            objectpooling::getinstance(9)->putin(pwidget);
            // qdebug()<<"对象池窗口数m_vecwidget: "<getsize();
            // qdebug()<<"移除后的窗口数m_vecwidget: "<setparent(nullptr);
            }
        }
        for(int i = 0; i < n-m_n;  i){
            m_vecwidget.push_back(objectpooling::getinstance(9)->takeout());
        }
    }
    //删除窗口原本的布局
    delete playout;
    //    ui->widget->setlayout(nullptr);
}
void manullayoutdialog::threecolumnlayout(int r, int c)
{
    int total = r*c;
    if(m_n == total){
        return ;
    }
    clearlastlayout(total);
    qgridlayout *pgridlayout = new qgridlayout(ui->widget);
    pgridlayout->setcontentsmargins(0,0,0,0);
    for(int i = 0; i < r;  i){
        for(int j = 0; j < c;   j){
            pgridlayout->addwidget(m_vecwidget[i j 2*i],i,j);//找下标对应的位置与元素之间的关系
        }
    }
    m_n = total;
}
void manullayoutdialog::on_pushbutton_clicked()
{
    if(m_n == 1){
        return ;
    }else{
        clearlastlayout(1);
    }
    qhboxlayout *phlayout = new qhboxlayout(ui->widget);
    phlayout->setcontentsmargins(0,0,0,0);
    // qdebug()<<"布局1中的窗口数m_vecwidget: "<addwidget(m_vecwidget.back());
    m_n = 1;
}
void manullayoutdialog::on_pushbutton_2_clicked()
{
    if(m_n == 2){
        return ;
    }else if(m_n > 2){
        clearlastlayout(2);
        qhboxlayout *playout = new qhboxlayout(ui->widget);
        playout->setcontentsmargins(0,0,0,0);
        for(auto it = m_vecwidget.begin();it != m_vecwidget.end();  it){
            playout->addwidget(*it);
        }
    }else{
        qlayout *playout = ui->widget->layout();
        qwidget *pwidget = objectpooling::getinstance(9)->takeout();
        playout->addwidget(pwidget);
        m_vecwidget.push_back(pwidget);
    }
    m_n = 2;
    // qdebug()<<"布局2中的窗口数m_vecwidget: "<widget);
    pgridlayout->setcontentsmargins(0,0,0,0);
    for(int i = 0; i < 2;  i){
        for(int j = 0; j < 2;   j){
            pgridlayout->addwidget(m_vecwidget[i j i],i,j);//找下标对应的位置与元素之间的关系
        }
    }
    m_n = 4;
}
void manullayoutdialog::on_pushbutton_4_clicked()
{
    threecolumnlayout(2,3);
}
void manullayoutdialog::on_pushbutton_5_clicked()
{
    threecolumnlayout(3,3);
}

运行结果

选一种的2行6列布局下的效果的截图。具体的运行效果和文章开始的效果一样。

qt实现手动切换多种布局的完美方案

程序分析

项目中先创建了一个单例模式下的对象池,负责布局中总窗口的创建、回收,取出、以及存入。同时创建了一个手动布局类manullayoutdialog,在该类中实现了在界面上点击不同布局按钮的响应,objectpooling类作为手动布局类manullayoutdialog的成员函数,两个类之间是一种关联的关系。采用队列存放布局中的窗口,当要切换的布局中的窗口数大于当前的窗口布局中的窗口数,则先清除之前的窗口布局,将布局中的窗口回收到窗口数组中,同时向对象池中取出相差数量的窗口,放入窗口数组,创建新的布局,将窗口数组中的窗口加入新布局;当要切换的布局中的窗口数小于当前的窗口布局中的窗口数,则先从布局中移除相差数量的窗口,将移除的窗口从窗口数组中去除,删除窗口原来的布局,同时将移除的窗口存入对象池中,创建新的布局,将窗口数组中的窗口加入到新的布局。

注意

示例中有两个需要注意的点:
1.对象池中窗口的释放。 可看manullayoutdialog的析构函数。
2.原本布局中窗口的回收。 可看clearlastlayout函数。
上面的两点在代码的注释中有写,是为重点注意项。

免费资源网,https://freexyz.cn/
返回顶部
顶部
网站地图