多界面切換技巧——Qt

前言

微信中需要很多界面之間的相互切換,比如各種聊天對話框的轉換。這麼多的界面是怎麼實現切換的,而內存大小穩定在一定的水平下,而不是界面的一直隨着界面的增長而增長。

我寫了類似的微信的東西,我算了算大概有三十左右個界面,而且還沒寫完。若全部實例化,那將會挺大的,而且也不合適,有的界面出現的頻率並不是很大,若只因出現了一次,就一直保存着這塊內存,很浪費。所以我想了個解決辦法,可能不是最優化的,但是也是有些作用的。

 

思路及代碼

界面切換,我用的是QStackedWidget,因爲我只是部分界面切換,這個還是比較好用的。

我的思路就是:將界面進行標號,分爲常用和不常用的,若是不常用的,若被切換掉後就將此移除,繼而刪除。

界面標號,我用到了QObject的方法setProperty來攜帶數據,通過此數據進行區分。

數據,我自定義了一個結構體

struct LevelValue {
  int iLevel;     //界面等級 
  int iFormType; //界面類型(0聊天/1工作/2聯繫人/3我的)
};
Q_DECLARE_METATYPE(LevelValue)

每個界面都進行屬性設置

    //設置界面等級
    LevelValue data;
    data.iLevel=2;
    data.iFormType=0;
    QVariant var=QVariant::fromValue(data);
    this->setProperty("LevelValue",var);

然後,在界面切換時,判斷上一個界面的是否需刪除,上一個界面我通過指針QWidget* m_pPreWidget來保存。

m_pPreWidget=nullptr;
connect(ui->formStacked,SIGNAL(currentChanged(int)),this,SLOT(stackedCurrentChanged(int)));

void MainWidget::stackedCurrentChanged(int index)
{

    if(m_pPreWidget!=nullptr)
    {
         QVariant var=m_pPreWidget->property("LevelValue");
         if(!var.canConvert<LevelValue>())
             return;
         LevelValue level=var.value<LevelValue>();
         if(level.iLevel==3)
         {//暫定當界面等級爲三級時需移除
             //容器移除
             QString name=m_nameIndexMap.key((long)m_pPreWidget);
             m_nameIndexMap.remove(name);
             //界面移除
             ui->formStacked->removeWidget(m_pPreWidget);
             m_pPreWidget->deleteLater();
         }
    }
    m_pPreWidget=ui->formStacked->currentWidget();
}

 後續中,我發現我有的界面雖然屬於不常用、要刪除的行列,但是他需要再切換回來,所以我又增加一容器來保存需要再切換的界面(即不能刪除的界面),若上一個界面包含在此容器內,那麼則不用刪除。所以這個完整的代碼是:

void MainWidget::stackedCurrentChanged(int index)
{
    //最新界面容器更新
    QWidget* pCurWidget=ui->formStacked->widget(index);
    //LevelValue *data=(LevelValue*)pCurWidget->userData(Qt::UserRole);
    QVariant var=pCurWidget->property("LevelValue");

    if(var.canConvert<LevelValue>())
    {
        LevelValue data=var.value<LevelValue>();
        int iType=data.iFormType;
        m_latestForms[iType]=pCurWidget;
    }

    //刪除無用的
    if(m_pPreWidget!=nullptr)
    {
        //判斷是否是其他模塊最新界面,是則不能刪除
        bool iflag=false;
        foreach(QWidget* pWidget,m_latestForms)
        {
            if(pWidget==m_pPreWidget)
            {
                iflag=true;
                break;
            }
        }
        if(!iflag)
        {
            //LevelValue *level=(LevelValue*)m_pPreWidget->userData(Qt::UserRole);
            QVariant var=m_pPreWidget->property("LevelValue");
            if(!var.canConvert<LevelValue>())
                return;
            LevelValue level=var.value<LevelValue>();
            if(level.iLevel==3)
            {//暫定當界面等級爲三級時需移除
                //容器移除
                QString name=m_nameIndexMap.key((long)m_pPreWidget);
                m_nameIndexMap.remove(name);
                //界面移除
                ui->formStacked->removeWidget(m_pPreWidget);
                m_pPreWidget->deleteLater();
            }
        }
    }
    m_pPreWidget=ui->formStacked->currentWidget();
}

 

結束語

第一次做這麼多界面之間的切換,後續若算法優化,將繼續更新,修改,看到的大佬有更好的東西,希望不嗇賜教。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章