QT 是一个跨平台C++图形界面开发库,利用QT可以快速开发跨平台窗体应用程序,在QT中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率。
目前,QT开发中常用的基础组件有以下几种:
PushButton 按钮组件
LineEdit 单行输入组件
SpinBox 数值组件
HorizontalSlider 滑块条组件
LCDNumber 数码表与LCD屏幕
ComBox 下拉框组件
ProgressBar 进度条与定时器
DateTime 日期与时间组件
PlainTextEdit 多行文本框
RadioButton 单选框分组
如上方列表中提到的的组件,就是在开发中经常被使用的,这些组件我将通过一个个小案例,帮助大家理解组件的应用方式与应用场景。
PushButton 按钮组件: 在QT中任何组件都可以用两种创建方式,我们可以通过使用new
关键字动态创建按钮,也可以使用QT的图形化工具自动生成。
首先我们通过命令行的方式生成几个按钮,导入QPushButton
包,然后定义如下代码,通过调用connect()
可实现对特定按钮赋予特定的函数事件。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <iostream> #include <QPushButton> void Print () { std::cout << "hello lyshark" << std::endl; } MainWindow::MainWindow (QWidget *parent): QMainWindow (parent), ui (new Ui::MainWindow) { ui->setupUi (this ); QPushButton * btn = new QPushButton; btn->setParent (this ); btn->setText ("退出" ); btn->move (100 ,200 ); btn->resize (100 ,50 ); btn->setEnabled (true ); QPushButton * btn2 = new QPushButton ("触发信号" ,this ); btn2->setParent (this ); btn2->move (100 ,100 ); btn2->resize (100 ,50 ); this ->resize (500 ,400 ); this ->setWindowTitle ("我的窗体" ); this ->setFixedSize (1024 ,300 ); connect (btn,&QPushButton::clicked,this ,&QWidget::close); connect (btn2,&QPushButton::clicked,this ,&Print); } MainWindow::~MainWindow () { delete ui; }
LineEdit 单行输入组件: 单行输入框LineEdit()
组件用来输入一行文本内容,GroupBox()
组件用来实现分组,QString
类是String类的二次封装版,通过两者配合实现两个简单的数值转换器。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <iostream> #include <QString> #include <QPushButton> MainWindow::MainWindow (QWidget *parent): QMainWindow (parent), ui (new Ui::MainWindow) { ui->setupUi (this ); ui->NumberSum->setEnabled (false ); ui->lineEdit_hex->setEnabled (false ); ui->lineEdit_bin->setEnabled (false ); ui->NumberSum->setEchoMode (QLineEdit::Password); } MainWindow::~MainWindow () { delete ui; } void MainWindow::on_pushButton_clicked () { QString string_total; QString Number_One = ui->numberA->text (); QString Number_Two = ui->NumberB->text (); if (Number_One.length () == 0 || Number_Two.length () == 0 ) { ui->label_3->setText ("参数不能为空" ); } else { int number_int = Number_One.toInt (); float number_float = Number_Two.toFloat (); float total = number_int * number_float; string_total = string_total.sprintf ("%.2f" ,total); ui->NumberSum->setText (string_total); } } void MainWindow::on_pushButton_2_clicked () { QString str = ui->lineEdit->text (); int value = str.toUInt (); str = str.setNum (value,16 ); str = str.toUpper (); ui->lineEdit_hex->setText (str); str = str.setNum (value,2 ); str = QString::number (value,2 ); ui->lineEdit_bin->setText (str); }
如上我们学习总结了按钮组件与编辑框组件的使用,这两个组件组合起来可实现一个简单地页面登录验证界面,代码如下:
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QMessageBox> #include <QByteArray> #include <QSettings> #include <QCryptographicHash> QString m_user="admin" ; QString m_pswd="12345" ; int m_tryCount=0 ; QString MainWindow::encrypt (const QString &str) { QByteArray btArray; btArray.append (str); QCryptographicHash hash (QCryptographicHash::Md5) ; hash.addData (btArray); QByteArray resultArray =hash.result (); QString md5 =resultArray.toHex (); return md5; } void MainWindow::ReadString () { QString organization="UserDataBase" ; QString appName="onley" ; QSettings settings (organization,appName) ; bool saved=settings.value ("saved" ,false ).toBool (); m_user=settings.value ("Username" , "admin" ).toString (); QString defaultPSWD=encrypt ("12345" ); m_pswd=settings.value ("PSWD" ,defaultPSWD).toString (); if (saved) { ui->lineEdit_Username->setText (m_user); } ui->checkBox->setChecked (saved); } void MainWindow::WriteString () { QSettings settings ("UserDataBase" ,"onley" ) ; settings.setValue ("Username" ,m_user); settings.setValue ("PSWD" ,m_pswd); settings.setValue ("saved" ,ui->checkBox->isChecked ()); } MainWindow::MainWindow (QWidget *parent) :QMainWindow (parent),ui (new Ui::MainWindow) { ui->setupUi (this ); setFixedSize (this ->width (), this ->height ()); ui->lineEdit_Password->setEchoMode (QLineEdit::Password); ReadString (); } MainWindow::~MainWindow () { delete ui; } void MainWindow::on_pushButton_clicked () { QString user=ui->lineEdit_Username->text ().trimmed (); QString pswd=ui->lineEdit_Password->text ().trimmed (); QString encrptPSWD=encrypt (pswd); if ((user==m_user)&&(encrptPSWD==m_pswd)) { WriteString (); QMessageBox::critical (this ,"成功" ,"已登录" ); } else { m_tryCount++; if (m_tryCount>3 ) { QMessageBox::critical (this , "错误" , "输入错误次数太多,强行退出" ); this ->close (); } else { QMessageBox::warning (this , "错误提示" , "用户名或密码错误" ); } } }
SpinBox 数值组件: 该控件主要用于整数或浮点数的计数显示,与普通的LineEdit不同,该组件可以在前后增加特殊符号并提供了上下幅度的调整按钮,灵活性更强。
该组件有两个版本,SpinBox()
用于显示整数与单精度浮点数,DoubleSpinBox()
则是双精度浮点数,SpinBox有两个特殊参数,prefix
参数是在前方加入特殊符号,而suffix
则是在后方加入特殊符号。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <iostream> #include <QString> #include <QPushButton> MainWindow::MainWindow (QWidget *parent): QMainWindow (parent), ui (new Ui::MainWindow) { ui->setupUi (this ); ui->doubleSpinBox->setEnabled (false ); } MainWindow::~MainWindow () { delete ui; } void MainWindow::on_pushButton_3_clicked () { int x = ui->spinBox->value (); int y = ui->spinBox_2->value (); double total = x+y; ui->doubleSpinBox->setValue (total); QString label_value = ui->label_10->text (); ui->label_10->setNum (total); }
我们继续在SpinBox的基础上改进,如上代码中每次都需要点击计算按钮才能出结果,此时我们需求是实现当SpinBox
中的参数发生变化时自定的完成计算,这里就需要用到信号和槽了,当SpinBox被修改后,自动触发计算信号实现计算。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <iostream> #include <QString> #include <QPushButton> MainWindow::MainWindow (QWidget *parent): QMainWindow (parent), ui (new Ui::MainWindow) { ui->setupUi (this ); ui->doubleSpinBox->setEnabled (false ); QObject::connect (ui->spinBox,SIGNAL (valueChanged (int )),this ,SLOT (on_pushButton_clicked ())); QObject::connect (ui->spinBox_2,SIGNAL (valueChanged (int )),this ,SLOT (on_pushButton_clicked ())); QObject::connect (ui->doubleSpinBox,SIGNAL (valueChanged (double )),this ,SLOT (on_pushButton_clicked ())); } MainWindow::~MainWindow () { delete ui; } void MainWindow::on_pushButton_clicked () { int x = ui->spinBox->value (); int y = ui->spinBox_2->value (); double total = x+y; ui->doubleSpinBox->setValue (total); QString label_value = ui->label_10->text (); ui->label_10->setNum (total); }
HorizontalSlider 滑块条组件: 根据上面的SpinBox信号与槽函数的绑定,我们还可以将其绑定到滑块条组件上,如下代码实现了,当用户改变滑块条时,右侧的textEdit
的颜色也会发生相应的改变。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <iostream> #include <QString> #include <QPushButton> MainWindow::MainWindow (QWidget *parent): QMainWindow (parent), ui (new Ui::MainWindow) { ui->setupUi (this ); QObject::connect (ui->SliderRed,SIGNAL (valueChanged (int )),this ,SLOT (on_SliderRed_valueChanged (int ))); QObject::connect (ui->SliderGreen,SIGNAL (valueChanged (int )),this ,SLOT (on_SliderRed_valueChanged (int ))); QObject::connect (ui->SliderBlue,SIGNAL (valueChanged (int )),this ,SLOT (on_SliderRed_valueChanged (int ))); QObject::connect (ui->SliderAlpha,SIGNAL (valueChanged (int )),this ,SLOT (on_SliderRed_valueChanged (int ))); } MainWindow::~MainWindow () { delete ui; } void MainWindow::on_SliderRed_valueChanged (int value) { Q_UNUSED (value); QColor color; int R=ui->SliderRed->value (); int G=ui->SliderGreen->value (); int B=ui->SliderBlue->value (); int alpha=ui->SliderAlpha->value (); color.setRgb (R,G,B,alpha); QPalette pal=ui->textEdit->palette (); pal.setColor (QPalette::Base,color); ui->textEdit->setPalette (pal); }
数码表与LCD屏幕: 这是两个比较有趣的组件,如下布局中圆形的是dial
组件,其右侧则是一个LCD Number
组件,两者可以灵活的结合在一起使用,当拨动齿轮时自动影响LCD数码屏幕的显示。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <iostream> #include <QString> #include <QPushButton> #include <QRadioButton> MainWindow::MainWindow (QWidget *parent): QMainWindow (parent), ui (new Ui::MainWindow) { ui->setupUi (this ); } MainWindow::~MainWindow () { delete ui; } void MainWindow::on_dial_valueChanged (int value) { ui->LCDDisplay->display (value); } void MainWindow::on_radioBtnDec_clicked () { ui->LCDDisplay->setDigitCount (3 ); ui->LCDDisplay->setDecMode (); } void MainWindow::on_radioBtnBin_clicked () { ui->LCDDisplay->setDigitCount (8 ); ui->LCDDisplay->setBinMode (); } void MainWindow::on_radioBtnOct_clicked () { ui->LCDDisplay->setDigitCount (5 ); ui->LCDDisplay->setOctMode (); } void MainWindow::on_radioBtnHex_clicked () { ui->LCDDisplay->setDigitCount (3 ); ui->LCDDisplay->setHexMode (); }
CheckBox 多选框: 多选框CheckBox
组件也是最常用的组件,多选框支持三态选择,选中半选中和未选中状态。
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow (QWidget *parent) :QMainWindow (parent),ui (new Ui::MainWindow) { ui->setupUi (this ); ui->checkBox->setTristate (); ui->checkBox->setEnabled (true ); } MainWindow::~MainWindow () { delete ui; } void MainWindow::on_checkBox_stateChanged (int state) { if (state == Qt::Checked) { ui->checkBox->setText ("选中" ); } else if (state == Qt::PartiallyChecked) { ui->checkBox->setText ("半选" ); } else { ui->checkBox->setText ("未选中" ); } } void MainWindow::on_pushButton_clicked () { int check = ui->checkBox->isCheckable (); if (check == 1 ) { ui->checkBox->setChecked (false ); } } void MainWindow::on_checkBox_master_stateChanged (int state) { if (state == Qt::Checked) { ui->checkBox_sub_a->setChecked (true ); ui->checkBox_sub_b->setChecked (true ); } if (state == Qt::Unchecked) { ui->checkBox_sub_a->setChecked (false ); ui->checkBox_sub_b->setChecked (false ); } }
ComBox 下拉框组件: 该组件提供了下拉列表供用户选择,ComBox组件除了可以显示下拉列表外,每个项还可以关联一个QVariant类型的变量用于存储不可见数据。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <iostream> #include <QList> #include <QMap> QMap<QString,int > City_Zone; QMap<QString,QList <QString>> map ; QList<QString> tmp; MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) { ui->setupUi(this); ui->comboBox_main->clear(); QIcon icon; icon.addFile(":/image/1.ico" ); for (int x=0 ;x<10 ;x++) { ui->comboBox_main->addItem(icon,QString::asprintf("元素_%d" ,x)); } ui->comboBox_main->clear(); QStringList str; str << "北京" << "上海" << "广州" ; ui->comboBox_main->addItems(str); ui->comboBox_main->setItemIcon(0 ,QIcon(":/image/1.ico" )); ui->comboBox_main->setItemIcon(1 ,QIcon(":/image/2.ico" )); ui->comboBox_main->setItemIcon(2 ,QIcon(":/image/3.ico" )); ui->comboBox_main->clear(); City_Zone.insert("请选择" ,0 ); City_Zone.insert("北京" ,1 ); City_Zone.insert("上海" ,2 ); City_Zone.insert("广州" ,3 ); ui->comboBox_main->clear(); foreach(const QString &str,City_Zone.keys()) { ui->comboBox_main->addItem(QIcon(":/image/1.ico" ),str,City_Zone.value(str)); } tmp.clear(); tmp << "大兴区" << "昌平区" << "东城区" ; map ["北京" ] = tmp; tmp.clear(); tmp << "黄浦区" << "徐汇区" << "长宁区" << "杨浦区" ; map ["上海" ] = tmp; tmp.clear(); tmp << "荔湾区" << "越秀区" ; map ["广州" ] = tmp; ui->comboBox_main->setCurrentIndex(3 ); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked () { QString one = ui->comboBox_main->currentText(); QString two = ui->comboBox_submain->currentText(); std ::cout << one.toStdString().data() << " | " << two.toStdString().data() << std ::endl ; } void MainWindow::on_comboBox_main_currentTextChanged (const QString &arg1) { ui->comboBox_submain->clear(); QList<QString> qtmp; qtmp = map .value(arg1); for (int x=0 ;x<qtmp.count();x++) { ui->comboBox_submain->addItem(QIcon(":/image/2.ico" ),qtmp[x]); } }
ProgressBar 进度条与定时器: 进度条ProgressBar
组件通常会结合QTimer
定时器组件共同使用,首先我们需要设置一个时钟周期,定时器每经过一定的时间周期则执行对变量或进度条的递增操作,由此实现进度条动态输出效果。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QTimer> QTimer *my_timer; MainWindow::MainWindow (QWidget *parent): QMainWindow (parent), ui (new Ui::MainWindow) { ui->setupUi (this ); ui->progressBar->setValue (0 ); ui->progressBar_2->setValue (100 ); my_timer = new QTimer (this ); connect (my_timer,&QTimer::timeout,[=]{ static int x = 0 ; if (x != 100 ) { x++; ui->progressBar->setValue (x); ui->progressBar_2->setValue (int (100 -x)); } else { x=0 ; my_timer->stop (); } }); } MainWindow::~MainWindow () { delete ui; } void MainWindow::on_pushButton_clicked () { if (my_timer->isActive () == false ) { my_timer->start (100 ); } } void MainWindow::on_pushButton_2_clicked () { if (my_timer->isActive () == true ) { my_timer->stop (); } } void MainWindow::on_pushButton_3_clicked () { ui->progressBar->setValue (0 ); ui->progressBar_2->setValue (100 ); }
DateTime 日期与时间组件: 时间组件中包括了可以显示时间的QTime
显示日期的QDate
以及可同时显示时间与日期的QDateTime
这三种组件,三种组件的使用上几乎一致,如下代码是开发中最常用的总结。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDateTime> MainWindow::MainWindow (QWidget *parent): QMainWindow (parent), ui (new Ui::MainWindow) { ui->setupUi (this ); } MainWindow::~MainWindow () { delete ui; } void MainWindow::on_pushButton_clicked () { QDateTime curDateTime = QDateTime::currentDateTime (); ui->timeEdit->setTime (curDateTime.time ()); ui->dateEdit->setDate (curDateTime.date ()); ui->dateTimeEdit->setDateTime (curDateTime); ui->lineEdit->setText (curDateTime.toString ("yyyy-MM-dd hh:mm:ss" )); } void MainWindow::on_pushButton_2_clicked () { QString str = ui->lineEdit_2->text (); str = str.trimmed (); if (!str.isEmpty ()) { QDateTime datetime = QDateTime::fromString (str,"yyyy-MM-dd hh:mm:ss" ); ui->dateTimeEdit_string_to_datetime->setDateTime (datetime); } }
PlainTextEdit 多行文本框: 多行文本编辑器,用于显示和编辑多行简单文本,如下代码左侧PlainTextEdit
中输入数据(每行换行)点击按钮后自动将左侧数据放入右侧的listView
组件中。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QLabel> #include <QTextBlock> #include <iostream> #include <QStringListModel> MainWindow::MainWindow (QWidget *parent): QMainWindow (parent), ui (new Ui::MainWindow) { ui->setupUi (this ); QStatusBar * stBar = statusBar (); setStatusBar (stBar); QLabel * label = new QLabel ("左侧提示信息" ,this ); stBar->addWidget (label); QLabel * label2 = new QLabel ("右侧提示信息" ,this ); stBar->addPermanentWidget (label2); } MainWindow::~MainWindow () { delete ui; } void MainWindow::on_pushButton_clicked () { QTextDocument* doc = ui->plainTextEdit->document (); int count = doc->blockCount (); QStringList data; QStringListModel *model; for (int x=0 ;x< count;x++) { QTextBlock textLine = doc->findBlockByNumber (x); QString str = textLine.text (); data << str; } model = new QStringListModel (data); ui->listView->setModel (model); }
RadioButton 单选框分组: 单选框是最常用的组件,在一个界面中可以有多种单选框,每种单选框都会对应一个问题,此实我们需要使用ButtonGroup
组件对单选框进行分组,并通过信号和槽函数相互绑定,从而实现对用户的多种选择进行判断。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QButtonGroup> #include <iostream> QButtonGroup *group_sex; QButtonGroup *group_hobby; MainWindow::MainWindow (QWidget *parent): QMainWindow (parent), ui (new Ui::MainWindow) { ui->setupUi (this ); group_sex = new QButtonGroup (this ); group_sex->addButton (ui->radioButton_male,0 ); group_sex->addButton (ui->radioButton_female,1 ); group_sex->addButton (ui->radioButton_unknown,2 ); ui->radioButton_unknown->setChecked (true ); group_hobby = new QButtonGroup (this ); group_hobby->addButton (ui->radioButton_eat,3 ); group_hobby->addButton (ui->radioButton_drink,4 ); group_hobby->addButton (ui->radioButton_sleep,5 ); ui->radioButton_eat->setChecked (true ); connect (ui->radioButton_male,SIGNAL (clicked (bool )),this ,SLOT (MySlots ())); connect (ui->radioButton_female,SIGNAL (clicked (bool )),this ,SLOT (MySlots ())); connect (ui->radioButton_unknown,SIGNAL (clicked (bool )),this ,SLOT (MySlots ())); } MainWindow::~MainWindow () { delete ui; } void MainWindow::MySlots () { switch (group_sex->checkedId ()) { case 0 : std::cout << "male" << std::endl; break ; case 1 : std::cout << "female" << std::endl; break ; case 2 : std::cout << "unknown" << std::endl; break ; } }