最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Qt實現(xiàn)手動切換多種布局的完美方案

 更新時間:2024年07月02日 14:23:00   作者:肩上風(fēng)騁  
通過點擊程序界面上不同的布局按鈕,使主工作區(qū)呈現(xiàn)出不同的頁面布局,多個布局之間可以通過點擊不同布局按鈕切換,支持的最多的窗口為9個,不同布局下窗口數(shù)隨之變化,這篇文章主要介紹了Qt實現(xiàn)手動切換多種布局的完美方案,需要的朋友可以參考下

引言

之前寫了一個手動切換多個布局的程序,下面來記錄一下。
程序運(yùn)行效果如下:

示例

需求

通過點擊程序界面上不同的布局按鈕,使主工作區(qū)呈現(xiàn)出不同的頁面布局,多個布局之間可以通過點擊不同布局按鈕切換。支持的最多的窗口為9個。不同布局下窗口數(shù)隨之變化。

開發(fā)環(huán)境

使用的QtCreator12.0.2,基于Qt5.15.2庫開發(fā)。

代碼實現(xiàn)

創(chuàng)建基于QApplication的應(yīng)用程序。
下面是實現(xiàn)代碼:
main.cpp

#include "manullayoutdialog.h"
#include <QApplication>
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 <QObject>
#include <QWidget>
#include <QVector>
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<QWidget*> m_vecWidget;
};
#endif // OBJECTPOOLING_H

ObjectPooling.cpp

#include "objectpooling.h"
#include <qDebug>
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 : "<<m_vecWidget.size();
        m_vecWidget.pop_back();
//       qDebug()<<"takeOut-back : "<<m_vecWidget.size();
       return pWidget;
    }
    qDebug()<<"對象池沒有對象了!!";
    return nullptr;
}
void ObjectPooling::putIn(QWidget *pWidget)
{
    m_vecWidget.push_back(pWidget);
}
int ObjectPooling::getSize() const
{
    return m_vecWidget.size();
}

ManulLayoutDialog.h

#ifndef MANULLAYOUTDIALOG_H
#define MANULLAYOUTDIALOG_H
#include <QDialog>
#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——新的布局中窗口的總數(shù)
    void threeColumnLayout(int r,int c);//r——行數(shù),c——列數(shù)
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;//布局中窗口的總個數(shù)
    QVector<QWidget*> m_vecWidget;//保存布局中的窗口
    ObjectPooling* m_pool;
};
#endif // MANULLAYOUTDIALOG_H

ManulLayoutDialog.cpp

#include "manullayoutdialog.h"
#include "ui_manullayoutdialog.h"
#include <QDebug>
ManulLayoutDialog::ManulLayoutDialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::ManulLayoutDialog)
{
    ui->setupUi(this);
    initLayout();
}
ManulLayoutDialog::~ManulLayoutDialog()
{
    for(QWidget *pWidget:m_vecWidget){
        pWidget->setParent(nullptr);//不設(shè)置被回收的窗口父對象為空,會被再次釋放
        ObjectPooling::getInstance(9)->putIn(pWidget);
    }
    m_vecWidget.clear();
    delete ui;//若被回收的窗口沒有設(shè)置父對象為空,這里會析構(gòu)該窗口,回收到對象池后會再次析構(gòu)
}
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()<<"移除前的窗口數(shù)m_vecWidget: "<<m_vecWidget.size();
    if(m_n>n){
        for(int i =0; i <m_n -n;++i){//趟數(shù)
            //移除窗口中的控件,回收到對象池
            QWidget *pWidget = m_vecWidget.back();
            if(pLayout && pWidget){
                qDebug()<<"準(zhǔn)備移除窗口===";
                pLayout->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()<<"對象池窗口數(shù)m_vecWidget: "<<ObjectPooling::getInstance(9)->getSize();
            // qDebug()<<"移除后的窗口數(shù)m_vecWidget: "<<m_vecWidget.size();
        }
    }else if(m_n <n){
        //為了防止二次重設(shè)父對象,先將上一次的父對象清空
        for(auto it = m_vecWidget.begin();it != m_vecWidget.end();++it){
            if(*it){
                (*it)->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);//找下標(biāo)對應(yīng)的位置與元素之間的關(guān)系
        }
    }
    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中的窗口數(shù)m_vecWidget: "<<m_vecWidget.size();
    pHLayout->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中的窗口數(shù)m_vecWidget: "<<m_vecWidget.size();
}
void ManulLayoutDialog::on_pushButton_3_clicked()
{
    if(m_n == 4){
        return ;
    }
    clearLastLayout(4);//只能先清理之前的布局,不能與下面的新布局互換位置
    QGridLayout *pGridLayout = new QGridLayout(ui->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);//找下標(biāo)對應(yīng)的位置與元素之間的關(guān)系
        }
    }
    m_n = 4;
}
void ManulLayoutDialog::on_pushButton_4_clicked()
{
    threeColumnLayout(2,3);
}
void ManulLayoutDialog::on_pushButton_5_clicked()
{
    threeColumnLayout(3,3);
}

運(yùn)行結(jié)果

選一種的2行6列布局下的效果的截圖。具體的運(yùn)行效果和文章開始的效果一樣。

程序分析

項目中先創(chuàng)建了一個單例模式下的對象池,負(fù)責(zé)布局中總窗口的創(chuàng)建、回收,取出、以及存入。同時創(chuàng)建了一個手動布局類ManulLayoutDialog,在該類中實現(xiàn)了在界面上點擊不同布局按鈕的響應(yīng),ObjectPooling類作為手動布局類ManulLayoutDialog的成員函數(shù),兩個類之間是一種關(guān)聯(lián)的關(guān)系。采用隊列存放布局中的窗口,當(dāng)要切換的布局中的窗口數(shù)大于當(dāng)前的窗口布局中的窗口數(shù),則先清除之前的窗口布局,將布局中的窗口回收到窗口數(shù)組中,同時向?qū)ο蟪刂腥〕鱿嗖顢?shù)量的窗口,放入窗口數(shù)組,創(chuàng)建新的布局,將窗口數(shù)組中的窗口加入新布局;當(dāng)要切換的布局中的窗口數(shù)小于當(dāng)前的窗口布局中的窗口數(shù),則先從布局中移除相差數(shù)量的窗口,將移除的窗口從窗口數(shù)組中去除,刪除窗口原來的布局,同時將移除的窗口存入對象池中,創(chuàng)建新的布局,將窗口數(shù)組中的窗口加入到新的布局。

注意

示例中有兩個需要注意的點:
1.對象池中窗口的釋放。 可看ManulLayoutDialog的析構(gòu)函數(shù)。
2.原本布局中窗口的回收。 可看clearLastLayout函數(shù)。
上面的兩點在代碼的注釋中有寫,是為重點注意項。

到此這篇關(guān)于Qt實現(xiàn)手動切換多種布局的文章就介紹到這了,更多相關(guān)Qt切換多種布局內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

青冈县| 淮滨县| 横峰县| 大英县| 昌乐县| 涞源县| 彰武县| 濮阳县| 洮南市| 铜山县| 洮南市| 新源县| 青海省| 永川市| 乌什县| 石河子市| 溧水县| 隆昌县| 湖南省| 巴彦县| 鸡西市| 洪洞县| 岐山县| 台州市| 刚察县| 黄石市| 洛扎县| 揭东县| 嘉义市| 神池县| 长汀县| 鄄城县| 南木林县| 邵武市| 邳州市| 龙海市| 新河县| 萝北县| 扎赉特旗| 安化县| 淳安县|