天天看點

嵌入式Qt-實作兩個視窗的切換

之前的文章,分别有介紹過使用Qt程式實作一個時鐘和一個秒表,本篇,來将這兩個功能整合在一起,實作兩個頁面的随意切換,并且兩個頁面能獨立運作,互不影響。

先來看下最終的效果,通過左側的兩個按鈕,實作兩個頁面的切換。

嵌入式Qt-實作兩個視窗的切換

1 Qt堆棧視窗

本篇的頁面切換功能,是利用Qt的QStackedWidget實作的。

1.1QStackedWidget

QStackedWidget 類提供了多頁面切換的布局,一次隻能顯示一個界面。

1.2 基礎模闆

對于QStackedWidget的使用,可以先參考下面這個模闆,配合QLabel來控制頁面的切換:

#include "stackdlg.h"
#include <QHBoxLayout>

StackDlg::StackDlg(QWidget *parent)
    : QDialog(parent)
{
    setWindowTitle(tr("StackedWidget"));

    list = new QListWidget(this); //建立ListWidge
    list->insertItem(0, tr("Window1")); //ListWidge中添加Item
    list->insertItem(1, tr("Window2")); //ListWidge中添加Item
    list->insertItem(2, tr("Window3")); //ListWidge中添加Item

    stack = new QStackedWidget(this); //建立StackedWidget
    label1 = new QLabel(tr("WindowTest1"));
    label2 = new QLabel(tr("WindowTest2"));
    label3 = new QLabel(tr("WindowTest3"));
    stack->addWidget(label1); //StackedWidget中添加視窗1
    stack->addWidget(label2); //StackedWidget中添加視窗2
    stack->addWidget(label3); //StackedWidget中添加視窗3

    QHBoxLayout *mainLayout = new QHBoxLayout(this); //建立豎直布局器
    mainLayout->setMargin(5);
    mainLayout->setSpacing(5);
    mainLayout->addWidget(list);                      //放入ListWidge
    mainLayout->addWidget(stack,0, Qt::AlignHCenter); //放入StackedWidget
    mainLayout->setStretchFactor(list, 1);  //ListWidge的伸縮尺度是1
    mainLayout->setStretchFactor(stack, 3); //StackedWidget的伸縮尺度是3

    // ListWidge的行狀态變化時,切換對應的StackedWidget顯示
    connect(list, SIGNAL(currentRowChanged(int)), stack, SLOT(setCurrentIndex(int)));
}      

該代碼的運作效果如下:

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-SwJ6IO7N-1659970086705)(https://xxpcb-1259761082.cos.ap-shanghai.myqcloud.com/pic2/qt-arm/4-stackwidget/2.png)]

本篇就在這個模闆的基礎上,将Qt時鐘程式和Qt秒表程式移植過來。

2 移植時鐘與秒表程式

2.1 時鐘程式移植

将之前這篇中的程式作為一個獨立的視窗移植到本篇的程式中:​​嵌入式Qt-動手編寫并運作自己的第1個ARM-Qt程式​​

移植步驟:

  • Qt Creator中,堆棧視窗基礎工程的基礎上,點檔案菜單,再點建立檔案或項目,建立一個C++類,名字可取clockwidget
  • 嵌入式Qt-實作兩個視窗的切換
  • 将Qt時鐘的程式複制過來,代碼基本不需要修改,隻需要把類名換成ClockWidget即可

例如其構造函數如下:

ClockWidget::ClockWidget(QWidget *parent) : QWidget(parent)
{
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(1000);

    setWindowTitle(tr("Clock"));
    setMinimumSize(200, 200); //設定最小尺寸
}      

2.2 秒表程式移植

将之前這篇中的程式作為一個獨立的視窗移植到本篇的程式中:​​嵌入式Qt-做一個秒表​​

秒表這個Qt程式,用到了Qt Creator的圖形頁面設計,是以要主要移植的不同之處。

移植步驟:

  • Qt Creator中,堆棧視窗基礎工程的基礎上,點檔案菜單,再點建立檔案或項目,建立一個C++類,名字可取TimerWidget
  • 将ui檔案也拷貝過來,在工程中,通過添加現有檔案的方式,将ui檔案添加進工程
  • 另外,可以将移植過來的ui檔案,更名為TimerWidget.ui。需注意的是,修改了檔案名後,還需要将ui檔案以文本的形式打開,修改對應的類名為TimerWidget,要包含的頭檔案也改名為ui_TimerWidget.h
  • 嵌入式Qt-實作兩個視窗的切換

移植後的構造函數如下:

#include "timerwidget.h"
#include "ui_TimerWidget.h"
#include<QPainter>
#pragma execution_character_set("utf-8")

TimerWidget::TimerWidget(QWidget *parent) : QWidget(parent), ui(new Ui::TimerWidget)
{
    ui->setupUi(this);
    connect(&timer, SIGNAL(timeout()), this, SLOT(timeout_slot()));
    connect(&timer, SIGNAL(timeout()), this, SLOT(update()));
    connect(ui->Btn_Reset, SIGNAL(clicked()), this, SLOT(update()));

    time.setHMS(0,0,0,0);
    ui->Txt_ShowTime->setText("00:00:00");

    ui->Btn_Start->setChecked(false);
    ui->Btn_Reset->setEnabled(false);
    ui->Btn_Hit->setEnabled(false);
}      

注意頭檔案包含的是ui_TimerWidget.h,構造函數繼承的ui也是Ui::TimerWidget

2.3 主程式架構

移植好Qt時鐘程式和Qt秒表程式後,就可以将這兩個功能加入到堆棧視窗中了。

注意,下面的頁面切換,我改用兩個QPushButton來實作Qt時鐘和Qt秒表的頁面切換,并使用QGridLayout進行布局,使得兩個按鈕位于整個界面的左側。

StackDlg::StackDlg(QWidget *parent)
    : QDialog(parent)
{
    setWindowTitle(tr("StackedWidget"));
    setMinimumSize(800, 480);
    qDebug("Hello");

    QPushButton *pClockButton = new QPushButton("時\n鐘", this);
    QPushButton *pTimerButton = new QPushButton("秒\n表", this);
    pClockButton->setFixedSize(QSize(80,200));
    pClockButton->setFont(QFont("Times", 20));
    pTimerButton->setFixedSize(QSize(80,200));
    pTimerButton->setFont(QFont("Times", 20));

    pStack = new QStackedWidget(this);
    ClockWidget *pClockWidget = new ClockWidget();
    TimerWidget *pTimerWidget = new TimerWidget();
    pStack->addWidget(pClockWidget);
    pStack->addWidget(pTimerWidget);

    QGridLayout *mainLayout = new QGridLayout(this);
    mainLayout->addWidget(pClockButton, 0, 0, Qt::AlignCenter);
    mainLayout->addWidget(pTimerButton, 1, 0, Qt::AlignCenter);
    mainLayout->addWidget(pStack, 0, 1, 2, 1);

    mainLayout->setContentsMargins(10,10,1,1);
    mainLayout->setColumnStretch(1, 10);
    mainLayout->setRowStretch(1, 1);

    connect(pClockButton, SIGNAL(clicked()), this, SLOT(showClock()));
    connect(pTimerButton, SIGNAL(clicked()), this, SLOT(showTimer()));
}

void StackDlg::showClock()
{
    qDebug("%s", __func__);
    pStack->setCurrentIndex(0);
}
void StackDlg::showTimer()
{
    qDebug("%s", __func__);
    pStack->setCurrentIndex(1);
}      

另外需要注意的是,Qt的信号和槽機制,需要信号和槽函數的參數一緻或信号的參數多于槽的參數,而按鈕按下沒有參數,但切換堆棧頁面需要一個參數(索引号,訓示要展示第幾個頁面),是以不能直接使用pStack的setCurrentIndex作為槽函數,需要自己再封裝一層,分别寫兩個按鈕按下時的槽函數。

3 測試

将代碼在Windows上編譯運作ok後,再将源碼複制到Ububtu中進行交叉編譯,具體的編譯過程可參考之前的文章:​​嵌入式Qt-動手編寫并運作自己的第1個ARM-Qt程式​​

然後将編譯後的程式複制到Linux闆子中運作,運作效果如下:

​​https://www.bilibili.com/video/BV1RB4y147s7​​

嵌入式Qt-實作兩個視窗的切換

4 總結