Qt系統學習第二章 Qt窗口系統 (資源文件圖片添加, QDialog, QMessageBox, 布局, 控件, Qt樣式表)


資源文件:

QMainWindow : 

在菜單欄中,文件下面的下拉框中,不能直接輸入中文,可以先隨便寫個英文名,然后在對應所屬的狀態欄中找到,將text右側的“save”改為“保存”,即可

 

  這里的“保存”和“打開”可以通過拖動鼠標來改變順序

 

 

  將菜單欄中的按鈕放入工具欄:在ui界面中的Action Editor里面選擇要放入工具欄的action;然后鼠標點住別放,往工具欄中拖,若出現紅色豎杠,就表示此處可以拖入,此時松開鼠標即可完成拖入。

 

 

  運行起來的程序,工具欄是可以自由拖動停靠的,要想不可拖動停靠,可以在ui界面的右側的對象中找mainToolBar,在下面的屬性中找QToolBqr,將movable后面的框框里,把對號去掉,就無法移動了,將allowedAreas

 

 

 控件中的Dock Widget是浮動窗口;屬性中的floating是浮動與否,windowTitle是浮動窗口的小標題

 

 

QMenu (菜單欄)----- 只有一個

toolbar  (工具欄)----- 可以有很多個

dockwidget (浮動窗口)--可以有很多個

statusBar(下狀態欄)----- 只有一個

 程序中,初始化一個變量的方式有兩種: 在.h的private下面定義一個int number; 可以在.cpp中這樣初始化.

 

qt中,通過代碼添加資源文件(.qrc)如圖:

 

方式一:

 

這種比較麻煩;

 

方式二:

可以通過右鍵左側文件夾  ->  添加新文件->  文件和類"Qt"  ->  Qt Resource File  ->  choose  ->  指定名稱(英文)  ->  .qrc 添加到文件  ->  完成  ->  項目所屬的.pro中出現 Resource  += ***.qrc

此時左側文件樹中出現,雙擊resource.qsc是無法打開的, 此時想要編輯,應該鼠標右鍵單擊resource.qrc  ->  Open With  ->  資源編輯器;

 

打開后, 點擊 "添加" 按鈕  ->  添加前綴  ->  修改前綴(最簡單的前綴就是一個/)  ->  點擊 "添加" 按鈕  ->  添加文件  ->  將所用到的圖標資源文件放入一個Image文件夾中, 再復制粘貼到工程所在目錄中  ->  鼠標左鍵拉選所用圖片  ->  選好后,點擊右下方  "打開"  即可完成添加資源文件;

此時的左側文件樹可以看到資源文件, 同時, 可以在添加前綴那塊在添加個文件前綴, 放別的資源文件進來, 方便后期項目過大時區分資源文件;同時,將.cpp文件中的資源文件地址更換

ui->actionsave_as->setIcon(QIcon(":/caidanlan/Image/1.jpg"));

 

 此時的程序編譯時, 運行速度會變慢, 是因為編譯器在編譯的時候, 將我們所添加的資源文件, 轉換成了二進制文件, 存入了程序中, 以后打包軟件的時候,也將圖片一起打包了就.

 

方式三:

添加完資源文件前綴及文件后,在.ui界面的Action Editor中,選擇所要添加資源文件的action; 然后查看右側的屬性窗口里找icon點開下拉框后,找到Normal Off/On,然后點擊其中一個右側的 "..." ,彈出資源文件窗口;此時選擇一個圖標, 選擇, 點擊OK即可;此時出現圖標,若想改變圖標大小, 可在.ui界面的右側的對象窗口里 找到並選中mainToolBar, 然后在右下角的屬性窗口中,找到QToolBar  ->  iconSize, 在這里可以改變圖標的寬高;iconText是圖標文本內容; 當圖標插入后,Qt默認不顯示文字,可將鼠標懸浮於圖標之上,1s后,可顯示出提示文字;提示文字可在iconText同級下面一行的toolTip后面設置;

 

 

 

 

QDialog : 

模態對話框: 無法對對話框后的文件進行編輯或處理;且有系統提示音;

非模態對話框: 可以對對話框后的文件進行編輯或處理;

 

PS: 使用QT類主要記 這個類, 都有哪些信號, 和槽函數.  Qt中,用宏的時候,記不住宏的名字,也可以用宏編碼

dlg->setAttribute(Qt::WA_DeleteOnClose);        //關閉窗口后,自窗口自動被析構.此處的是QObject派生的子類,父類窗口不關閉(析構),子類也不會被析構

//dlg->setAttribute(55); //在文檔助手里,上述宏對應的編號就是55

 

 

QMessageBox:

提示對話框: 

 

 

本節代碼如下:

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QDebug>
#include <QPushButton>
#include <QLabel>
#include <QDialog>       //對話框類
#include <QMessageBox>      //提示對話框
#include <QColorDialog>     //顏色對話框
#include <QFontDialog>      //字體對話框

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    number(10)      //初始化  方式1
{
    ui->setupUi(this);
    //number = 10;  //初始化  方式2
    //ui->menuEdit->addAction();
    connect(ui->actionopen, &QAction::triggered, this, [=]()
    {
//        //創建一個對話框
//        QDialog dlg(this);          //如果沒有(this),意思是dlg是個獨立的頂層窗口,加了(this)意思是,指定了父類是MainWindow(看本代碼第九行)
//        //顯示模態對話框   .exec()
//        dlg.exec();     //阻塞  關閉模態對話框后,程序才可以繼續執行

//        QString name = QFileDialog::getOpenFileName(this, "打開文件", "D:\\", "Image (*.jpg *.png )");
//        qDebug() << name.toUtf8().data();       //qDebug不能直接打印Qstring類型的,需要先轉成QByteArray{toUtf8()},,再轉成char *QByteArray {data()}

        //QMessageBox::about(this,"about","*******");
        //QMessageBox::critical(this,"error","系統文件錯誤!!!",QMessageBox::Ok | QMessageBox::Cancel);        //  |  是為了區分,在Open的時候可能會加參數,比如只讀/只寫,  QMessageBox::Ok 和QMessageBox::Cancel 對應的都是數值, 轉換為二進制后, 只占其中一位.將這兩個按位異或的方式放入整數里,占很多的位,通過對應位來判斷所設屬性
        //if(QMessageBox::Ok == QMessageBox::critical(this,"error","系統文件錯誤!!!",QMessageBox::Ok | QMessageBox::Cancel))      //是個紅色大錯號
        //if(QMessageBox::Ok == QMessageBox::information(this,"error","系統文件錯誤!!!",QMessageBox::Ok | QMessageBox::Cancel))  //是個藍色感嘆號
        //if(QMessageBox::Ok == QMessageBox::warning(this,"error","系統文件錯誤!!!",QMessageBox::Ok | QMessageBox::Cancel))     //是個黃色感嘆號, 並設置Cancel為默認按鈕
//        if(QMessageBox::Ok == QMessageBox::question(this,"error","系統文件錯誤!!!",QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel))  //是個藍色問號
//        {
//            QDialog dlg(this);
//            dlg.exec();
//        }
//        QColor color = QColorDialog::getColor();
//        qDebug() << color.red() << color.green() << color.blue();       //顏色對話框
        bool ok;
        QFont font = QFontDialog::getFont(&ok, QFont("華文彩雲"), this, "我的字體設置");
        if(ok)
        {
            qDebug() << font.family() << font.italic() << font.pointSize() << font.bold();  //字體類型 << 傾斜與否  << 高度 << 加粗與否
        }


    });

    connect(ui->actionsave, &QAction::triggered, this, [=]()
    {
        //創建一個對話框
        QDialog *dlg = new QDialog(this);      //此時運行,非模態對話框一閃而過,此處new是為了不析構這個dlg,使對話框一直存在,也可以while(1){}
        //但是弊端是,這個程序運行起來后,有可能會反復點擊一萬次"save"按鈕, 來創建這個窗口, 這就意味着被new了一萬次, 但是一次都沒被析構. 解決辦法是 將QDialog *dlg定義為成員變量.這樣就可以在外部釋放,這樣比較麻煩.
        //也可以設置對話框屬性
        dlg->setAttribute(Qt::WA_DeleteOnClose);        //關閉窗口后,自窗口自動被析構.此處的是QObject派生的子類,父類窗口不關閉(析構),子類也不會被析構
        //dlg->setAttribute(55);        //在文檔助手里,上述宏對應的編號就是55

        //顯示非模態對話框   .show()
        dlg->show();     //非阻塞
    });

    ui->dockWidget->show();     //浮動窗口

    QPushButton* btn =  new QPushButton("hello",this);      //給下狀態欄的左側添加“hello”按鈕
    ui->statusBar->addWidget(btn);  //下狀態欄

    QLabel* label = new QLabel("world",this);               //給下狀態欄“hello”按鈕的左側添加一個label顯示內容為"world"
    ui->statusBar->addWidget(label);

    //ui->actionsave_as->setIcon(QIcon("D:\\1.jpg"));        //給菜單欄下拉框中的"save as"添加圖標,圖標路徑為:D:/1.jpg

    //添加完資源文件后, 可用下面這種添加方式
    ui->actionsave_as->setIcon(QIcon(":/caidanlan/Image/1.jpg"));
}

MainWindow::~MainWindow()
{
    delete ui;
}

 

 

 

布局:
一般ui界面中,常用的是前三種布局垂直布局, 水平布局, 網格布局.

 

 

水平布局:使所選空間處於水平位置;

    eg:在ui界面拖入兩個label和兩個Text Browser, 選中用戶名和右邊的Text Browser, 點擊ui界面上方的水平布局,此時變為;

     但是不推薦使用,因為很容易水平變為右圖這種; 順序搞反后,不容易點擊改變; 

 

 

    建議先放入一個widget窗口,再將用戶名和Text Browser放入widget窗口,,選中widget窗口后,點擊水平布局即可,,密碼和Text Browser2,同理, 兩個按鈕同理,最上面的label不用管,如圖,狀態樹的所屬為:

 

 

 

垂直布局: 選中后, 點垂直布局, 變為: ;

 

 

此時拉拽ui界面, 按鈕和框表會隨之改變,要想讓上方的label中的內容居中,可在對應label所屬的屬性框中找到,將水平的格式調為AlignVCenter,或者同理, 把label放入widget中, 再做一個水平布局;

 

 

加彈簧,彈簧也可以設置屬性,sizeType中,Expanding,是默認可伸展的彈簧, Fixed是固定彈簧長度,

按鈕固定大小:在按鈕的屬性框中,找到,將最大和最小的寬度設置為同一數值, 按鈕大小就不會發生改變,或者兩個按鈕中間加個彈簧; 

 

 

水平和垂直布局只能改變一行或一列, 效果圖如下

 

 

 網格布局:  打破用戶名和密碼的布局后,將這四個模塊放入同一個widget,然后選擇網格布局, 此時, , 將整個主窗口Widget垂直布局,將最大和最小的寬高都設置為192*173,此時:,用戶名左側邊框太寬,可以在主窗口Widget的屬性中,找到

 

將layoutLeftMargin 設置為0. Top是頂部間距, Right是右側邊距, Bottom是底部邊距, Spacing是控件直接的默認邊距

 

控件介紹:

Layouts(布局): 垂直 水平 網格 表格

 

Spaces(彈簧): 水平 垂直

 

Buttons(按鈕): 

    Push Button  普通按鈕  三種信號:點擊clicked ;按下pressed ; 釋放 released;  可以給按鈕設置圖標

    Radio Button 單選按鈕  成組使用, ui界面的多個按鈕只可點擊一個.要想分兩組使用, 將一組單選按鈕放入Group Box框中. 比如性別 只有男女, 單選題.

    Check Box  復選按鈕  可以有多個選擇, 沒有選擇限制. 比如愛好, 多選題. 信號是stateChanged, 使用lambda表達式時,()中要加參數 int  state

    connect(ui->checkBox, &QCheckBox::stateChanged, this, [=](int state)
    {
        QMessageBox::information(this, "checkbox", QString::number(state));
        //QString::number(state) 把int型的state轉為字符串
        qDebug() << state;    //選中復選框就打印2 未選就打印0
    });

Item Views 比較高級, 老師不給教

 

Item Widget:

    List Widget 數據一行一行的顯示

    ui->listWidget->addItem("hello,world!");
    //QListWidgetItem* Item = new QListWidgetItem(QIcon("C:\\Users\\muchai\\Desktop\\1.jpg"),"l",ui->listWidget);
    //ui->listWidget->addItem(Item);
    ui->listWidget->addItem(new QListWidgetItem(QIcon("C:\\Users\\muchai\\Desktop\\1.jpg"),"1"));

 

 

 Table Widget 數據如Excel表顯示, 有行列表格線.  使用時需要指定行數 列數;

    //1、指定行數
    ui->tableWidget->setRowCount(100);
    //2、指定列數
    ui->tableWidget->setColumnCount(3);

    //給每列起名字
    QStringList list;
    list << "姓名" << "性別" << "年齡" ;
    //給每行起名字
    QStringList list2;
    list2 << "人員1" << "人員2" << "人員3";
    ui->tableWidget->setHorizontalHeaderLabels(list);
    ui->tableWidget->setVerticalHeaderLabels(list2);

,框中可以進行編輯。

 

 

 

Group Box(組框):一般會將Radio Button放入組框中。

 

Scroll Area(滾動區域):很小的窗口,顯示很多的內容

 

 

 

Tool Box:抽屜一樣的盒子,像QQ的分組列表,點開后,里面的好友被彈出,Page里面可以放控件,比如在Page1中放入本例的Group Box1,在Page2中放入本例的Scroll Area

 

 

 

Tab Widget:選擇頁面,可以設置Tab按鈕的位置,按鈕文字。

 

 

 

Stacked Widget(棧窗口):可以設置多個頁面,通過連接按鈕來切換頁面;連接按鈕時,可在Stacked Widget的屬性欄中的QStackedWidget下的currentIndex的數值來查看窗口序號,同時這個序號也是連接外部按鈕的槽函數的參數(此法的槽函數帶int型的參數,與button的clicked的bool返回值不匹配,一般使用lambda表達式作為槽函數使用,在lambda的{}中寫槽函數返回)。除了用序號連接外部按鈕外,還可以根據Stacked Widget對應的窗口屬性欄中QObject下的objectName來連接。

 

    //connect(ui->btn_music, &QPushButton::clicked, ui->stackedWidget, &QStackedWidget::setCurrentIndex());      //信號與槽返回值類型不匹配,前者為bool 后者為int
    connect(ui->btn_music, &QPushButton::clicked, this, [=]()
    {
        ui->stackedWidget->setCurrentIndex(0);          //參數可在ui界面的Stacked Widget的屬性欄中的QStackedWidget下的currentIndex的數值來查看窗口序號
    });
    connect(ui->btn_tiktok, &QPushButton::clicked, this, [=]()
    {
        ui->stackedWidget->setCurrentWidget(ui->video);     //video是Stacked Widget對應的窗口屬性欄中QObject下的objectName
    });
    connect(ui->btn_cale, &QPushButton::clicked, this, [=]()
    {
        ui->stackedWidget->setCurrentIndex(2);
    });

 

 

 

Dock Widget(浮動窗口):可以停靠在主窗口邊框,還可以獨立出來的窗口

 

Combo Box(下拉框):可以通過additem添加字符串,直接加字符串就行,或者圖標加字符串

 

Font Combo Box(下拉框):字體下拉框

 

Label(文本圖形框):可以放入圖片(靜態、動態)或文字;在Qt中 Picture不是圖片,Pixmap才是圖片!!

    //ui->label->setPixmap(QPixmap(":/Image/1.jpg"));
   
//      QMovie movie(":/Image/yaw.gif");    //這樣不行,因為movie對象創建在構造函數里面,movie對象創建出來后,構造函數里面的對象就被析構了,movie在播放的時候就已經被析構掉了,播放不出來畫面.
//      ui->label->setMovie(&movie);
//      movie.start();     
        
        QMovie* movie = new QMovie(":/Image/yaw.gif");
        ui->label->setMovie(movie);
        movie->start();    

自定義控件: (封裝SpinBox和水平進度條)

  Spin Box的默認大小是0-99; 可通過 setRang(0,10000) 來設置Spin Box的大小; 

 

  本節就是將這兩個控件(Spin Box & 滑動條)封裝成一個控件(widget窗口), 方便后期重復使用;

步驟:

  1. 先給項目中新建一個類

  選中項目的名字, 鼠標右鍵 -> 添加新文件; 此時可以添加一個C++-> C++ Class, 但是C++ Class不帶ui界面, 需要用代碼來創建控件和編輯其屬性;故此處用Qt -> Qt設計師界面類 -> Widget(空白界面,所有類的父類) -> 在<類名:>后面的LineEdit中, 給封裝的類起個響亮的名字(SmallWidget), 頭文件、源文件、界面文件自動修改 -> 完成;

  2. 在smallwiddget.ui 中, 將Spin Box 和 水平滑動條放入, 將整個ui界面水平布局, 再將ui界面的窗口拖動到最小; 

  3. 此時在widget.ui中, 想用封裝的自定義控件, 先在widget.ui中放入一個Widget控件(窗口), 鼠標右鍵單擊剛放入的Widget窗口, 鼠標左鍵選擇 "提升為..."; 在彈出的提升的窗口部件中,基類名稱不用管, 在提升的類的名稱中寫入剛才創建的類的類名(SmallWidget), 寫的時候注意大小寫 !  頭文件不用管, 選中全局包含(在項目中的任何一個窗口都可以使用此控件) , 點擊 "添加"按鈕. 添加完成后, 提升的類會上升到上面的窗口, 此時點擊對話框底部的"提升"按鈕, 回到widget.ui界面, 此時可以看到ui界面的右側屬性欄中, widget的類名稱已改變成SmallWidget, 而不再是QWidget. 此時再拉入一個widget_2,右鍵單擊 -> 左鍵 "提升為" -> SmallWidget (全局包含的意義:可不限制窗口的將一個QWidget類提升為SmallWidget類)

  此時的smallwidget.ui:

  此時的widget.ui:

 

   運行界面:

   4. 因為把SmallWidget封裝成了一個類, 在SmallWidget類中維護這兩個控件要在smallwidget.cpp中的構造函數中編寫代碼, 進行Spin Box於滑動模塊的對應的信號槽連接,使Spin Box增大,滑塊隨之移動, 滑塊移動, Spin Box隨之改變; 

void (QSpinBox::*sigValeChange)(int) = &QSpinBox::valueChanged;       //Qt5中不能直接將信號直接寫入connect(因為valuechanged是個重載信號),需要定義一個指針;
connect(ui->spinBox, sigValeChange, ui->horizontalSlider, &QSlider::setValue);      //&QSlider里面沒有對應的槽函數, 它的父類QAbstractSlider里面有setValue
connect(ui->horizontalSlider, &QSlider::valueChanged, ui->spinBox, &QSpinBox::setValue);  

   5. 提供接口函數, 在smallwidget.h的public中,定義接口函數

    int getValue();  //獲取值
    void SetValue(int value);  //設置值 

   6. 在smallwidget.cpp中實現

void SmallWidget::SetValue(int value)
{
    if(value > 0 && value < 100) { ui->spinBox->setValue(value); } } int SmallWidget::getValue() { return ui->spinBox->value(); }

 

Qt樣式表

  在思想上很大程度來自於HTML的層疊式樣式表(CSS), 通過調用 QWidget::setStyleSheet()或QApplication::setStyleSheet(),可為一個獨立的子部件, 窗口, 甚至整個應用程序指定一個樣式表; Qt樣式表與CSS的語法幾乎完全相同.

1. 語法基礎: selector { attribute: value }      

  eg:(.cpp構造函數中)  ui -> label -> setStyleSheet ("QLabel { color: red} ");    //為一個獨立的子部件指定一個樣式表

  (.cpp構造函數中)       this -> setStyleSheet ("QLabel { color: red} ");         //為一整個窗口指定一個樣式表(本例中,所有的label都是紅色)

  (main.cpp中)      a.setStyleSheet ("QLabel { color: red} ");           //為整個應用程序指定一個樣式表

  當為整個應用程序指定一個樣式表后,可對其中的一個或多個窗口或子部件進行屬性修改; 為窗口指定樣式表后, 也可修改其中的子部件屬性;

  

  選擇器通常為一個類名 (eg: QComboBox), 屬性(attribute)是一個樣式表屬性的名字, 值(value)是賦給該屬性的值;

  為方便使用, 可使用以下簡化形式的樣式表:

  selector1, selector2, ... ... , selectorM 

  {

    attribute1: value1;

    attribute2: value2;

    ...

    attributeN: valueN;

  }

  這種簡化形式可以同時為與M個選擇器相匹配的部件設置N種屬性

  QCheckBox, QComboBox, QSpinBox

  {

    color: red;

    background-color: white;

    font: bold;

  }

  這個規則設置了所有的QCheckBox, QComboBox和QSpinBox的前景色、背景色和字體

2. 方箱模型: 樣式表中, 每個部件都可看成是一個由四個同心的矩形組成的箱體(方框套方框);

  空白(margin): 空白區域位於邊框外, 且總是透明

  邊框(border): 為部件提供了四周的框架, 其border-style屬性可以設置為一些內置的框架風格,如inset, outset, solid, ridge;

  填充(padding):填充在邊框和內容區域之間, 提供了空白間隔.

  內容(content): 對於一個平面部件, 例如一個空白、邊框和填充都是0像素的部件而言,這四個矩形完全重合;

3. 前景和背景

  前景用於繪制上面的文本, 可以通過color: 屬性指定, 背景色用於繪制部件的填充矩形, 可以通過 background-color: 屬性指定; 

  背景圖片使用background-image 屬性定義,用於繪制由background-origin指定的矩形區域(空白, 邊框, 填充, 內容), 對齊和平鋪方式可以通過background-position和background-repeat屬性指定;

4. 可伸縮樣式:  

  默認情況下, 通過background-image指定的背景圖片會自動重復平鋪,以覆蓋部件的整個填充矩形,若我們想創建能夠隨着部件大小自動縮放,而不是平鋪的背景,我們需要設置"邊框圖片".  通過border-image:  指定屬性;

  QPushButton{

    border-width: 4px; 

    border-image: url(button.png);  /*4 4 4 4 stretch stretch*/     }  //注釋里的是往里裁剪圖片的屬性, 設的越大,裁的越多;

5. 控制大小:min-width, min-height (不常用,因為可以直接在ui界面屬性欄中控制) 

6. 偽狀態;

    ui -> pushButton -> setStyleSheet("QPushButton

    {"

      "border: 2px outset green;"    //按鈕邊框為綠

    "}");

偽狀態列表:

:checked    button部件被選中

:disabled    部件被禁用

:enable       部件被啟用

:fouces     部件獲得焦點

:hover         鼠標位於部件上

:indeterminate  checkbox或radiobutton被部分選中

:off       部件可以切換, 且處於off狀態

:on       部件可以切換, 且處於on狀態

:pressed       部件被鼠標按下

:unchecked   button部件未被選中

    ui -> pushButton -> setStyleSheet("QPushButton

    {"

      "border-image:url(:/1.jpg);"    //按鈕設置圖標

    "}");

   

    ui -> pushButton -> setStyleSheet("QPushButton:hover

    {"

      "border-image:url(:/1.jpg);"    //鼠標位於按鈕上,按鈕圖標亮出

    "}");

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM