第四章 常用介面元件的使用
在Qt類庫中,所有介面元件類的位元組或間接父類都是QWidget.
QWidget的父類是QObject與QPaintDevice.所以QWidget是多重繼承的類.
QObject支援元物件系統,其訊號與槽機制為程式設計中物件間通訊提供了極大便利.
QPaintDevice是能使用QPainter類在繪圖裝置上繪圖的類.
所有從QWidget繼承而來的介面元件被稱為widget元件,他們是構成GUI應用程式的視窗介面基本元素.
介面元件可以從視窗系統接收滑鼠事件,鍵盤事件和其他事件,然後在螢幕上繪製自己.
常用的介面元件
按鈕類元件
按鈕類繼承關係:
- QAbstractButton:抽象類,提供按鈕共有特性
- QPushButton:普通按鈕
- QCommandLinkButton:單選按鈕,多個互斥項間選擇.
- QToolButton:工具按鈕
- QRadioButton:單選按鈕
- QCheckBox:核取方塊
- QPushButton:普通按鈕
- QDialogButttonBox:複合元件類,可設定為多個按鈕組合
輸入類元件
輸入類元件繼承關係:
- QComboBox:下拉選單框,也稱組合框
- QFontComboBox:字型下拉選單框,自動從系統獲取字型
- QLineEdit:編輯框,用於輸入單行文字
- QFrame:基本控制元件的基類
- QAbstractScrollArea:抽象類
- QTextEdit:文字編輯框,支援富文字格式,包括markdown.
- QPlainTextEdit:純文字編輯器,支援多段落純文字.
- QAbstractScrollArea:抽象類
- QAbstractSpinBox:抽象類
- QSpinBox:整數輸入框,用於輸入整數或離散型資料.
- QDoubleSpinBox:浮點數輸入框.
- QDateTimeEdit:允許使用者編輯日期與時間
- QDateEdit:日期編輯框
- QTimeEdit:時間編輯框
- QAbstractSlider:抽象類
- QDial:錶盤,用於在設定的範圍內輸入和顯示數值.
- QScrollBar:卷滾條,用於在大的顯示區域內滑動.
- QSlider:滑動條,具有設定的數值範圍.
- QKeySequenceEdit:按鍵序列編輯器,一般用於處理快捷鍵
顯示類元件
顯示類元件繼承關係:
- QFrame:基本控制元件的基類
- QLabel:標籤,用於顯示文字,圖片等
- QAbstractScrollArea:抽象類
- QTextEdit:文字編輯框,支援富文字格式,包括markdown.
- QTextBrowser:文字瀏覽器,用於顯示富文字格式內容
- QGraphicsView:圖形檢視元件,圖形/檢視架構中的檢視元件
- QTextEdit:文字編輯框,支援富文字格式,包括markdown.
- QLCDNumber:LCD數字顯示元件,模仿LCD顯示效果的元件
- QCalendarWidget:日曆元件,用於顯示日曆
- QProgressBar:進度條,用於表示某個操作的進度
- QOpenGLWidget:OpenGL顯示元件,用於在Qt程式啟動OpenGL圖形
- QQuickWidget:QML顯示元件,用於自動載入QML檔案
容器類元件
容器類元件繼承關係:
- QGroupBox:分組框,具有標題和邊框的容器元件
- QFrame:框架元件,是具有邊框的介面元件的父類
- QAbstractScrollArea:抽象類
- QScrollArea:卷滾區域,具有水平和垂直捲軸的容器
- QMdiArea:MDI工作區元件,在MDI應用程式中用於管理多文件視窗
- QToolBox:工具箱,垂直方向的多頁容器元件
- QStackedWidget:堆疊多頁元件,沒有標籤欄的多頁元件
- QAbstractScrollArea:抽象類
- QTabWidget:帶標籤欄的多頁元件
- QDockWidget:停靠元件,可以停靠在QMainWindow視窗的停靠區域,也可以浮動
- QAxWidget:ActiveX顯示元件,用於顯示ActiveX控制元件
Item元件
Item元件繼承關係:
- QAbstractItemView
- QListView
- QUndoView
- QListWidget
- QTreeView
- QTreeWidget
- QTableView
- QTableWidget
- QColumnView
- QListView
Item Views元件大多是用於模型/檢視結果,每一種檢視元件需要相應的一種模型用於儲存資料.
Item Widgets元件類是相應Item Views元件類的子類,它們直接使用項(item)儲存資料,稱為相應檢視類的便利類(convenience class)
其他介面類
還有一些介面元件並沒有出現在元件皮膚裡,例如常用的選單欄(QMenuBar類),選單(QMenu類),工具欄(QToolBar類),狀態列(QStatusBar類)等元件.
QWidget類的主要屬性和介面函式
QWidget作為介面元件時的屬性
屬性名稱 | 屬性值型別 | 功能 |
---|---|---|
enabled | bool | 元件的使能狀態 |
geometry | QRect | 元件的幾何形狀 |
sizePolicy | QSizePolicy | 元件預設的佈局特性 |
minimumSize | QSize | 元件最小尺寸 |
maximumSize | QSize | 元件最大尺寸 |
palette | QPalette | 元件的調色盤 |
font | QFont | 元件使用的字型 |
cursor | QCursor | 滑鼠游標移到元件上的形狀 |
mouseTracking | bool | 元件是否響應滑鼠移動 |
tabletTracking | bool | 元件是否響應平板追蹤 |
focusPolicy | Qt::FocusPolicy | 元件的焦點策略 |
contextMenuPolicy | Qt::ContextMenuPolicy | 組建的上下文選單策略 |
acceptDrops | bool | 元件是否接收拖動來的其他物件 |
toolTip | QString | 滑鼠移動到元件上時,顯示簡短提示 |
statusTip | QString | 滑鼠移動到元件上時,主視窗狀態列顯示提示文字 |
autoFillBackground | bool | 元件背景是否自動填充 |
styleSheet | QString | 組建的樣式表 |
元件負責預設佈局特性的sizePolicy是QSizePolicy型別,定義了元件在水平和垂直方向的尺寸變化策略.
為了訪問元件的sizePolicy,應當透過其Widget內部的sizePolicy()方法訪問.
QSizePolicy是一個列舉型別,因而有以下列舉常量:
- QSizePolicy::Fixed:固定尺寸,元件大小不改變
- QSizePolicy::Minimum:最小尺寸,使用sizeHint()的返回值或minimumuSize作為最小尺寸.
- QSizePolicy::Maximum:最大尺寸,使用sizeHint()的返回值或maximumuSize作為最大尺寸.
- QSizePolicy::Preferred:首選尺寸,元件仍然可以調整,但是放大時不會超過sizeHint()返回的尺寸.
- QSizePolicy::Expanding:可擴充套件尺寸,元件可擴充套件.
- QSizePolicy::MinimumExpanding:最小可擴充套件尺寸,綜合了可擴充套件尺寸與最小尺寸.
- QSizePolicy::Ignored:忽略尺寸,sizeHint()函式的返回值被忽略,元件佔據儘可能大的空間.
在使用QSizePolicy的時候,QWidget的sizeHint()函式會起到很大作用.
在元件的父元件尺寸發生變化時,sizeHint()返回元件的建議尺寸.
一般不需要修改元件的sizePolicy屬性,使用其預設值即可.
部分部件的尺寸策略還進一步細分為水平策略與垂直策略
水平延伸因子與垂直延伸因子都是整數值,其取值範圍在0~255.
QWidget作為視窗時的屬性
屬性 | 屬性值型別 | 功能 |
---|---|---|
windowTitle | QString | 視窗標題欄的文字 |
windowIcon | QIcon | 視窗標題上的圖表 |
windowOpacity | qreal | 視窗的不透明度(範圍0.0~1.0) |
windowFilePath | QString | 視窗相關的含路徑檔名 |
windowModified | bool | 顯示視窗內文件是否被修改(*) |
windowModality | Qt::WindowModality | 視窗的模態,表示視窗是否在上層 |
windowFlags | Qt::WindowFlags | 視窗的標誌,是其一些值的組合 |
QWidget作為獨立的視窗時,實際上還有一些與視窗顯示有關的共用槽函式.
名稱 | 功能 |
---|---|
close() | 關閉視窗 |
hide() | 隱藏視窗 |
show() | 顯示視窗 |
showFullScreen() | 以全屏方式顯示視窗 |
showMaximized() | 視窗最大化 |
showMinimized() | 視窗最小化 |
showNormal() | 恢復正常視窗 |
佈局管理
在Qt Designer的元件皮膚裡有用於佈局管理的兩組元件,Layouts與Spacers.
QLayout繼承自QObject與QLayoutItem.是Layouts中所有元件的基類.QLayout不是從QWidget繼承來的.
從QLayout繼承而來的幾個類是常用的佈局管理類:
- QVBoxLayout:垂直佈局
- QHBoxLayout:水平佈局
- QGridLayout:網格佈局,使元件按行與列網格狀佈局
- QFormLayout:表單佈局,與Grid相似,但只有兩列
- QStackedLayout:堆疊佈局,用於管理多個頁面
任何佈局類物件在視覺化設計時都有layoutLeftMargin,layoutTopMargin,layoutRightMargin和layoutBottomMargin這個4個邊距屬性用於設定佈局元件與父容器的4個邊距的最小值.
下面是一個調整邊距屬性值及layoutSpacing的例子:
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
this->windowTitle().clear();
this->setWindowTitle(QString("this is my window"));
QVBoxLayout* total_layout;
total_layout= new QVBoxLayout;
QGroupBox *btn_group;
btn_group= new QGroupBox(this);
btn_group->setGeometry(QRect(260,310,341,43));
QPushButton* btn_1,*btn_2,*btn_3;
btn_1= new QPushButton("button_1",btn_group);
btn_2= new QPushButton("button_2",btn_group);
btn_3= new QPushButton("button_3",btn_group);
QHBoxLayout* btn_layout;
btn_layout= new QHBoxLayout;
btn_layout->setSpacing(10);
btn_layout->setContentsMargins(15,25,5,5);
btn_layout->addWidget(btn_1);
btn_layout->addWidget(btn_2);
btn_layout->addWidget(btn_3);
total_layout->addLayout(btn_layout);
this->setLayout(total_layout);
}
在上面的例子中,所有的QPushButton都以QGroupBox為父物件.
使用QGroupBox::setGeometry()設定了元件的幾何形狀.
使用QHBoxLayout::setSpacing()設定了元件間的最小間距.
使用QHBoxLayout::setContentMargins()設定了四個邊距的值.
網格佈局
視覺化設計網格佈局時一般是在一個容器元件內先擺放元件,使各元件的位置和大小與期望的效果大致相同,然後點選工具欄上的網格佈局按鈕進行網格佈局.
除了4個邊距屬性,網格佈局還有幾個特有的屬性:
- layoutHorizontalSpacing:水平方向上元件最小間距
- layoutVerticalSpacing:垂直方向上元件最小間距
- layoutRowStretch:各行的延展因子
- layoutColumnStretch:各列的延展因子
- layoutRowMinimumHeight:各行的最小高度,單位為畫素
- layoutColumnMinimumWidth:各列的最小寬度,單位為畫素
- layoutSizeConstraint:佈局的尺寸限制方式
下面是應用網格佈局應用的一個例子:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QGroupBox *groupBox=new QGroupBox(this);
groupBox->setGeometry(QRect(290,160,200,230));
QGridLayout *gridLayout=new QGridLayout(groupBox);
gridLayout->setHorizontalSpacing(7);
gridLayout->setVerticalSpacing(12);
gridLayout->setContentsMargins(10,10,-1,-1);
QPushButton *pushButton=new QPushButton(groupBox);
gridLayout->addWidget(pushButton,0,0,1,1);
QPushButton *pushButton_2=new QPushButton(groupBox);
gridLayout->addWidget(pushButton_2,0,1,1,1);
QComboBox *comboBox=new QComboBox(groupBox);
comboBox->addItem(QString());
gridLayout->addWidget(comboBox,1,0,1,2);
QPlainTextEdit *plainTextEdit=new QPlainTextEdit(groupBox);
gridLayout->addWidget(plainTextEdit,2,0,1,2);
this->setLayout(gridLayout);
}
其中,下面的語句表示將表格新增至0行0列,佔據1行1列的位置.
gridLayout->addWidget(pushButton,0,0,1,1);
其他語句以此類推.
分割條佈局
實現分割條功能的類是QSplitter,分隔條可以實現水平分割或垂直分割.一般是在兩個可以自由改變大小的元件間分割.
分割條主要有以下幾個屬性:
- orientation:方向,即水平分割或垂直分割
- opaqueResize:如果值為true,則拖動分割條時,元件是動態改變大小的.
- handleWidth:進行分割操作的拖動條的寬度,單位為畫素.
- childrenCollapsible:表示進行分割操作時,子元件大小是否可以為0.
下面是一個使用分割條的例子:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSplitter *splitter=new QSplitter(this);
splitter->setOrientation(Qt::Horizontal);
splitter->setOpaqueResize(true);
splitter->setHandleWidth(8);
splitter->setMinimumSize(QSize(350,200));
splitter->setChildrenCollapsible(true);
QGroupBox *groupBox=new QGroupBox(splitter);
groupBox->setMinimumSize(QSize(10,0));
splitter->addWidget(groupBox);
QPlainTextEdit *plainTextEdit;
plainTextEdit=new QPlainTextEdit;
splitter->addWidget(plainTextEdit);
}
QChar字元
QChar是一個類,用於處理Qt中的字元.可以將其理解為一個加強版的char.
QChar有很多介面函式,常用的有:
- isDigital():是否為數字
- isLetter():是否為字母
- isLetterOrNumber():是否為字母或數字
- isLower():是否為小寫數字
- isUpper():是否為大寫數字
- isMark():是否為記號
- isNonCharacter():是否為非文字字元
- isNull():是否為'\0'
- isNumber():判斷字元是否為一個數,包括①之類的序號
- isPrint():判斷字元是否為可列印字元
- isPunct():判斷字元是否為標點符號
- isSpace():判斷字元是否為分割符號,如空格,製表符
- isSymbol():判斷字元是否為符號
- toLower():返回小寫形式
- toUpper():返回大寫形式
- (char16_t)unicode():返回16位編碼數值
其中值得注意的是一個靜態函式QChar::fromLatin1(),其用於將Latin1字元轉換為QChar字元.
與之對應的,QChar有一個toLatin1()函式用於將QChar字元轉換為Latin1字元.
提供一個使用例子:
QString str="String";
QChar ch=QChar::fromLatin1('Q');
str[0]=ch;
與之相似的,在QChar與UTF-16值轉換方面有unicode()方法與QChar::fromUsc2(char16_t c)函式.
QString字串
QString是Qt中的一個類,用於儲存字串.一般來說,Qt使用到字串的地方都使用QString.
而一般的std::string與QString互轉需要透過QString::fromStdString(str)與qstr.toStdString().
QString是由QChar組成的一個串,QChar使用的是UTF-16編碼.
QString使用隱式共享來減少記憶體佔用.這意味著只有在修改一個字串的時候,這個字串才會複製.
QString的建立與初始化
QString可以直接透過const char*初始化.
QString str="Hello World";
QString在被建立與初始化後,其儲存的就是一個QChar的字元陣列.可以對其進行索引.
QString str="Hello";
QChar ch0=str[0];
QString字串常用操作
可以使用加法運算子進行字串拼接.
QString str1="Hello ";
QString str2="World";
Qstring str3=str1+str2;
也可以透過append()在字串後新增字串,透過prepend()在字串前新增字串.
QString str1="igg";
str1.preend(QString("n"));
str1.append(QString("a"));
front()返回第一個字元,back()返回最後一個字元.
left(n)返回前n個字元,right(n)返回後n個字元.注意:轉義符視為一個字元處理.
mid(pos,n)返回字串中的字元數,pos為起始位置,n為返回字元的個數.
sliced()與mid()功能相同,但是其不判斷是否在邊界內.
函式section()用於從字串中提取sep作為分隔符,從start段到end段的字串.
例如:
QString str1="學生姓名,男,2004-09-15,漢族,湖南",str2;
str2=str1.section(",",0,0);//學生姓名
str2=str1.section(",",1,1);//男
str2=str1.section(",",1,2);//男,2004-09-15
str2=str1.section(",",4,4);//湖南
isNull()和isEmpty()作用相似,但是isNull()會對'\0'進行判定,而isEmpty()判定'\0'為true.
QString str1="",str2;
str1.isNull();//false
str1.isEmpty();//true
str2.isNull();//true
str2.isEmpty();//true
count(),若帶有引數,可以統計某個字元在字串中出現的次數.若不帶引數,count(),size()與length()都返回字串長度.
clear()函式清空當前字串,使字串為NULL.
resize()用於改變字串長度,但如果長度短於當前字串則會截斷;長度長於當前字串則會導致未初始化的記憶體.
如果resize內含有引數,那麼則使用該QChar填充字串填充部分.
與resize()不同,函式fill()則將字串中每個字元都用一個新字元替換.其同樣可以透過引數調整字串長度.
indexOf()與lastIndexOf()的功能是在字串內查詢某個字串首次與最後一次出現的位置.
contains()判斷當前字串是否包含某個字串.可透過Qt::CaseInsensitive表示是否分辨大小寫.
endsWith()和startWith()判斷字串是否以某個字串開頭或結尾.
count()用於統計當前字串中某個字串出現的次數.可以設定Qt::CaseInsensitive是否分辨大小寫.
函式toUpper()和toLower()用於將字串內的字母全部轉換為大寫字母或小寫字母.
trimmed()和simplified(),trimmed()會去掉字串首尾的空格,函式simplified()不僅去掉首尾空格,還會將中間的連續空格用單個空格替換.
chop(n)去掉字串末尾的n個字元,如果n大於實際意義,字串內容就變為空.
insert(pos,str),函式insert用於在某個位置插入一個字串.如果pos大於實際意義,字串會自動補充空格填充.
replace(pos,n,after)用於從某個位置開始替換n個字元.
其還有一種形式replace(before,after)用於替換所有before字串為after.可以指定Qt::CaseInsensitive分辨大小寫.
remove(pos,n)的功能為從字串pos開始的位置移出n個字元.若超出實際意義,則把pos後面的字元都移除.
同樣的,其還有另一種引數模式,remove(ch),即移除字串中某個字元出現的所有例項.
QString字串與數值轉換
QString有一些介面函式用於將字串轉換為整數:
引數ok用於獲取返回值,表示轉換是否成功.
- toInt(bool* ok,int base=10)
- toUInt(bool* ok,int base=10)
- toLong(bool* ok,int base=10)
- toUInt(bool* ok,int base=10)
- toShort(bool* ok,int base=10)
- toUShort(bool* ok,int base=10)
- toLongLong(bool* ok,int base=10)
- toULongLong(bool* ok,int base=10)
其也還有兩個介面函式用於將字串轉換為浮點數:
- toFloat(bool* ok)
- toDouble(bool* ok)
函式setNum()則用於將整數或浮點數轉換為字串.
- setNum(int n,int base=10)
- setNum(float n,char format='g',int precision=6)
格式字元 | 格式字元含義 | 精度位數含義 |
---|---|---|
e,E | 科學計數法 | 基數小數點後位數 |
f | 自然計數法 | 小數點後的有效位數 |
g,G | 根據情況自動調節 | 小數點前後的數字位數之和 |
QString還有一個靜態函式number(),其與setNum類似,但是是靜態函式形式
- QString::number(long n,int base)
- QString::number(double n,char format,precision)
靜態函式asprintf()用於構造格式化輸出字串.
- QString QString::asprintf(const char cformat*,...)
但是注意,asprintf輸出%s會導致亂碼,只能使用UTF-8編碼的const char*字串來作為引數.
也就是說,QString型的字串應當透過QString::data()來表現.
例如:
QString str1=QString::asprintf("Year=%d,Month=%02d",2024,04);
QString str2="哈爾濱工程大學 拓荒者學社"
QString str3=QString::asprintf("歡迎來到%s",str2.toLocal8Bit().data());
QString str4=QString::asprintf("PI=%.10f",M_PI);//3.1415926536
arg()函式是QString的成員函式,用於格式化輸出各種資料的字串,其功能與asprintf類似.
但是arg函式透過形式為%n的佔位符來對應實參,這與一般printf不同.
int year=2024,month=2,day=23;
QString str=QString("%1年,%2月,%3日").arg(year).arg(month).arg(day);
QSpinBox和QDoubleSpinBox
屬性名稱 | 功能 |
---|---|
prefix | 數字顯示的字首 |
suffix | 數字現實的字尾 |
buttonSysbols | 右側調節按鈕的符號 |
text | 只讀屬性,SpinBox內的所有文字 |
cleanText | 只讀屬性,不帶前字尾的所有文字 |
minimum | 數值範圍的最小值 |
maximum | 數值範圍的最大值 |
singleStep | 單步步長改變值 |
stepType | 步長型別,單一步長或自適應步長 |
value | 當前顯示的值 |
displayIntegerBase | QSpinBox使用的進位制 |
decimals | QDoubleSpinBox顯示的小數位數 |
對於預設值value的相關操作,存在兩個相關的函式:
- int QSpinBox::value()
- void QSpinBox::setValue(int val)
對於相關的讀寫範圍,還有一個函式setRange(),用於同時設定最小值與最大值.
- void QSpinBox::setRange(int minimum,int maximum)
QSpinBox還有兩個特有的訊號,訊號定義如下:
- void QSpinBox::valueChanged(int i)
- void QSpinBox::textChanged(const QString &text)
訊號valueChanged()在value變化時被髮射,傳遞的引數為變化之後的數值.
訊號textChanged()在顯示的文字發生變化的時候被髮射.
下面是使用QSpinBox的一個例項:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
//ui->setupUi(this);
lbTest1= new QLabel(QString("電源電動勢"));
lbTest2= new QLabel(QString("反應物濃度"));
lbTest3= new QLabel(QString("十六進位制值測試"));
sbTest1= new QSpinBox;
sbTest2= new QSpinBox;
sbTest3= new QSpinBox;
sbTest1->setSuffix(QString("mV"));
sbTest1->setValue(10);
sbTest2->setSuffix(QString("mod/L"));
sbTest2->setValue(1);
sbTest3->setSuffix(QString("值"));
sbTest3->setValue(28);
sbTest3->setDisplayIntegerBase(16);
txlTest= new QLineEdit;
txlTest->setText(QString("這裡會顯示內容"));
connect(sbTest1,SIGNAL(valueChanged(int)),this,SLOT(SpinBoxToLineEdit(int)));
QGridLayout* gridTest= new QGridLayout;
gridTest->addWidget(lbTest1,0,0,1,1);
gridTest->addWidget(lbTest2,1,0,1,1);
gridTest->addWidget(lbTest3,3,0,1,1);
gridTest->addWidget(sbTest1,0,1,1,1);
gridTest->addWidget(sbTest2,1,1,1,1);
gridTest->addWidget(sbTest3,3,1,1,1);
gridTest->addWidget(txlTest,2,0,1,2);
this->setLayout(gridTest);
}
void Widget::SpinBoxToLineEdit(int i)
{
this->txlTest->clear();
this->txlTest->insert(QString("電源電動勢改變後:%1").arg(i));
return;
}
常用的按鈕控制元件
按鈕是介面上常用的元件,常用的4種按鈕控制元件是:普通按鈕(QPushButton),工具按鈕(QToolButton),單選按鈕(QRadioButton),核取方塊(QCheckBox)
這四種按鈕都是繼承於QAbstractButton類的.
屬性 | 屬性值型別 | 功能 |
---|---|---|
text | QString | 按鈕的顯示文字 |
icon | QIcon | 按鈕的圖示 |
shortcut | QKeySequence | 按鈕的快捷鍵 |
checkable | bool | 按鈕是否可複選 |
checked | bool | 按鈕是否複選狀態 |
autoExclusive | bool | 在一個佈局或容器元件內的同類按鈕是否互斥 |
autoRepeat | bool | 是否自動重複發射訊號 |
- QPushButton的checkable預設為false
- QRadioButton和QCheckBox的checkable屬性預設為true
- QCheckBox的autoExclusive屬性預設為false
- QRadioButton的autoExclusive屬性預設為true
屬性 | 屬性值型別 | 功能 |
---|---|---|
autoDefault | bool | 按鈕是否為自動預設按鈕 |
default | bool | 按鈕是否為預設按鈕 |
flat | bool | 按鈕是否沒有邊框 |
QCheckBox新增了一個tristate屬性,QRadioButton沒有新的屬性.
QAbstractButton定義的新訊號:
- void clicked(bool checked)//點選按鈕時
- void pressed()//按下空格或左鍵
- void released()//釋放空格或左鍵
- void toggled(bool checked)//按鈕的checked屬性變化
QPushButton和QRadioButton沒有定義新訊號.
QCheckBox定義了一個新訊號:
- void QCheckBox::stateChanged(int state)
下面提供了一個使用button的例子:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
void on_btnLeft();
void on_btnMiddle();
void on_btnRight();
void on_btnBF();
void on_btnIT();
void on_btnUL();
void on_chkRead(bool checked);
void on_chkEnabled(bool checked);
void on_chkClean(bool checked);
void on_radBlack();
void on_radBlue();
void on_radRed();
signals:
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->btnLeft,SIGNAL(clicked(bool)),this,SLOT(on_btnLeft()));
connect(ui->btnRight,SIGNAL(clicked(bool)),this,SLOT(on_btnRight()));
connect(ui->btnMiddle,SIGNAL(clicked(bool)),this,SLOT(on_btnMiddle()));
connect(ui->btnBF,SIGNAL(clicked(bool)),this,SLOT(on_btnBF()));
connect(ui->btnIT,SIGNAL(clicked(bool)),this,SLOT(on_btnIT()));
connect(ui->btnUL,SIGNAL(clicked(bool)),this,SLOT(on_btnUL()));
connect(ui->radBlack,SIGNAL(clicked(bool)),this,SLOT(on_radBlack()));
connect(ui->radBlue,SIGNAL(clicked(bool)),this,SLOT(on_radBlue()));
connect(ui->radRed,SIGNAL(clicked(bool)),this,SLOT(on_radRed()));
connect(ui->chkClean,SIGNAL(clicked(bool)),this,SLOT(on_chkClean(bool)));
connect(ui->chkEnabled,SIGNAL(clicked(bool)),this,SLOT(on_chkEnabled(bool)));
connect(ui->chkRead,SIGNAL(clicked(bool)),this,SLOT(on_chkRead(bool)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnLeft()
{
ui->pltEdit->setAlignment(Qt::AlignLeft);
}
void MainWindow::on_btnMiddle()
{
ui->pltEdit->setAlignment(Qt::AlignCenter);
}
void MainWindow::on_btnRight()
{
ui->pltEdit->setAlignment(Qt::AlignRight);
}
void MainWindow::on_btnBF()
{
static bool flag=true;
QFont font= ui->pltEdit->font();
font.setBold(flag);
ui->pltEdit->setFont(font);
flag=!flag;
}
void MainWindow::on_btnIT()
{
static bool flag=true;
QFont font= ui->pltEdit->font();
font.setItalic(flag);
ui->pltEdit->setFont(font);
flag=!flag;
}
void MainWindow::on_btnUL()
{
static bool flag=true;
QFont font= ui->pltEdit->font();
font.setUnderline(flag);
ui->pltEdit->setFont(font);
flag=!flag;
}
void MainWindow::on_chkRead(bool checked)
{
ui->pltEdit->setReadOnly(checked);
}
void MainWindow::on_chkEnabled(bool checked)
{
ui->pltEdit->setEnabled(checked);
}
void MainWindow::on_chkClean(bool checked)
{
ui->pltEdit->setClearButtonEnabled(checked);
}
void MainWindow::on_radBlack()
{
QPalette plet= ui->pltEdit->palette();
plet.setColor(QPalette::Text,Qt::black);
ui->pltEdit->setPalette(plet);
}
void MainWindow::on_radBlue()
{
QPalette plet= ui->pltEdit->palette();
plet.setColor(QPalette::Text,Qt::blue);
ui->pltEdit->setPalette(plet);
}
void MainWindow::on_radRed()
{
QPalette plet= ui->pltEdit->palette();
plet.setColor(QPalette::Text,Qt::red);
ui->pltEdit->setPalette(plet);
}
QSlider和QProgressBar
QAbstractSlider是QSlider,QScrollBar和QDial的父類,它定義了這幾個類共有的一些屬性和介面函式.
屬性 | 屬性值型別 | 功能 |
---|---|---|
minimum | int | 資料範圍的最小值 |
maximum | int | 資料範圍的最大值 |
singleStep | int | 變化最小步長 |
pageStep | int | 按PgUp與PgDn變化的數值 |
value | int | 元件的當前值 |
sliderPosition | int | 滑塊的位置 |
tracking | bool | 改變value是否改變slider位置 |
orientation | Qt::Orientation | 滑動條的方向,水平或垂直 |
invertedAppearance | bool | 顯示方式是否反向 |
invertedControls | bool | 反向按鍵控制 |
QAbstractSlider的介面函式主要是屬性的讀寫函式,還有一個常用函式setRange()用於設定最大值與最小值.
- void QAbstractSlider::setRange(int min,int max)
QAbstractSlider類的訊號主要有:
- void actionTriggered(int action)//滑動條觸發一些動作
- void rangeChanged(int min,int max)//minimum或maximum值變化時
- void sliderMoved(int value)//使用者按住滑鼠拖動滑塊時
- void sliderPressed()//在滑塊上按下滑鼠時
- void sliderReleased()//在滑塊上釋放滑鼠時
- void valueChanged(int value)//value值改變時
action表示動作的型別,用列舉型別QAbstractSlider::SliderAction的值表示.如SliderToMinimum表示拖動到最小值.
如果tracking屬性被設定為false時,valueChanged()僅在滑鼠拖動結束時發射.
QSlider一般用於滑動輸入數值資料的元件,其新定義的屬性有兩個:
- tickPosition:標尺刻度的顯示位置,屬性值為列舉型別QSlider::TickPosition.
- tickInterval:標尺刻度的間隔值.
QScrollBar沒有新定義的屬性,一般與文字編輯器或容器元件組合使用.起滾卷條的作用.
QDial表示錶盤式元件,透過旋轉錶盤獲得輸入值.QDial定義了3個新的屬性:
- notchesVisible:錶盤外圍的刻度線是否可見.
- notchTarget:錶盤刻度間的間隔畫素值.
- wrapping:錶盤上首尾刻度是否連貫.
QProgressBar表示進度條元件,一般以百分比資料來顯示進度.其父類為QWidget.
其幾個不易理解的屬性如下:
- textDirection:文字的方向.
- format:顯示文字的格式.
QProgressBar類的介面函式主要是屬性的讀寫函式.QProgressBar還有兩個常用的與屬性無關的函式:
- void QProgressBar::setRange(int minimum,int maximum)
- void QProgressBar::reset()
下面是一個使用捲軸的例項:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->dial,SIGNAL(valueChanged(int)),this,SLOT(do_valueChange(int)));
connect(ui->progressBar,SIGNAL(valueChanged(int)),this,SLOT(do_valueChange(int)));
connect(ui->scrollBar,SIGNAL(valueChanged(int)),this,SLOT(do_valueChange(int)));
connect(ui->slider,SIGNAL(valueChanged(int)),this,SLOT(do_valueChange(int)));
connect(ui->spinBox,SIGNAL(valueChanged(int)),this,SLOT(do_valueChange(int)));
ui->dial->setNotchesVisible(true);
do_valueChange(10);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::do_valueChange(int value)
{
ui->dial->setValue(value);
ui->progressBar->setValue(value);
ui->scrollBar->setValue(value);
ui->slider->setValue(value);
ui->spinBox->setValue(value);
}
日期時間資料
日期和時間是經常遇到的資料型別.Qt提供了三個類用於表示和處理資料型別:
- QTime:表示時間資料的類.
- QDate:表示日期資料的類.
- QDateTime:表示時間和日期資料的類.
這三個類都沒有父類.為了在介面上輸入和現實日期時間的資料,Qt定義了幾個用於日期時間資料處理的介面類:
- QTimeEdit:編輯和顯示時間的元件類
- QDateEdit:編輯和顯示日期的元件類
- QDateTimeEdit:編輯和顯示日期的元件類.
- QCalendarWidget:一個用日曆形式顯示和選擇日期的元件類.
QTime類適用於儲存與操作時間資料的類,時間資料包含小時,分鐘,秒,毫秒.QTime總是24小時制,不區分AM/PM.
QTime初始化時間資料的函式定義如下:
- QTime::QTime(int h,int m,int s=0,int ms=0)
還可以使用靜態函式QTime::currentTime()建立一個QTime物件,並將其初始化為系統當前時間.
函式原型 | 功能 |
---|---|
int hour() | 返回當前時間的小時 |
int minute() | 返回當前時間的分鐘 |
int second() | 返回當前時間的秒 |
int misec() | 返回當前時間的毫秒 |
bool setHMS(int h,int m,int s,int ms=0) | 設定當前時間的資料 |
int msecSinceStartOfDay() | 返回時間從00:00:00開始的毫秒數 |
QTime addSecs(int s) | 當前時間延後s秒後的時間 |
int secsTo(QTime t) | 返回一個與當前時間相差t秒的秒數 |
QString toString(const QString& format) | 將當前時間按照format格式轉換為字串 |
QDate是用於儲存和操作日期資料的類,日期資料包含年月日資料.
與QTime類似,可以在初始化時為其提供資料,也可以使用靜態函式QDate::currentDate()獲取系統當前日期.
函式原型 | 功能 |
---|---|
int year() | 返回當前日期年資料 |
int month() | 返回當前日期月資料 |
int day() | 返回當前日期日資料 |
int dayOfWeek() | 返回當前日期在一週中的日期 |
int dayOfYear() | 返回當前日期在一年中是第多少天 |
bool setDate(int year,int month,int day) | 設定日期的年日月資料 |
void getDate(int* year,int* month,int* day) | 透過指標變數,返回年日月資料 |
QDate addYears(int nyears) | 返回一個較時間遲n年的QDate變數 |
QDate addMonths(int nmonths) | 返回一個較時間遲n月的QDate變數 |
QDate addDays(qint64 ndays) | 返回一個較時間遲n天的QDate變數 |
qint64 daysTo(QDate d) | 返回一個與當前日期差d天的天數 |
QString toString(const QString&format) | 將當前日期按照format格式轉換為字串 |
此外,QDate還有一個靜態函式isLeapYear()可以判斷某年是否為閏年:
- bool QDate::isLeapYear(int year)
函式原型 | 功能 |
---|---|
QDate date() | 返回當前日期時間資料的日期資料 |
QTime time() | 返回當前日期時間資料的時間資料 |
qint64 toMSecsSinceEpoch() | 返回與UTC時間1970-01-01T00:00:00:00.000相差的毫秒數 |
void setMSecsSinceEpoch(qint64 msecs) | 設定與UTC時間1970-01-01T00:00:00:00.000相差的毫秒數 |
qint64 toSecsSinceEpoch() | 返回與UTC時間1970-01-01T00:00:00:00.000相差的秒數 |
void setSecsSinceEpoch(qint64) | 設定與UTC時間1970-01-01T00:00:00:00.000相差的秒數 |
QString toString(const QString& format) | 將當前日期時間按照format設定的格式轉換為字串 |
QDateTime toUTC() | 將當前時間轉換為UTC時間 |
QDateTime有兩個靜態函式用於返回系統當前時間:
- QDateTime QDateTime::currentDateTime()
- QDateTime QDateTime::currentDateTimeUtc()
QTime,QDate,QDateTime都有一個函式toString(),用於將當前的日期時間資料轉換為字串.
同樣的,QTime,QDate,QDateTime都有一個靜態函式fromString().用於將字串轉換為相應類的物件.
- QString QDateTime::toString(const QString&format,QCalendar cal=QCalendar())
- QDateTime QDateTime::fromString(const QString&string,const QString&format,QCalendar cal=QCalendar())
格式字元 | 含義 |
---|---|
d | 天1~31 |
dd | 天01~31 |
M | 月1~12 |
MM | 月01~12 |
yy | 年00~99 |
yyyy | 年0000~9999 |
h | 小時023或112 |
hh | 小時0023或0112 |
H | 小時0~23 |
HH | 小時00~23 |
m | 分鐘0~59 |
mm | 分鐘00~59 |
s | 秒0~59 |
ss | 秒00~59 |
z | 毫秒0~999 |
zzz | 毫秒000~999 |
AP或A | 使用AM/PM顯示 |
ap或a | 使用am/pm顯示 |
而且上述字元僅作為一個佔位符使用,其其他內容不影響其字串format.
QtDesigner有3個用於編輯日期時間資料的介面元件,如QTimeEdit,QDateEdit,QDateTimeEdit.
而QDateTimeEdit是QDateEdit和QTimeEdit的父類,而QDateTimeEdit的父類是QAbstractSpinBox.
所以其實日期時間編輯框的特性與QSpinBox的有些相似.
QDateTimeEdit的主要屬性有:
- currentSection:游標所在的輸入段,是列舉型別QDateTimeEdit::Section.
- currentSecitonIndex:用序號表示的游標所在的段.
- calendarPopup:是否允許彈出一個日曆選擇框.會將上下調節按鈕變成一個下拉按鈕.
- displayFormat:日期時間資料的顯示格式.
QDateTimeEdit常用的介面函式就是讀取或設定日期時間資料的函式:
- QDateTime dateTime()
- void setDateTime(const QDateTime&dateTime)
- QDate date()
- void setDate(QDate date)
- QTime time()
- void setTime(QTime time)
QDateTimeEdit有3個訊號:
- void dateChanged(QDate date)
- void timeChanged(QTime time)
- void dateTimeChanged(const QDateTime& datetime)
QCalendarWidget則是一個用於選擇日期的日曆元件.
QCalendarWidget的幾個常見介面函式有:
- void showToday()
- void showSelectedDate()
- QDate selectedDate()
- void setSelectedDate(QDate date)
QCalendarWidget有4個訊號:
- void activated(QDate date)
- void clicked(QDate date)
- void currentPageChanged(int year,int month)
- void selectionChanged()
選擇的日期變化時,QCalendarWidget會發射selectionChanged訊號.
下面給出了一個使用QDateTime,QCalendarWidget等的例子:
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
void on_btnReset();
void on_btnClear();
void on_btnTime();
void on_btnDate();
void on_btnDateTime();
void on_btnChange();
void on_timeEdit();
void on_dateEdit();
void on_dateTimeEdit();
void on_calendar();
};
#endif // MAINWINDOW_H
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->btnClear,SIGNAL(clicked(bool)),this,SLOT(on_btnClear()));
connect(ui->btnReset,SIGNAL(clicked(bool)),this,SLOT(on_btnReset()));
connect(ui->btnTime,SIGNAL(clicked(bool)),this,SLOT(on_btnTime()));
connect(ui->btnDate,SIGNAL(clicked(bool)),this,SLOT(on_btnDate()));
connect(ui->btnDateTime,SIGNAL(clicked(bool)),this,SLOT(on_btnDateTime()));
connect(ui->btnChange,SIGNAL(clicked(bool)),this,SLOT(on_btnChange()));
connect(ui->dateEdit,SIGNAL(dateChanged(QDate)),this,SLOT(on_dateEdit()));
connect(ui->timeEdit,SIGNAL(timeChanged(QTime)),this,SLOT(on_timeEdit()));
connect(ui->dateTimeEdit,SIGNAL(dateTimeChanged(QDateTime)),this,SLOT(on_dateTimeEdit()));
connect(ui->calendar,SIGNAL(selectionChanged()),this,SLOT(on_calendar()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnReset()
{
ui->calendar->clearFocus();
ui->dateEdit->clear();
ui->timeEdit->clear();
ui->dateTimeEdit->clear();
ui->pltEdit->clear();
ui->lineEdit->clear();
}
void MainWindow::on_btnClear()
{
ui->lineEdit->clear();
ui->pltEdit->clear();
}
void MainWindow::on_btnTime()
{
QTime TM1(13,24,5);
QString str=TM1.toString("HH:mm:ss");
ui->pltEdit->appendPlainText(QString("Time1:%1").arg(str));
QTime TM2= TM1.addSecs(150);
str= TM2.toString("HH:mm:ss");
ui->pltEdit->appendPlainText(QString("Time1 add 150secs:%1").arg(str));
TM2= QTime::currentTime();
str=TM2.toString("HH:mm:ss zzz");
ui->pltEdit->appendPlainText(QString("Current Time:%1").arg(str));
}
void MainWindow::on_btnDate()
{
QDate DT1(2021,7,6);
QString str=DT1.toString("yyyy-MM-dd");
ui->pltEdit->appendPlainText(QString("Date1:%1").arg(str));
QDate DT2;
DT2.setDate(2021,8,25);
str=DT2.toString("yyyy-MM-dd");
ui->pltEdit->appendPlainText(QString("Date2:%1").arg(str));
DT2=QDate::currentDate();
str=DT2.toString("yyyy-MM-dd");
ui->pltEdit->appendPlainText(QString("Current Date:%1").arg(str));
}
void MainWindow::on_btnDateTime()
{
QDateTime DT1=QDateTime::currentDateTime();
QString str=DT1.toString("yyyy-MM-dd hh:mm:ss zzz");
ui->pltEdit->appendPlainText(QString("Current DateTime:%1").arg(str));
QDate dt= DT1.date();
str=dt.toString("yyyy-MM-dd");
ui->pltEdit->appendPlainText(QString("DT1 Date:%1").arg(str));
QTime tm=DT1.time();
str=tm.toString("hh:mm:ss zzz");
ui->pltEdit->appendPlainText(QString("DT1 Time:%1").arg(str));
qint64 MS=DT1.toSecsSinceEpoch();
ui->pltEdit->appendPlainText(QString("Secs Since:%1").arg(MS));
MS+=120;
DT1.setSecsSinceEpoch(MS);
str=DT1.toString("yyyy-MM-dd hh:mm:ss zzz");
ui->pltEdit->appendPlainText(QString("DT1 After120s:%1").arg(str));
}
void MainWindow::on_btnChange()
{
static bool calendar_flag=true;
ui->dateTimeEdit->setCalendarPopup(calendar_flag);
calendar_flag=!calendar_flag;
}
void MainWindow::on_timeEdit()
{
QTime tm= ui->timeEdit->time();
ui->dateTimeEdit->setTime(tm);
}
void MainWindow::on_dateEdit()
{
QDate dt= ui->dateEdit->date();
ui->lineEdit->setText(QString("%1").arg(dt.toString("yyyy-MM-dd")));
ui->dateTimeEdit->setDate(dt);
ui->calendar->setSelectedDate(dt);
ui->calendar->showSelectedDate();
}
void MainWindow::on_dateTimeEdit()
{
QDateTime datetime= ui->dateTimeEdit->dateTime();
ui->lineEdit->setText(QString("%1").arg(datetime.date().toString("yyyy-MM-dd")));
ui->dateEdit->setDate(datetime.date());
ui->timeEdit->setTime(datetime.time());
ui->calendar->setSelectedDate(datetime.date());
ui->calendar->showSelectedDate();
ui->pltEdit->appendPlainText(QString("Now Time:%1").arg(datetime.toString("yyyy-MM-dd hh:mm:ss zzz")));
}
void MainWindow::on_calendar()
{
QDate dt=ui->calendar->selectedDate();
ui->dateEdit->setDate(dt);
ui->dateTimeEdit->setDate(dt);
ui->lineEdit->setText(dt.toString("yyyy-MM-dd"));
}
QTimer和QElapsedTimer
QTimer是軟體計時器,其父類是QObject.其主要功能是設定以毫秒為單位的定時週期.
當定時器啟動後,定時溢位時QTimer發射timeout()訊號.
QTimer類的主要屬性如下:
屬性 | 屬性值型別 | 功能 |
---|---|---|
interval | int | 定時週期,單位是毫秒 |
singleShot | bool | 定時器是否為單次計時 |
timerType | Qt::TimerType | 定時器精度型別 |
active | bool | 返回定時器是否正在執行 |
remainingTime | int | 到發生定時溢位的剩餘時間 |
屬性timeType表示定時器的精度型別,設定函式setTimerType()的原型定義如下:
- void QTimer::setTimerType(Qt::TimerType atype)
引數atype是列舉型別Qt::TimerType,有以下幾個列舉值,預設為Qt::CoarseTimer:
- Qt::PreciseTimer:精確計時器,精度保持在毫秒級
- Qt::CoarseTimer:粗糙計時器,定時誤差保持在週期值的5%內
- Qt::VeryCoarseTimer:非常粗糙的定時器,精度保持在秒級.
QTimer有幾個公有槽函式用於啟動和停止定時器:
- void QTimer::start()//啟動定時器
- void QTimer::start(int msec)//啟動定時器,並設定定時週期
- void QTimer::stop()//停止定時器
QTimer只有一個timeout()訊號,其原型如下:
- void QTimer::timeout()
QTimer還有一個靜態函式singleShot(),用於建立和啟動單次定時器,並且將定時器的timeout()訊號與指定的槽函式關聯.
這個函式有多種引數形式,其中一種函式原型定義如下:
- void QTimer::singleShot(int msec,Qt::TimerType,const QObject* receiver,const char* member)
QElapsedTimer則用於快速計算兩個時間的間隔時間,它沒有父類,不支援Qt的元物件系統,所以只有介面函式.
QElapsedTimer的介面函式有:
- void start()
- qint64 elapsed()
- qint64 nsecsElapsed()
- qint64 restart()
函式elapsed()的返回值是自上次start()之後計時器的執行時間,單位是毫秒.
函式nsecsElapsed()的返回值也是指上次start()之後計時器的執行時間,但單位是納秒.
函式restart()返回從上次啟動計時器到現在的時間,單位是毫秒,然後重啟計時器.
下面是一個使用QTimer的例項:
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTime>
#include <QTimer>
#include <QElapsedTimer>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QTimer* m_timer;
QElapsedTimer m_counter;
private slots:
void do_timer_timeout();
void do_timer_shot();
void do_btnStart();
void do_btnStop();
void do_btnOneShot();
};
#endif // MAINWINDOW_H
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_timer= new QTimer(this);
m_timer->stop();
m_timer->setTimerType(Qt::CoarseTimer);
ui->radCoarse->setChecked(true);
connect(m_timer,SIGNAL(timeout()),this,SLOT(do_timer_timeout()));
connect(ui->btnStart,SIGNAL(clicked(bool)),this,SLOT(do_btnStart()));
connect(ui->btnStop,SIGNAL(clicked(bool)),this,SLOT(do_btnStop()));
connect(ui->btnOneShot,SIGNAL(clicked(bool)),this,SLOT(do_btnOneShot()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::do_timer_timeout()
{
QApplication::beep();
QTime curTime= QTime::currentTime();
ui->LCDHour->display(curTime.hour());
ui->LCDMin->display(curTime.minute());
ui->LCDSec->display(curTime.second());
if(m_timer->isSingleShot()){
int tmMsec= m_counter.elapsed();
QString str=QString("流逝的時間:%1毫秒").arg(tmMsec);
ui->labelTime->setText(str);
ui->btnStop->setEnabled(false);
}
}
void MainWindow::do_timer_shot()
{
QApplication::beep();
int tmMsec= m_counter.elapsed();
QString str=QString("流逝的時間:%1毫秒").arg(tmMsec);
ui->labelTime->setText(str);
ui->btnOneShot->setEnabled(true);
}
void MainWindow::do_btnStart()
{
m_timer->setInterval(ui->spinBox->value());
if(ui->radCoutinue->isChecked())
m_timer->setSingleShot(false);
else
m_timer->setSingleShot(true);
if(ui->radPrecise->isChecked())
m_timer->setTimerType(Qt::PreciseTimer);
else if(ui->radCoutinue->isChecked())
m_timer->setTimerType(Qt::CoarseTimer);
else
m_timer->setTimerType(Qt::VeryCoarseTimer);
m_timer->start();
m_counter.start();
ui->btnStart->setEnabled(false);
ui->btnOneShot->setEnabled(false);
ui->btnStop->setEnabled(true);
}
void MainWindow::do_btnStop()
{
m_timer->stop();
int tmMsec= m_counter.elapsed();
int ms= tmMsec%1000;
int sec= tmMsec/1000;
QString str= QString("流逝的時間:%1秒%2毫秒").arg(sec).arg(ms,3,10,QChar('0'));
ui->labelTime->setText(str);
ui->btnStart->setEnabled(true);
ui->btnOneShot->setEnabled(true);
ui->btnStop->setEnabled(false);
}
void MainWindow::do_btnOneShot()
{
int intv= ui->spinBox->value();
QTimer::singleShot(intv,Qt::PreciseTimer,this,&MainWindow::do_timer_shot);
m_counter.start();
ui->btnOneShot->setEnabled(false);
}
QComboBox
QComboBox是下拉選單框元件,它可以提供下拉選單供使用者選擇輸入,也可以提供編輯框用於輸入文字.
所以QComboBox也被稱為組合框.
屬性 | 屬性值型別 | 功能 |
---|---|---|
editable | bool | 是否可編輯,若為false則只可使用下拉欄 |
currentText | QString | 當前顯示的文字 |
currentIndex | int | 當前選中項的序號 |
maxVisibleItems | int | 下拉選單中顯示最大條數,若超過將出現卷滾條 |
maxCount | int | 下拉選單中最大項數 |
insertPolicy | InsertPolicy | 使用者編輯的新文字插入列表的方式,為列舉型別QComboBox::InsertPolicy |
placeholderText | QString | 佔位文字 |
duplicatesEnabled | bool | 是否允許列表中出現重複的項 |
modelColumn | int | 下拉選單中的資料在資料模型中的列編號 |
QComboBox使用模型/檢視結構儲存和顯示下拉選單的資料,下拉選單的資料實際上儲存在QStandardItemModel模型裡.下拉選單使用QListView的子類元件顯示.modelColumn屬性表示下拉選單現實的資料在模型中的列編號.
QComboBox的幾個訊號原型如下:
- void activated(int index)
- void currentIndexChanged(int index)
- void currentTextChanged(const QString &text)
- void editTextChanged(const QString &text)
- void highlighted(int index)
- void textActivated(const QString &text)
- void textHighlighted(const QString &text)
下面是使用QComboBox的一個例項:
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
//void on_btnSimpleInit();
void on_pushButton_5_clicked(bool checked);
void on_btnSimpleInit_clicked(bool checked);
void on_chkEditable_clicked(bool checked);
void on_btnClearList_clicked(bool checked);
void on_btnDataInit_clicked(bool checked);
void comChanged(const QString& arg1);
void on_comData_currentIndexChanged(int index);
void on_chkReadOnly_clicked(bool checked);
};
#endif // MAINWINDOW_H
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_5_clicked(bool checked)
{
ui->pltEdit->clear();
}
void MainWindow::on_btnSimpleInit_clicked(bool checked)
{
QIcon icon;
icon.addFile(":/img/icon.jpg");
ui->comSimple->clear();
for(int i=0;i<20;i++)
ui->comSimple->addItem(icon,QString("城市%1").arg(i));
}
void MainWindow::on_chkEditable_clicked(bool checked)
{
ui->comSimple->setEditable(checked);
}
void MainWindow::on_btnClearList_clicked(bool checked)
{
ui->comSimple->clear();
}
void MainWindow::on_btnDataInit_clicked(bool checked)
{
ui->comData->clear();
QMap<QString,int>city_zone;
city_zone.insert(QString("北京"),10);
city_zone.insert(QString("上海"),20);
city_zone.insert(QString("廣州"),30);
city_zone.insert(QString("長沙"),40);
city_zone.insert(QString("成都"),50);
for(auto iter:city_zone.keys())
ui->comData->addItem(iter,city_zone.value(iter));
}
void MainWindow::comChanged(const QString &arg1)
{
ui->pltEdit->appendPlainText(arg1);
}
void MainWindow::on_comData_currentIndexChanged(int index)
{
Q_UNUSED(index);
QString str= ui->comData->currentText()+ui->comData->currentData().toString();
ui->pltEdit->appendPlainText(str);
}
void MainWindow::on_chkReadOnly_clicked(bool checked)
{
ui->pltEdit->setEnabled(!checked);
}
QMainWindow和QAction
QMainWindow是主視窗類,具有選單欄,工具欄,狀態列等主視窗常見的介面元素.
要設計主視窗上的選單欄,工具欄,按鈕的下拉選單,組建的快捷選單等需要用到QAction類.
視窗介面視覺化設計
建立一個GUI專案,在嚮導中選擇視窗基類為QMainWindow,新建視窗類的名稱會被自動設定為MainWindow.
QAction的父類是QObject,所以支援Qt的元物件系統.在UI視覺化設計時就可以建立Action,使用設計好的Action可以建立選單項和工具按鈕.
Qt Designer介面下方有一個Action編輯器,可以在這個編輯器裡視覺化設計Action.
在Action編輯器中,編輯Action的對話方塊,包括以下一些設定內容:
- Text:Action的顯示文字
- Object name:Action的物件名稱
- ToolTip:當滑鼠游標停留時的提示
- Icon:Action的圖示
- Checkable:Action是否可被複選
- ShortCut:Action的快捷鍵.
在Action編輯器中建立一個Action後,屬性編輯器就會顯示這幾個Action的屬性.一些屬性說明如下:
- text:用Action建立選單項時顯示的文字.
- iconText:這是用Action建立工具按鈕時按鈕上顯示的文字.
- statusTip:這是滑鼠移到Action上時的提示.
- shortcutContext:這是Action快捷鍵的有效響應範圍.
- autoRepeat:當快捷鍵一直按下時,Action是否自動重複執行.
- menuRole:在macOS上才有作用的功能.
- iconVisibleInMenu:表示選單項上是否需顯示Action圖示.
- shortcutVisuableInContextMenu:表示使用Action建立右鍵快捷選單時,是否顯示快捷鍵.
- priority:表示Action在UI上的優先順序.
工具欄對應QToolBar類,選擇一個工具欄後,在屬性編輯器中可對其屬性進行設定.
屬性名稱 | 屬性值型別 | 含義與作用 |
---|---|---|
movable | bool | 工具欄是否可移動 |
allowedAreas | Qt::ToolBarAreas | 工具欄可以放置的視窗區域 |
orientation | Qt::Orientation | 工具欄的方向 |
iconSize | QSize | 圖示的大小 |
toolButtonStyle | Qt::ToolButtonStyle | 工具按鈕樣式 |
floatable | bool | 工具欄是否可浮動 |
屬性toolButtonStyle的取值決定了工具按鈕顯示的樣式,屬性值Qt::ToolButtonStyle有以下幾種列舉值.
- Qt::ToolButtonIconOnly:只顯示圖示
- Qt::ToolButtonTextOnly:只顯示文字
- Qt::ToolButtonTextBesideIcon:文字顯示在圖示旁邊
- Qt::ToolButtonTextUnderIcon:文字顯示在圖示下面
- Qt::ToolButtonFollowStyle:由QStyle樣式定義
QAction的類大部分介面函式是用於屬性讀寫的函式.
QAction還定義了一些訊號和公有槽.QAction主要的訊號有:
- void changed()//Action的text等屬性發生改變時
- void checkableChanged(bool checkable)//checkable的屬性變化時
- void enabledChanged(bool enabled)//enabled屬性值變化時
- void hovered()//滑鼠移動至該Action上時
- void toggled(bool checked)//checked屬性值變化時
- void triggered(bool checked=false)//點選此Action時
- void visibleChanged()//visible屬性值變化時
當我們點選Action建立的選單項/工具按鈕或按下Action的快捷鍵時,QAction屬性發射triggered()訊號.
當Action的checked屬性變化時,Action會發射toggled(bool)訊號.
QAction定義了一些公有槽,這些公有槽可以在程式中直接呼叫或connect.
- void hover()//觸發hovered()訊號
- void trigger()//觸發triggered()訊號
- void resetEnabled()//復位enabled為預設值
- void setChecked(bool)//設定checked屬性的值
- void setDisabled(bool b)//設定enabled屬性的值
- void setVisible(bool)//設定visible屬性的值
- void toggle()//反轉checked屬性的值
在UI視覺化設計時,可以用Action視覺化地建立工具欄上的按鈕,但是不能視覺化地在工具欄上放置其他元件.
QToolBar提供了介面函式,可以透過程式碼在工具欄上新增元件,從而靈活地設計工具欄.
- void addAction(QAction *action)//新增一個Action
- QAction *addWidget(QWidget *widget)//新增一個介面元件
- QAction *insertWidget(QAction *before,QWidget *widget)//插入一個介面元件
- QAction *addSeparator()//新增一個分隔條
- QAction *insertSeparator(QAction *before)//插入一個分隔條
主視窗上的狀態列對應的是QStatusBar類,在UI視覺化設計時,不能在狀態列上放置任何元件,而只能透過其介面函式向狀態列新增元件.
QStatusBar有兩個函式用於新增元件,其原型如下:
- void addWidget(QWidget *widget,int stretch=0)//新增正常元件
- void addPermanentWidget(QWidget *widget,int strech=0)//新增永久元件
QStatusBar類有兩個公有槽,可以顯示和清楚臨時訊息,定義如下:
- void showMessage(const QString &message,int timeout=0)//顯示臨時訊息
- void clearMessage()//清除臨時訊息
如果一個Action的statusTip屬性不為空,當滑鼠移到這個Action建立的選單或按鈕上時,狀態列就會自動顯示這個Action的statusTip屬性的內容:當滑鼠移出時,臨時訊息就會被自動清除.
下面是一個使用QAction,QToolBar,QStatusBar的綜合例子:
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QActionGroup>
#include <QLabel>
#include <QFontComboBox>
#include <QSpinBox>
#include <QProgressBar>
#include <QTextCharFormat>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QLabel* lbFile;
QProgressBar* progressBar;
QSpinBox* spinFontSize;
QLabel* lbFontSize;
QFontComboBox* fcomFont;
private slots:
void on_actNewFile_triggered();
void on_actOpenFile_triggered();
void on_actSaveFile_triggered();
void on_pltEdit_copyAvailable(bool b);
void on_pltEdit_selectionChanged();
void on_actBlod_triggered(bool checked);
void on_actItalian_triggered(bool checked);
void on_actUnderline_triggered(bool checked);
void on_spinFontSize(int fontSize);
void on_fcomCombo(QFont font);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
//中英介面互斥
ui->setupUi(this);
QActionGroup *acgLanguage = new QActionGroup(this);
acgLanguage->addAction(ui->actChinese);
acgLanguage->addAction(ui->actEnglish);
acgLanguage->setExclusive(true);
//建立一些無法透過GUI介面設計的元件
spinFontSize=new QSpinBox(this);
spinFontSize->setMinimum(5);
spinFontSize->setMaximum(50);
spinFontSize->setValue(ui->pltEdit->font().pointSize());
spinFontSize->setMinimumWidth(50);
QLabel* lbSpinFont= new QLabel(QString("字號"),this);
QLabel* lbFontComboBoxFont= new QLabel(QString("字型"),this);
fcomFont= new QFontComboBox(this);
fcomFont->setMaximumWidth(80);
fcomFont->setFont(ui->pltEdit->font());
ui->toolBar->addWidget(lbSpinFont);
ui->toolBar->addWidget(spinFontSize);
ui->toolBar->addWidget(lbFontComboBoxFont);
ui->toolBar->addWidget(fcomFont);
ui->toolBar->addSeparator();
ui->toolBar->addAction(ui->actClose);
ui->toolBar->addSeparator();
//狀態列相關
lbFile= new QLabel(this);
lbFile->setMaximumWidth(150);
lbFile->setText(QString("檔名:"));
ui->statusbar->addWidget(lbFile);
progressBar= new QProgressBar(this);
progressBar->setMinimum(5);
progressBar->setMaximum(50);
progressBar->setValue(ui->pltEdit->font().pointSize());
ui->statusbar->addWidget(progressBar);
lbFontSize= new QLabel(QString("Permanent"),this);
ui->statusbar->addPermanentWidget(lbFontSize);
//訊號與槽
connect(spinFontSize,SIGNAL(valueChanged(int)),this,SLOT(on_spinFontSize(int)));
connect(fcomFont,SIGNAL(currentFontChanged(QFont)),this,SLOT(on_fcomCombo(QFont)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actNewFile_triggered()
{
ui->pltEdit->clear();
ui->pltEdit->document()->setModified(false);
lbFile->setText("檔名:新建檔案");
}
void MainWindow::on_actOpenFile_triggered()
{
lbFile->setText(QString("正在開啟檔案"));
for(int i=1;i<99;i++){
progressBar->setValue(i);
_sleep(1);
}
lbFile->setText(QString("檔名:新建檔案"));
progressBar->setValue(ui->pltEdit->font().pointSize());
}
void MainWindow::on_actSaveFile_triggered()
{
ui->pltEdit->clear();
ui->pltEdit->document()->setModified(false);
QString str= lbFile->text();
lbFile->setText("檔案已儲存");
_sleep(2);
lbFile->setText(str);
}
void MainWindow::on_pltEdit_copyAvailable(bool b)
{
ui->actCopy->setEnabled(b);
ui->actCut->setEnabled(b);
ui->actPaste->setEnabled(ui->pltEdit->canPaste());
}
void MainWindow::on_pltEdit_selectionChanged()
{
QTextCharFormat fmt= ui->pltEdit->currentCharFormat();
ui->actBlod->setChecked(fmt.font().bold());
ui->actItalian->setChecked(fmt.font().italic());
ui->actUnderline->setChecked(fmt.font().underline());
spinFontSize->setValue(fmt.font().pointSize());
fcomFont->setCurrentFont(fmt.font());
}
void MainWindow::on_actBlod_triggered(bool checked)
{
QTextCharFormat fmt= ui->pltEdit->currentCharFormat();
if(checked)
fmt.setFontWeight(QFont::Bold);
else
fmt.setFontWeight(QFont::Normal);
ui->pltEdit->setCurrentCharFormat(fmt);
}
void MainWindow::on_actItalian_triggered(bool checked)
{
QTextCharFormat fmt= ui->pltEdit->currentCharFormat();
fmt.setFontItalic(checked);
ui->pltEdit->setCurrentCharFormat(fmt);
}
void MainWindow::on_actUnderline_triggered(bool checked)
{
QTextCharFormat fmt= ui->pltEdit->currentCharFormat();
fmt.setFontUnderline(checked);
ui->pltEdit->setCurrentCharFormat(fmt);
}
void MainWindow::on_spinFontSize(int fontSize)
{
QTextCharFormat fmt=ui->pltEdit->currentCharFormat();
fmt.setFontPointSize(fontSize);
progressBar->setValue(fontSize);
ui->pltEdit->setCurrentCharFormat(fmt);
}
void MainWindow::on_fcomCombo(QFont font)
{
QTextCharFormat fmt=ui->pltEdit->currentCharFormat();
fmt.setFont(font);
ui->pltEdit->setCurrentCharFormat(fmt);
lbFontSize->setText(QString("字型:%1").arg(font.family()));
}
在此還需要補充QPlainTextEdit相關的一些使用.
QPlainTextEdit元件定義了許多用於編輯操作的槽函式,其也有一些訊號函式:
- void blockCountChanged(int newBlockCount)//段落數變化時
- void copyAvailable(bool yes)//有文字被選擇或取消選擇時
- void cursorPositionChanged(bool changed)//游標位置變化時
- void modificationChanged(bool changed)//文件的修改狀態變化時
- void redoAvailable(bool available)//redo操作狀態變化時
- void selectionChanged()//選擇的內容變化時
- void textChanged()//文件內容變化時
- void undoAvailable(bool available)//undo操作狀態變化時
- void updateRequest(const QRect &rect,int dy)//需要更新顯示時
QToolButton和QListWidget
Qt中用於處理項資料(item data)的元件有兩類:
一類是Item Views元件,包括QListView,QTreeView,QTableView等;
另一類是Item Widgets元件,包括QListWidget,QTreeWidget,QTableWidget等.
Item Widgets元件直接將資料儲存在每一個項裡,一個項儲存了文字,文字的格式定義,圖示,使用者資料等內容.
QToolBox是工具箱元件類,工具箱是一種垂直分頁的多頁容器元件.在UI視覺化設計時,在工具箱元件上點選滑鼠右鍵調出快捷選單,可以分別使用Insert Page和Delete Page選單項新增和刪除頁面.
工具箱的每一個頁面都是一個QWidget元件,在頁面的工作區可以放置任何其他介面元件.
QToolBox有一個訊號,其中index是當前頁面序號:
- void QToolBox::currentChanged(int index)
對於QListWidget,其有的QListWidgetItem有一個標識變數flags,用於設定列表項的特性.
flags是列舉型別Qt::ItemFlag的列舉值的組合:
- Selectable:列表項可被選擇,Qt::ItemIsSelectable
- Editable:列表項可被編輯,Qt::ItemIsEditable
- DragEnabled:列表項可以被拖動,Qt::ItemIsDragEnabled
- DropEnabled:列表項可以接收拖放的項,Qt::ItemIsDropEnabled
- UserCheckable:列表項可以被複選,Qt::ItemIsUserCheckable
- Enabled:列表項可用,Qt::ItemIsEnabled
- Tristate:自動改變列表項複選狀態,Qt::ItemIsAutoTristate
QToolButton繼承於一般的QAbstractButton,並在此基礎上有新增的屬性:
- popupMode屬性:屬性值為QToolButton::ToolButtonPopupMode.這個屬性決定了彈出選單的模式.
- QToolButton::DelayedPopup:按鈕上沒有任何附加的顯示內容.如果按鈕有下拉選單,則按下按鈕並延時一會兒後才顯示下拉選單.
- QToolButton::MenuButtonPopup:會在按鈕右側顯示一個帶箭頭的下拉按鈕.
- QToolButton::InstantPopup:會在按鈕右下角顯示一個很小的下拉箭頭圖示.
- toolButtonStyle屬性:屬性值是列舉型別Qt::ToolButtonTextBesideIcon.比歐仕工具按鈕上文字標的顯式方式.
- autoRaise屬性:如果設定為true,按鈕就沒有邊框,滑鼠移動到按鈕上才顯示邊框.
- arrowType屬性:屬性值是列舉型別Qt::ArrowType,預設值Qt::NoArrow.不會在上面顯示內容.
除了與讀寫相關的一些介面函式,QToolButton類還有兩個主要的函式:
- setDefaultAction()函式:這個函式用於為工具按鈕設定關聯的Action
- void QToolButton::setDefaultAction(QAction*action)
- setMenu()函式:這個函式用於為工具按鈕設定下拉選單,其函式原型定義如下:
- void QToolButton::setMenu(QMenu*menu)
QMenu是選單類,它直接從QWidget繼承而來.在Qt Designer中我們可以透過Action視窗建立選單欄.
QMenu是管理選單的類,它的父類是QWidget,選單實際上是一種視窗.建立選單主要會用到一下幾個函式:
- void QWidget::addAction(QAction*action)//新增Action
- QAction *QMenu::addMenu(QMenu *menu)//新增選單
- QAciton *QMenu::addSeparator()//新增一個分隔條
顯示選單可以使用exec()函式,其函式原型定義如下:
- QAction *QMenu::exec(const QPoint&p,QAction*action=nullptr)
引數p表示選單左上角座標,顯示滑鼠右鍵快捷選單時,通常使用滑鼠游標的當前位置QCursor::pos()作為引數p的值.
QListWidget元件的列表項是QListWidgetItem物件.QListWidgetItem沒有父類,所以沒有屬性,但是它有一些讀取函式與設定函式:
讀取函式 | 設定函式 | 資料型別 | 設定函式的功能 |
---|---|---|---|
text() | setText() | QString | 設定項的文字 |
icon() | setIcon() | QIcon | 設定項的圖示 |
data() | setData() | QVariant | 為項的不同角色設定資料 |
flags() | setFlags() | Qt::ItemFlag | 設定項的特性,是Qt::ItemFlag的組合 |
checkState() | setCheckState() | Qt::CheckState | 設定項的複選狀態 |
isSelected() | setSelected() | bool | 設定為當前項 |
QListWidget的主要介面函式則見下:
分組 | 函式名 | 功能 |
---|---|---|
新增或刪除項 | void addItem() | 新增一個項 |
void addItems() | 一次新增多個項 | |
void insertItem() | 在某一行前面插入一個項 | |
void insertItems() | 在某一行前面一次插入多個項 | |
QListWidgetItem *takeItem() | 從列表元件中移除一個項,並返回這個項 的物件指標,但不從記憶體中刪除這個項 |
|
void clear() | 移除列表中所有的項,並從記憶體中刪除 | |
項的訪問 | QListWidgetItem *currentItem() | 返回當前項 |
void setCurrentItem() | 設定當前項 | |
QListWidgetItem *item() | 根據行號返回一個項 | |
QListWidgetItem *itemAt() | 根據螢幕座標返回項 | |
int currentRow() | 返回當前行的行號 | |
void setCurrentRow() | 設定當前行 | |
int row() | 返回一個項所在行號 | |
int count() | 返回列表元件中項的個數 | |
排序 | void setSortingEnabled() | 設定列表是否可排序 |
bool isSortingEnabled() | 列表是否可排序 | |
void sortItems() | 對列表按照指定方式排序 |
QListWidget元件中的每一行是一個QListWidgetItem物件.
QListWidgetItem的函式setFlags()用於設定項的一些特性.其函式原型定義如下:
- void QListWidgetItem::setFlags(Qt::ItemFlags flags)
QListWidget定義的訊號比較多,各訊號的定義如下:
- void currentItemChanged(QListWidget *current,QListWidgetItem *previous)
- void currentRowChanged(int currentRow)
- void currentTextChanged(const QString& currentText)
- void itemSelectionChanged()
- void itemChanged(QListWidgetItem *item)
- void itemActivated(QListWidgetItem *item)
- void itemEntered(QListWidgetItem *item)
- void itemPressed(QListWidgetItem *item)
- void itemClicked(QListWidget *item)
- void itemDoubleClicked(QListWidgetItem *item)
每個繼承自QWidget的類都有customContexrMenuRequested()訊號,在一個元件上點選滑鼠右鍵時,元件發射這個訊號,用於請求建立快捷選單.
要是QWidget元件在點選滑鼠右鍵時發射customContextMenuRequested()訊號,還需要設定contextMenuPolicy屬性:
- Qt::NoContextMenu:元件沒有快捷選單,由其父容器元件處理
- Qt::PreventContextMenu:阻止快捷選單,並且點選滑鼠右鍵事件也不會交給父容器元件處理.
- Qt::DefaultContextMenu:預設的快捷選單,QWidget::contextMenuEvent()事件被自動處理.
- Qt::ActionsContextMenu:自動根據QWidget::actions()返回的Action列表建立並顯示快捷選單.
- Qt::CustomContextMenu::元件發射customContextMenuRequested()訊號,由使用者程式設計實現快捷選單.
下面是一個綜合使用QToolButton和QListWidget的例子:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->actQuit,SIGNAL(triggered(bool)),this,SLOT(close()));
ui->toolButton->setDefaultAction(ui->actInitList);
ui->toolButton_2->setDefaultAction(ui->actDeleteList);
ui->toolButton_3->setDefaultAction(ui->actAddItem);
ui->toolButton_5->setDefaultAction(ui->actInsertItem);
ui->toolButton_6->setDefaultAction(ui->actDeleteItem);
ui->tbnSelAll_2->setDefaultAction(ui->actSelectAll);
ui->tbnSelNone_2->setDefaultAction(ui->actSelectNone);
ui->tbnSelInv_2->setDefaultAction(ui->actSelectInv);
QMenu* menuSelection=new QMenu(this);
menuSelection->addAction(ui->actSelectAll);
menuSelection->addAction(ui->actSelectInv);
menuSelection->addAction(ui->actSelectNone);
ui->tbnSelItems->setPopupMode(QToolButton::MenuButtonPopup);
ui->tbnSelItems->setMenu(menuSelection);
ui->tbnSelItems->setDefaultAction(ui->actSelection);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actInitList_triggered()
{
ui->listWidget_2->clear();
QIcon icon(QString(":/img/img/redo.jpg"));
bool chk=ui->chkEditable_2->isChecked();
for(int i=0;i<10;i++){
QListWidgetItem* aItem= new QListWidgetItem();
aItem->setIcon(icon);
aItem->setText(QString("Item %1").arg(i));
aItem->setCheckState(Qt::Checked);
if(chk)
aItem->setFlags(Qt::ItemIsEditable|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
else
aItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
ui->listWidget_2->addItem(aItem);
}
}
void MainWindow::on_actDeleteList_triggered()
{
ui->listWidget_2->clear();
}
void MainWindow::on_actAddItem_triggered()
{
QIcon icon(QString(":/img/img/redo.jpg"));
bool chk=ui->chkEditable_2->isChecked();
QListWidgetItem* aItem= new QListWidgetItem();
aItem->setIcon(icon);
aItem->setText(QString("New Item"));
aItem->setCheckState(Qt::Checked);
if(chk)
aItem->setFlags(Qt::ItemIsEditable|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
else
aItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
ui->listWidget_2->insertItem(ui->listWidget_2->currentRow(),aItem);
}
void MainWindow::on_actDeleteItem_triggered()
{
int row= ui->listWidget_2->currentRow();
delete ui->listWidget_2->takeItem(row);
}
void MainWindow::on_actInsertItem_triggered()
{
QIcon icon(QString(":/img/img/redo.jpg"));
bool chk=ui->chkEditable_2->isChecked();
QListWidgetItem* aItem= new QListWidgetItem();
aItem->setIcon(icon);
aItem->setText(QString("New Item"));
aItem->setCheckState(Qt::Checked);
if(chk)
aItem->setFlags(Qt::ItemIsEditable|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
else
aItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
ui->listWidget_2->addItem(aItem);
}
void MainWindow::on_listWidget_2_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
QString str="";
if(current!=NULL){
str+="當前項:"+current->text();
if(previous!=NULL)
str+=" 前一項:"+previous->text();
ui->litItemEdit_2->setText(str);
}
ui->plainTextEdit->appendPlainText(QString("currentChanged()訊號被髮射"));
}
void MainWindow::on_checkBox_clicked(bool checked)
{
ui->listWidget_2->setSortingEnabled(checked);
ui->toolButton_7->setEnabled(checked);
ui->toolButton_8->setEnabled(checked);
}
void MainWindow::on_toolButton_7_clicked(bool checked)
{
ui->listWidget_2->sortItems(Qt::AscendingOrder);
}
void MainWindow::on_toolButton_8_clicked(bool checked)
{
ui->listWidget_2->sortItems(Qt::DescendingOrder);
}
void MainWindow::on_pushButton_clicked()
{
ui->plainTextEdit->clear();
}
void MainWindow::on_pushButton_2_clicked()
{
ui->plainTextEdit->appendPlainText(QString(""));
}
void MainWindow::on_listWidget_2_itemDoubleClicked(QListWidgetItem *item)
{
ui->plainTextEdit->appendPlainText(QString("doubleClicked訊號發射")+item->text());
}
void MainWindow::on_listWidget_2_customContextMenuRequested(const QPoint &pos)
{
Q_UNUSED(pos);
QMenu* menuList= new QMenu(this);
menuList->addAction(ui->actInitList);
menuList->addAction(ui->actDeleteItem);
menuList->addAction(ui->actDeleteList);
menuList->addAction(ui->actInsertItem);
menuList->addAction(ui->actAddItem);
menuList->addSeparator();
menuList->addAction(ui->actSelectAll);
menuList->addAction(ui->actSelectNone);
menuList->addAction(ui->actSelectInv);
menuList->exec(QCursor::pos());
delete menuList;
}
void MainWindow::on_actSelectAll_triggered()
{
int cnt= ui->listWidget_2->count();
for(int i=0;i<cnt;i++){
QListWidgetItem *aItem=ui->listWidget_2->item(i);
aItem->setCheckState(Qt::Checked);
}
}
void MainWindow::on_actSelectNone_triggered()
{
int cnt= ui->listWidget_2->count();
for(int i=0;i<cnt;i++){
QListWidgetItem *aItem=ui->listWidget_2->item(i);
aItem->setCheckState(Qt::Unchecked);
}
}
void MainWindow::on_actSelectInv_triggered()
{
int cnt= ui->listWidget_2->count();
for(int i=0;i<cnt;i++){
QListWidgetItem *aItem=ui->listWidget_2->item(i);
if(aItem->checkState()==Qt::Checked)
aItem->setCheckState(Qt::Unchecked);
else if(aItem->checkState()==Qt::Unchecked)
aItem->setCheckState(Qt::Checked);
}
}
QTreeWidget
QTreeWidget簡介
QTreeWidget是一種Item Widget元件.QTreeWidget元件被稱為樹形元件,它的項(item)被稱為節點,一個樹形元件內的所有節點組成的結構被稱為目錄樹.
樹形元件適合顯示具有層級結構的資料,例如,Windows資源管理器中顯示的檔案系統.
- QTreeWidget樹形元件:例項使用樹形元件管理目錄與圖片檔案,可以新增或刪除節點.
- QDockWidget停靠元件:QDockWidget是可以在視窗上停靠或桌面上層浮動的元件.
- QLabel標籤元件:視窗右側是一個QScrollArea元件,在它上面放置一個標籤,為標籤設定一個QPixmap物件顯示圖片.透過QPixmap的介面函式可進行圖片縮放.
QDockWidget的主要屬性有:
- floating屬性:表示停靠區元件是否處於浮動狀態.
- features屬性:停靠區元件的特性.其為Qt::DockWidgetAreas列舉值的組合.
- allowedAreas屬性:允許停靠的區域,可以設定在視窗左側,右側,頂部,底部停靠,也可以設定不允許停靠.
- windowTitle屬性:停靠區視窗的標題.
一個QTreeWidget元件的顯示內容分為表頭和目錄樹兩部分,表頭和目錄樹都是QTreeWidgetItem物件.
QTreeWidget可以使用QTreeWidgetItem或簡單的文字作為表頭.
如果只是簡單地設定表頭文字,可以使用函式setHeaderLabels()將字串列表作為表頭各列的標題.
- void QTreeWidget::setHeaderLabels(const QStringList &labels)
如果使用QTreeWidget作為表頭,則可以使用函式setHeaderItem()設計表頭,還可以使用headerItem()返回.
- void QTreeWidget::setHeaderItem(QTreeWidgetItem *item)
- QTreeWidgetItem *QTreeWidget::headerItem()
如果使用QTreeWidgetItem物件作為表頭,就可以透過QTreeWidgetItem的介面函式設定表頭屬性.
目錄樹裡一行就是一個節點,節點是QTreeWidgetItem物件.節點可以有直接點,子節點就是下一級的節點.
目錄樹裡最上層的節點稱為頂層節點,頂層節點沒有父節點.目錄樹裡可以有任意多個頂層節點.相關函式如下:
- int topLevelItemCount()//返回頂層節點個數
- void addTopLevelItem(QTreeWidgetItem *item)//新增一個頂層節點
- void insertTopLevelItem(int index, QTreeWidgetItem *item)//插入一個頂層節點
- int indexOfTopLevelItem(QTreeWidgetItem *item)//返回一個頂層節點的索引號
- QTreeWidgetItem *topLevelItem(int index)//根據index返回一個頂層節點
- QTreeWidgetItem *takeTopLevelItem(int index)//移除一個頂層節點,但是不刪除
獲得一個頂層節點後,就可以訪問它的所有子節點.所有次級節點都直接或間接掛靠在某個頂層節點下面.
目錄樹中還有一個隱藏的根節點,其可以看作所有頂層節點的父節點.透過invisibleRootItem()可以訪問它:
- QTreeWidgetItem *QTreeWidget::invisibleRootItem().
使用這個結點就可以透過QTreeWidgetItem類的介面函式訪問所有頂層節點.
QTreeWidget也還有一些其他的常用函式:
- int columnCount()//返回表頭列數
- void setColumnCount(int columns)//設定表頭列數
- void sortItems(int columns,Qt::SortOrder order)//將目錄樹按照某一列排序
- int sortColumn()//返回用於排序的列的編號
- QTreeWidgetItem *currentItem()//返回當前節點
- QList<QTreeWidgetItem*> selectedItems()//返回選擇的節點列表
如果樹形元件允許多選,函式selectedItems()會返回選擇的節點的列表.透過QTreeWidget的上層父類QAbstractItemView的selectionMode屬效能夠設定選擇模式,可以設定為多選.
QTreeWidget有如下幾個共有槽函式:
- void clear()//清除整個目錄樹
- void collapseItem(const QTreeWidgetItem *item)//摺疊節點
- void expandItem(const QTreeWidget *item)//展開節點
- void scrollToItem(const QTreeWidget *item,QAbstractItemView::ScrollHint hint=EnsureVisible)
//用於保證節點item可見,必要時自動移動卷滾條
QTreeWidget類有如下幾個訊號:
- void currentItemChanged(QTreeWidgetItem *current,QTreeWidgetItem *previous)
//當選中項變化時發射 - void itemActivated(QTreeWidgetItem *item,int column)//雙擊節點或按下enter時
- void itemChanged(QTreeWidgetItem *item,int column)//其中項改變
- void itemClicked(QTreeWidgetItem *item,int column)//其中項被單擊或雙擊
- void itemCollapsed(QTreeWidgetItem *item)//節點摺疊時
- void itemDoubleClicked(QTreeWidgetItem *item,int column)//其中項被雙擊
- void itemEntered(QTreeWidgetItem *item,int column)//滑鼠游標移動到節點上拖動時
- void itemExpanded(QTreeWidgetItem *item)//節點展開時
- void itemPressed(QTreeWidgetItem *item,int column)//使用者選中了項
- void itemSelectionChanged()//使用者選擇的項改變
為了更好地理解,這裡需要對幾個訊號的發射條件進行區分:
currentItemChanged()訊號在當前節點發生變化時被髮射,current是當前節點,previous是之前節點.
itemChanged()訊號在某節點的某一列的屬性發生變化時被髮射.
itemClicked()訊號在點選節點時被髮射,不管當前節點的行和列有沒有變化都會觸發此訊號.
itemSelectionChanged()訊號在使用者選擇的節點發生變化時被髮射.
下面給出一個測試程式說明這些差異:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
for(int i=0;i<10;i++){
QTreeWidgetItem* new_item=new QTreeWidgetItem();
new_item->setText(0,QString("編號"));
new_item->setTextAlignment(0,Qt::AlignHCenter);
new_item->setTextAlignment(0,Qt::AlignVCenter);
new_item->setCheckState(0,Qt::Checked);
new_item->setText(1,QString("姓名"));
new_item->setTextAlignment(1,Qt::AlignHCenter);
new_item->setTextAlignment(1,Qt::AlignVCenter);
new_item->setCheckState(1,Qt::Checked);
ui->treeWidget->addTopLevelItem(new_item);
}
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_treeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
ui->plainTextEdit->appendPlainText(QString("currentItemChanged:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(current)));
return;
}
void MainWindow::on_treeWidget_itemActivated(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemActivated:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemChanged(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemChanged:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemClicked:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemCollapsed(QTreeWidgetItem *item)
{
ui->plainTextEdit->appendPlainText(QString("itemCollapsed:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemDoubleClicked:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemEntered(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemEntered:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemExpanded(QTreeWidgetItem *item)
{
ui->plainTextEdit->appendPlainText(QString("itemExpanded:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemPressed(QTreeWidgetItem *item, int column)
{
ui->plainTextEdit->appendPlainText(QString("itemPressed:%1").arg(ui->treeWidget->invisibleRootItem()->indexOfChild(item)));
return;
}
void MainWindow::on_treeWidget_itemSelectionChanged()
{
ui->plainTextEdit->appendPlainText(QString("itemSelectionChanged"));
return;
}
QTreeWidgetItem簡介
QTreeWidget元件的表頭和目錄樹節點都是QTreeWidgetItem類物件,對目錄樹節點的操作主要透過QTreeWidgetItem類的介面函式實現.
QTreeWidgetItem類沒有父類,它只用來儲存結點的資料和各種屬性.繪製目錄樹由QTreeWidget實現.
QTreeWidgetItem類有多種引數形式的建構函式,較簡單的一種定義如下:
- QTreeWidgetItem(int type=Type)
可以傳遞一個整數表示結點的型別,可以透過成員函式type()返回這個型別.
在建立節點時,還可以傳遞字串列表作為節點各列的文字:
- QTreeWidgetItem(const QStringList &strings,int type=Type)
也可以在某個節點下建立子節點:
- QTreeWidgetItem(QTreeWidgetItem *parent,int type=Type)
還可以直接在樹形元件裡建立頂層節點:
- QTreeWidgetItem(QTreeWidget *parent,int type=Type)
建立一個節點後,可以透過一些函式對其進行操作:
- void setBackground(int column,const QBrush &brush)
- void setForeground(int column,const QBrush &brush)
- void setText(int column,const QString &text)
- void setTextAlignment(int column,const QString &toolTip)
- void setStatusTip(int column,const QString &statusTip)
- void setIcon(int column,const QIcon &icon)
- void setCheckState(int column,Qt::CheckState state)
- void setFont(int column,const QFont &font)
Qt::Alignment的取值有:
- Qt::AlignLeft:水平方向靠左
- Qt::AlignRight:水平方向靠右
- Qt::AlignTop:垂直方向靠頂部
- Qt::AlignButton:垂直方向靠底部
- Qt::AlignHCenter:水平方向居中
- Qt::AlignVCenter:垂直方向居中
- Qt::AlignCenter:水平垂直方向居中
- Qt::AlignJustify:水平方向調整間距兩端對齊
上面設定函式當然有相應的讀取函式,同樣需要傳遞引數column.
QTreeWidgetItem還有一個函式setData()用於為節點中的某一列設定使用者資料,這個資料是不顯示在介面上的.
- void setData(int column,int role,const QVariant &value)
- QVariant data(int column,int role)
引數role是使用者資料角色,可以使用常量Qt::UserRole定義第一個使用者資料,使用Qt::UserRole+1定義第二個使用者資料.
使用者資料是QVariant型別,可以儲存各種型別的資料.
QTreeWidgetItem的一些常用的介面函式有:
- int type()//返回建立節點時設定的type
- setFlags(Qt::ItemFlags flags)//設定結點的標誌
- Qt::ItemFlags flags()//讀取節點的標誌
- void setExpanded(bool expand)
- bool isExpanded()
- void setDisabled(bool disabled)
- bool isDisabled()
- void setHidden(bool hide)
- bool isHidden()
- void setSelected(bool select)
- bool isSelected()
注意,函式type()所返回的是建立節點時傳遞的type引數,節點建立後就不能更改.
Qt::ItemFlags的取值有:
- Qt::NoItemFlags//沒有標誌
- Qt::ItemIsSelectable//節點可以被選中
- Qt::ItemIsEditable//節點可以編輯
- Qt::ItemIsDragEnabled//節點可以被拖動
- Qt::ItemIsDropEnabled//節點可以接收被拖動的物件
- Qt::ItemIsUserCheckable//節點可以被複選
- Qt::ItemIsEnabled//節點可用
- Qt::ItemIsAutoTristate//自動決定三種複選狀態
- Qt::ItemIsUserTristate//使用者決定三種複選狀態
- Qt::ItemNeverHasChildren//不允許有子節點
而且這些節點可以用|組合.
一個節點可以有任意多個子節點,可以新增,插入或移除節點.
QTreeWidgetItem類中用於操作子節點的介面函式主要有以下幾個:
- void addChild(QTreeWidgetItem *child)//新增一個子節點
- QTreeWidgetItem *child(int index)//根據序號返回一個子節點
- int childCount()//返回子節點的個數
- int indexOfChild(QTreeWidgetItem *child)//返回一個子節點的索引號
- void insertChild(int index,QTreeWidgetItem *child)//插入一個子節點
- void removeChile(QTreeWidget *child)//移除一個子節點
- QTreeWidgetItem *takeChild(int index)//移除一個子節點,並返回節點指標
- QTreeWidgetItem *parent()//返回父節點
QLabel和Qpixmap的使用
對於QPixmap類變數,QPixamp::load()直接從一個檔案載入圖片.
QPixmap類儲存圖片資料,它有以下幾個函式可以用於縮放圖片:
- scaledToHeight(int height):返回一個縮放後的圖片副本,圖片按height縮放
- scaledToWidth(int width):返回一個縮放後的圖片副本,圖片按width縮放
- scaled(int width,int height):返回一個縮放後的圖片副本,預設不保持比例
設定圖片到標籤的,函式原型為:void QLabel::setPixmap(const QPixmap&)
將標籤放在一個QScrollArea元件上,當圖片過大時,QScrollArea將會出現卷滾條.
QDockWidget的操作
程式執行時,視窗上的QDockWidget元件可以被拖動.
QDockWidget類有如下幾個訊號:
- void allowedAreasChanged(Qt::DockWidgetAreas allowedAreas)//allowedAreas屬性值變化時
- void dockLocationChanged(Qt::DockWidgetArea area)//移動到其他停靠區時
- void featuresChanged(QDockWidget::DockWidgetFeatures features)//features屬性變化時
- void topLevelChanged(bool topLevel)//floating屬性值變化時
- void visiblityChanged(bool visible)//visible屬性值變化時
下面最終給出綜合使用QTreeWidget與QPixmap的例子:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QSpinBox>
#include <QTreeWidgetItem>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void changeItemCaption(QTreeWidgetItem *item);
void displayImage(QTreeWidgetItem* item);
void on_actAddFolder_triggered();
void on_actAddFile_triggered();
void on_actDeleteNode_triggered();
void on_treeWidget_2_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
void on_actForeachNode_triggered();
void on_actSuitWidth_triggered();
void on_actSuitHeight_triggered();
void on_actReal_triggered();
void on_actBigger_triggered();
void on_actSmaller_triggered();
void on_actVisiable_triggered(bool checked);
void on_actFloating_triggered(bool checked);
private:
QLabel *lbFileName,*lbNodeText;
QSpinBox *spinRadio;
QPixmap m_pixmap;
float radio;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->treeWidget_2->clear();
//header
QTreeWidgetItem *header=new QTreeWidgetItem();
header->setText(0,"目錄與檔案");
header->setText(1,"節點型別");
header->setText(2,"最後修改日期");
header->setTextAlignment(0,Qt::AlignHCenter|Qt::AlignVCenter);
header->setTextAlignment(1,Qt::AlignHCenter|Qt::AlignVCenter);
ui->treeWidget_2->setHeaderItem(header);
//root node
QIcon icon(QString(":/icons/img/close.jpg"));
QTreeWidgetItem *topItem= new QTreeWidgetItem();
topItem->setIcon(0,icon);
topItem->setText(0,"/...");
topItem->setText(1,"根目錄");
topItem->setText(2,"");
topItem->setFlags(Qt::ItemIsSelectable|
Qt::ItemIsUserCheckable|
Qt::ItemIsEnabled|
Qt::ItemIsAutoTristate
);
topItem->setCheckState(0,Qt::Checked);
ui->treeWidget_2->addTopLevelItem(topItem);
//status bar
lbNodeText= new QLabel("節點標題",this);
lbNodeText->setMinimumWidth(200);
ui->statusbar->addWidget(lbNodeText);
spinRadio=new QSpinBox(this);
spinRadio->setRange(0,2000);
spinRadio->setValue(100);
spinRadio->setSuffix("%");
spinRadio->setReadOnly(true);
spinRadio->setButtonSymbols(QAbstractSpinBox::NoButtons);
ui->statusbar->addPermanentWidget(spinRadio);
lbFileName=new QLabel("檔名",this);
ui->statusbar->addPermanentWidget(lbFileName);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::changeItemCaption(QTreeWidgetItem *item)
{
QString str="*"+item->text(0);
item->setText(0,str);
if(item->childCount()>0)
for(int i=0;i<item->childCount();i++)
changeItemCaption(item->child(i));
else
return;
}
void MainWindow::displayImage(QTreeWidgetItem *item)
{
QString filename=item->data(0,Qt::UserRole).toString();
lbFileName->setText(filename);
lbNodeText->setText(item->text(0));
m_pixmap.load(filename);
ui->actSuitWidth->trigger();
ui->actSuitHeight->setEnabled(true);
ui->actSuitWidth->setEnabled(true);
ui->actBigger->setEnabled(true);
ui->actSmaller->setEnabled(true);
ui->actReal->setEnabled(true);
}
#include <QFileDialog>
#include <QVariant>
void MainWindow::on_actAddFolder_triggered()
{
QString dir= QFileDialog::getExistingDirectory();
if(dir.isEmpty())
return;
QTreeWidgetItem *parItem=ui->treeWidget_2->currentItem();
if(parItem==nullptr)
return;
if(parItem->text(1)!="圖片"){
int cnt=dir.length();
int i=dir.lastIndexOf("/");
QString nodeName=dir.right(cnt-i-1);
QTreeWidgetItem *item=new QTreeWidgetItem();
QIcon icon(QString(":/icons/img/close.jpg"));
item->setIcon(0,icon);
item->setText(0,nodeName);
item->setText(1,"目錄");
item->setText(2,"");
item->setFlags(Qt::ItemIsSelectable|
Qt::ItemIsUserCheckable|
Qt::ItemIsEnabled|
Qt::ItemIsAutoTristate
);
item->setData(0,Qt::UserRole,QVariant(dir));
item->setCheckState(0,Qt::Checked);
parItem->addChild(item);
}
}
void MainWindow::on_actAddFile_triggered()
{
QStringList files=QFileDialog::getOpenFileNames(this,"選擇檔案","","Images(*.jpg;*.png)");
if(files.isEmpty())
return;
QTreeWidgetItem *parItem,*item;
item=ui->treeWidget_2->currentItem();
if(item->text(1)!="圖片")
parItem=item;
else
parItem=item->parent();
for(int i=0;i<files.size();i++){
QString fileName= files.at(i);
QFileInfo fileInfo(fileName);
QString nodeText=fileInfo.fileName();
QDateTime dateTime=fileInfo.lastModified();
QTreeWidgetItem *item=new QTreeWidgetItem();
QIcon icon(fileInfo.filePath());
item->setIcon(0,icon);
item->setText(0,nodeText);
item->setText(1,"圖片");
item->setText(2,dateTime.toString("yyyy-MM-dd"));
item->setFlags(Qt::ItemIsSelectable|
Qt::ItemIsUserCheckable|
Qt::ItemIsEnabled|
Qt::ItemIsAutoTristate
);
item->setData(0,Qt::UserRole,QVariant(fileName));
item->setCheckState(0,Qt::Checked);
parItem->addChild(item);
}
parItem->setExpanded(true);
}
void MainWindow::on_actDeleteNode_triggered()
{
QTreeWidgetItem *item,*parItem;
item=ui->treeWidget_2->currentItem();
parItem=item->parent();
if(item!=nullptr){
parItem->removeChild(item);
delete item;
}
else
return;
}
void MainWindow::on_treeWidget_2_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
if(current==nullptr||current==previous)
return;
QString itemType=current->text(1);
if(itemType=="根目錄"){
ui->actAddFile->setEnabled(true);
ui->actAddFolder->setEnabled(true);
ui->actDeleteNode->setEnabled(false);
}
else if(itemType=="目錄"){
ui->actAddFile->setEnabled(true);
ui->actAddFolder->setEnabled(true);
ui->actDeleteNode->setEnabled(true);
}
else if(itemType=="圖片"){
ui->actAddFile->setEnabled(false);
ui->actAddFolder->setEnabled(true);
ui->actDeleteNode->setEnabled(true);
displayImage(current);
}
}
void MainWindow::on_actForeachNode_triggered()
{
QTreeWidgetItem *item,*parItem;
item=ui->treeWidget_2->currentItem();
changeItemCaption(item);
}
void MainWindow::on_actSuitWidth_triggered()
{
int width=ui->scrollArea->width()-30;
int realWidth=m_pixmap.width();
radio=float(width)/realWidth;
spinRadio->setValue(radio*100);
QPixmap pix=m_pixmap.scaledToWidth(width);
ui->label->setPixmap(pix);
}
void MainWindow::on_actSuitHeight_triggered()
{
int height=ui->scrollArea->height()-30;
int realHeight=m_pixmap.height();
radio=float(height)/realHeight;
spinRadio->setValue(radio*100);
QPixmap pix=m_pixmap.scaledToHeight(height);
ui->label->setPixmap(pix);
}
void MainWindow::on_actReal_triggered()
{
int height=ui->scrollArea->height()-30;
int realHeight=m_pixmap.height();
radio=float(height)/realHeight;
spinRadio->setValue(radio*100);
QPixmap pix=m_pixmap.scaledToHeight(realHeight);
ui->label->setPixmap(pix);
}
void MainWindow::on_actBigger_triggered()
{
radio*=1.2;
int width=radio*m_pixmap.width();
int height=radio*m_pixmap.height();
ui->label->setPixmap(m_pixmap.scaled(width,height));
spinRadio->setValue(radio*100);
}
void MainWindow::on_actSmaller_triggered()
{
radio*=0.8;
int width=radio*m_pixmap.width();
int height=radio*m_pixmap.height();
ui->label->setPixmap(m_pixmap.scaled(width,height));
spinRadio->setValue(radio*100);
}
void MainWindow::on_actVisiable_triggered(bool checked)
{
ui->dockWidget_2->setVisible(checked);
}
void MainWindow::on_actFloating_triggered(bool checked)
{
ui->dockWidget_2->setFloating(checked);
}
QTableWidget
QTableWidget是QTableView的便利類,類QTableWidget的屬性和介面主要是父類中定義的.
QTableWidget還新增了兩個屬性,rowCount表示資料區行數,columnCount表示資料區列數.
QTableWidget還定義瞭如下的幾個公有槽函式:
- void insertColumn(int column)//在列號column處插入空行
- void removeColumn(int column)//移除列號column的一列
- void insertRow(int row)//在行號row處插入空行
- void removeRow(int row)//移除行號row的一行
QTableWidget表格的一個單元格通常關聯一個QTableWidgetItem物件.
要為表格的一個單元格設定項,一般是先建立一個QTableWidgetItem物件item,設定各種屬性,然後透過setItem()將其設定至某個單元格.其函式原型如下:
- void setItem(int row,int column,QTableWidgetItem *item)
要移除一個單元格關聯的項,可以使用含稅takeItem()來實現,其函式原型如下:
- QTableWidgetItem *takeItem(int row,int column)
函式takeItem會移除單元格關聯的項,並返回這個項的物件指標,但是不刪除這個物件.
QTableWidget定義了兩個公有槽:
- void clear()
- void clearContents()
QTableWidget表格資料區有一個當前單元格,也就是獲得輸入焦點的單元格.相關函式如下:
當前單元格關聯的QTableWidgetItem物件就是當前項,可以返回當前項的物件指標.也可以設定某個QTableWidgetItem物件為當前項,以改變當前單元格的位置.
- int currentRow()//返回當前單元格的行號
- int currentColumn()//返回當前單元格的列號
- void setCurrentCell(int row,int column)//透過行號和列號設定當前單元格位置
- QTableWidgetItem *currentItem()//返回當前項
- void setCurrentItem(QTableWidgetItem *item)//設定當前項,改變當前單元格位置
- QTableWidgetItem *item(int row,int column)//透過行號和列號返回項
- int row(const QTableWidgetItem *item)//返回一個項的行號
- int column(const QTableWidgetItem *item)//返回一個項的列號
- void setHorizontalHeaderItem(int column)//為某列設定項
- QTableWidgetItem *horizontalHeaderItem(int column)//返回column列的表頭項
- QTableWidgetItem *takeHorizontalHeaderItem(int column)//移除column列的表頭項
- void setHorizontalHeaderLabels(const QStringList &labels)
//使用字串列表的每一行作為水平表頭每一列的標題 - setVerticalHeaderItem(int row,QTableWidgetItem *item)//設定row的表頭項
- QTableWidgetItem *verticalHeaderItem(int row)//返回row的表頭項
- QTableWidgetItem *takeVerticalHeaderItem(int row)//移除row的表頭項
- void setVerticalHeaderLabels(const QStringList &labels)//用一個字串列表設定表頭標題
QTableWidget定義了較多的訊號:
- void cellActivated(int row,int column)//單元格被啟用時
- void cellChanged(int row,int column)//單元格的資料改變時
- void cellClicked(int row,int column)//在單元格上單擊滑鼠時
- void cellDoubleClicked(int row,int column)//在單元格上雙擊滑鼠時
- void cellEntered(int row,int column)//滑鼠移動到一個單元格上時
- void cellPressed(int row,int column)//在單元格上按下滑鼠左鍵或右鍵時
- void currentCellChanged(int currentRow,int currentColumn,int previousRow,int previousColumn)
//當前單元格發生切換時 - void itemActivated(QTableWidgetItem *item)//項被啟用時
- void itemChanged(QTableWidgetItem *item)//項內容改變時
- void itemClicked(QTableWidgetItem *item)//項被點選
- void itemDoubleClicked(QTableWidgetItem *item)//項被雙擊
- void itemEntered(QTableWidgetItem *item)//滑鼠移動到一個項上時
- void itemPressed(QTableWidgetItem *item)//在項上按下滑鼠左鍵或右鍵時
- void currentItemChanged(QTableWidgetItem *current,QTableWidgetItem *previous)
//當前項發生改變時 - void itemSelectionChanged()//選擇的項發生變化時
QTableWidgeItem關聯的每個單元格都需要關聯一個QTableWidgetItem物件.
QTableWidgetItem有多種引數形式的建構函式,其中的三種建構函式定義如下:
- QTableWidgetItem(const QIcon &icon,const QString &text,int type=Type)
- QTableWidgetItem(const QString &text,int type=Type)
- QTableWidgetItem(int type=Type)
建立QTableWidgetItem物件後,透過QTableWidget::setItem()函式可以將其設定為某個單元格的項.
QTableWidgetItem物件有一些介面函式用於設定項的特性:
- void setText(const QString &text)//設定單元格顯示文字
- void setTextAlignment(int alignment)//設定文字對其方式
- void setBackground(const QBrush &brush)//設定背景色
- void setForeground(const QBrush &brush)//設定前景色
- void setFont(const QFont &font)//設定字型
- void setIcon(const QIcon &icon)//設定圖示
- void setCheckState(Qt::CheckState state)//設定複選狀態
- void setToolTip(const QString &toolTip)//設定toolTip
- void setStatusTip(const QString &statusTip)//設定statusTip
- void setFlags(Qt::ItemFlags flags)//設定標誌
- void setData(int role,const QVariant &value)//設定資料
- int row()//返回項所在單元格行號
- int column()//返回項所在單元格的列號
- void setSelected(bool select)//設定項的選中狀態
- bool isSelected()//項是否被選中
- QTableWidget *tableWidget()//返回項所在的QTableWidget物件指標
後記:好長的一章,一章更比四章強( )