2.5 控件
2.5.1 按钮组
Qt的按钮控件的种类很多,有QPushButton(按钮),QToolButton(工具按钮),QRadioButton(单选按钮),QCheckBox(复选框),Command Link Button(命令链接按钮),QDialogButtonBox(对话框按钮)
实际上我们可以在Qt Creator的UI设计器界面看到按钮组的这些控件

对这些控件的解释如下
Push Button:按钮
Tool Button:工具按钮
Radio Button:单选按钮
Check Box:复选框
Command Link Button:命令链接按钮
Dialog Button Box:对话框按钮
2.5.1.1 我们通过一个简单的案例来学习一下这些按钮控件的使用
2.5.1.1.1 我们用到了控件了,因此我们需要建立Qt Widget Application






2.5.1.1.2 在qbuttonsdemo.h中写以下内容
#ifndef QBUTTONSDEMO_H #define QBUTTONSDEMO_H #include<QDebug> #include<QMenu> #include<QWidget> #include<QDialog> //1.在qbuttonsdemo.h中加入如下的头文件 #include<QPushButton>//按钮对应的类 #include<QToolButton>//工具按钮对应的类 #include<QRadioButton>//单选按钮对应的类 #include<QCheckBox>//复选框按钮对应的类 #include<QCommandLinkButton>//命令链接按钮对应的类 #include<QDialogButtonBox>//对话框按钮 class QButtonsDemo : public QWidget { Q_OBJECT public: QButtonsDemo(QWidget *parent = nullptr); ~QButtonsDemo(); //2.定义这些按钮的对象指针 private: QPushButton*push_btn;//按钮对象指针 QToolButton*tool_btn;//工具按钮对象指针 QRadioButton*radio_btn;//单选框按钮对象指针 QCheckBox*checkbox_btn;//复选框按钮对象指针 QCommandLinkButton*commandlink_btn;//命令链接按钮对象指针 QDialogButtonBox*dialog_btn;//对话框按钮对象指针 //3.如果我们需要在点击某些按钮之后产生一些反应,那么就需要用到信号和槽函数了,这些控件本身也内置了一些信号函数 //但槽函数需要我们自己实现 private slots: ///1.1 我们先来看看对于一般都PushButton有哪些可用的方法 ///我们知道对于一个QPushButton至少有这样几种信号函数(clicked(),pressed(),released()) void on_clicked_pushbutton();//我们这个槽函数是模拟点击一下pushbutton后会发生什么 void on_pressed_pushbutton();//我们按住pushbutton会调用此槽函数 void on_released_pushbutton();//当我们松开pushbutton时调用此槽函数 ///1.2 对于ToolButton来说,也有这些对应的方法 /// clicked(),pressed(),released() void on_clicked_toolbutton(); void on_pressed_toolbutton(); void on_released_toolbutton(); ///1.3 对于RadioButton来说,也有这些方法,只不过常用的有一个叫做toggled的方法 /// clicked(),pressed(),released() void on_clicked_radiobutton(); void on_pressed_radiobutton(); void on_released_radiobutton(); void on_toggled_radiobutton(bool checked); ///1.4 对于CheckBox来说,也有这些对应的方法(特别是toggled()方法) /// clicked(),pressed(),released() void on_clicked_checkbox(); void on_pressed_checkbox(); void on_released_checkbox(); void on_toggled_checkbox(bool checked); ///1.5 对于CommandLinkButton来说,也有这些方法(因为Button类基本上都是以QAbstractButton为基类的) ///clicked(),pressed(),released() /// CommandLinkButton没有toggled信号,因为其本身不具有类似CheckBox的特性 void on_clicked_commandlinkbutton(); void on_pressed_commandlinkbutton(); void on_released_commandlinkbutton(); ///1.6 对于DialogButtonBox来说,则又有其独特的信号函数 /// 1.6.1 accepted() /// 对于accepted这个信号,它支持这些枚举类型的DialogButtonBox ///Ok,Open,Save,Apply,SaveAll /// 1.6.2 clicked() /// 普通的clicked(QAbstractButton*)信号,所有的枚举均支持(它返回是哪一个具体的QDialogButtonBox被点击 void on_clicked_dialogbuttonbox(QAbstractButton*button); /// 1.6.3 helpRequested() /// 对于helpRequested()信号,它至少支持QDialogButtonBox::Help枚举 /// 1.6.4 rejected() /// 对于此信号,至少支持Cancel,Close这两种枚举 void on_accepted_dialogbuttonbox(); void on_helpRequested_dialogbuttonbox(); void on_rejected_dialogbuttonbox(); ///注:对于QDialogButtonBox的信号所支持的具体的按钮对应的枚举可以在文档中查阅到 private: void BindAllSignalAndSlots();//这个函数方便我们绑定所有的信号和槽函数 }; #endif // QBUTTONSDEMO_H
2.5.1.1.3 在qbuttonsdemo.cpp中写如下代码
#include"qbuttonsdemo.h" QButtonsDemo::QButtonsDemo(QWidget *parent):QWidget(parent) { this->setMaximumSize(QSize(500,200));//设置当前窗口最大尺寸 this->setMinimumSize(QSize(500,200));//设置当前窗口最小尺寸 //QPushButton this->push_btn = new QPushButton(tr("PushButton"),this);//new一个PushButton对象,以this作为其父窗口 this->push_btn->setGeometry(30,30,120,60);//设置该按钮的位置,尺寸 //QToolButton this->tool_btn = new QToolButton(this);//new一个toolButton对象,以this作为父窗口 this->tool_btn->setText(tr("ToolButton"));//设置toolbutton的显示文字 this->tool_btn->setGeometry(160,30,60,50);//设置该toolbutton的位置,尺寸 //QRadioButton this->radio_btn = new QRadioButton("RadioButton",this);//new一个RadioButton对象 this->radio_btn->setGeometry(230,30,100,60);//设置RadioButton的位置,尺寸 //QCheckBox this->checkbox_btn = new QCheckBox(tr("CheckBox"),this);//new一个复选框按钮对象 this->checkbox_btn->setGeometry(80,120,90,40);//设置位置尺寸 //QCommandLinkButton this->commandlink_btn = new QCommandLinkButton("CommandLinkButton","命令链接按钮",this);//new一个命令链接按钮对象 this->commandlink_btn->setGeometry(40,120,30,30);//设置尺寸 //QDialogButtonBox this->dialog_btn = new QDialogButtonBox(QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Yes|QDialogButtonBox::No,this);//new一个对话框按钮对象 this->dialog_btn->setGeometry(200,120,230,80);//设置尺寸 ///一次性绑定所有的控件对应的信号和槽函数 BindAllSignalAndSlots(); } //一次性绑定所有的信号和槽函数 void QButtonsDemo::BindAllSignalAndSlots() { //1.为PushButton绑定这三种信号及其对应的槽函数 connect(this->push_btn,SIGNAL(clicked()),this,SLOT(on_clicked_pushbutton())); connect(this->push_btn,SIGNAL(pressed()),this,SLOT(on_pressed_pushbutton())); connect(this->push_btn,SIGNAL(released()),this,SLOT(on_released_pushbutton())); //2.为ToolButton绑定这三种信号以及对应的槽函数 connect(this->tool_btn,SIGNAL(clicked()),this,SLOT(on_clicked_toolbutton())); connect(this->tool_btn,SIGNAL(pressed()),this,SLOT(on_pressed_toolbutton())); connect(this->tool_btn,SIGNAL(released()),this,SLOT(on_released_toolbutton())); //3.为RadioButton绑定这四种信号和槽 connect(this->radio_btn,SIGNAL(clicked()),this,SLOT(on_clicked_radiobutton())); connect(this->radio_btn,SIGNAL(pressed()),this,SLOT(on_pressed_radiobutton())); connect(this->radio_btn,SIGNAL(released()),this,SLOT(on_released_radiobutton())); connect(this->radio_btn,SIGNAL(toggled(bool)),this,SLOT(on_toggled_radiobutton(bool))); //这种带参数的信号在绑定时,只需要告诉其参数的类型即可,不需要写上具体的形参名称(哑元) //4.为CheckBox绑定四种信号对应的槽函数 connect(this->checkbox_btn,SIGNAL(clicked()),this,SLOT(on_clicked_checkbox())); connect(this->checkbox_btn,SIGNAL(pressed()),this,SLOT(on_pressed_checkbox())); connect(this->checkbox_btn,SIGNAL(released()),this,SLOT(on_released_checkbox())); connect(this->checkbox_btn,SIGNAL(toggled(bool)),this,SLOT(on_toggled_checkbox(bool))); //5.为CommandLinkButton绑定三种信号对应的槽函数 connect(this->commandlink_btn,SIGNAL(clicked()),this,SLOT(on_clicked_commandlinkbutton())); connect(this->commandlink_btn,SIGNAL(pressed()),this,SLOT(on_pressed_commandlinkbutton())); connect(this->commandlink_btn,SIGNAL(released()),this,SLOT(on_released_commandlinkbutton())); //6.为DialogButtonBox绑定这四种信号与之对应的槽函数 connect(this->dialog_btn,SIGNAL(accepted()),this,SLOT(on_accepted_dialogbuttonbox())); connect(this->dialog_btn,SIGNAL(helpRequested()),this,SLOT(on_helpRequested_dialogbuttonbox())); connect(this->dialog_btn,SIGNAL(rejected()),this,SLOT(on_rejected_dialogbuttonbox())); connect(this->dialog_btn,SIGNAL(clicked(QAbstractButton*)),this,SLOT(on_clicked_dialogbuttonbox(QAbstractButton*))); } QButtonsDemo::~QButtonsDemo() { delete this->push_btn; delete this->tool_btn; delete this->radio_btn; delete this->checkbox_btn; delete this->dialog_btn; delete this->commandlink_btn; } //1.1 当我们点击了PushButton后调用此函数 void QButtonsDemo::on_clicked_pushbutton() { qDebug()<<"点击了PushButton"; } //1.2 当我们按住pushbutton后会调用此函数 void QButtonsDemo::on_pressed_pushbutton() { qDebug()<<"按住了PushButton"; } //1.3 当我们松开pushbutton时调用此槽函数 void QButtonsDemo::on_released_pushbutton() { qDebug()<<"松开PushButton"; } //2.1 当点击了toolbutton时会调用此函数 void QButtonsDemo::on_clicked_toolbutton() { qDebug()<<"点击ToolButton"; } //2.2 当按住toolbutton时也会调用此函数 void QButtonsDemo::on_pressed_toolbutton() { qDebug()<<"按住了ToolButton"; } //2.3 当松开toolbutton时会调用此函数 void QButtonsDemo::on_released_toolbutton() { qDebug()<<"松开ToolButton"; } //3.1 点击RadioButton时,调用此函数 void QButtonsDemo::on_clicked_radiobutton() { qDebug()<<"点击了RadioButton"; } //3.2 按住RadioButton时,调用此函数 void QButtonsDemo::on_pressed_radiobutton() { qDebug()<<"按下RadioButton"; } //3.3 松开RadioButton时,调用此函数 void QButtonsDemo::on_released_radiobutton() { qDebug()<<"松开RadioButton"; } //3.4 当单选框的选中状态改变时,调用此函数 void QButtonsDemo::on_toggled_radiobutton(bool checked) { //该函数的形参就是用于描述复选框的状态的 qDebug()<<checked; } //4.1 当CheckBox被点击时,调用此函数 void QButtonsDemo::on_clicked_checkbox() { qDebug()<<"CheckBox被点击了"; } //4.2 当CheckBox被按住时,调用此函数 void QButtonsDemo::on_pressed_checkbox() { qDebug()<<"CheckBox被按下了"; } //4.3 当CheckBox被松开时,调用此函数 void QButtonsDemo::on_released_checkbox() { qDebug()<<"CheckBox被松开"; } //4.4 当CheckBox的状态被改变时,调用此函数并可以通过形参获取到其状态 void QButtonsDemo::on_toggled_checkbox(bool checked) { qDebug()<<checked; } //5.1 当CommandLinkButton被点击时,调用此槽函数 void QButtonsDemo::on_clicked_commandlinkbutton() { qDebug()<<"CommandLinkButton被点击了"; qDebug()<<this->commandlink_btn->description();//可以获取到该命令链接按钮的描述 } //5.2 当CommandLinkButton被按住时,调用此函数 void QButtonsDemo::on_pressed_commandlinkbutton() { qDebug()<<"CommandLinkButton被按下"; } //5.3 当CommandLinkButton被松开时,调用此函数 void QButtonsDemo::on_released_commandlinkbutton() { qDebug()<<"CommandLinkButton被松开"; } //6.1 当点击支持Accepted信号所支持的枚举按钮时,会调用函数 void QButtonsDemo::on_accepted_dialogbuttonbox() { qDebug()<<"DialogButtonBox的Accepted被触发"; } //6.2 点击支持helpRequested()信号支持的枚举时,调用此函数 void QButtonsDemo::on_helpRequested_dialogbuttonbox() { qDebug()<<"DialogButtonBox的HelpRequested被触发"; } //6.3 点击支持rejected()信号支持的枚举时,调用此函数 void QButtonsDemo::on_rejected_dialogbuttonbox() { qDebug()<<"DialogButtonBox的Reject被触发"; } //6.4 对于DialogButtonBox的一切种类的按钮,都会触发clicked()信号 void QButtonsDemo::on_clicked_dialogbuttonbox(QAbstractButton*button) { qDebug()<<button; qDebug()<<"DialogButtonBox的clicked()被触发"; }
运行效果:

2.5.2 输入控件组(Input Widgets)
2.5.2.1 相关的输入控件

ComboBox:组合框
FontComboBox:字体组合框
LineEdit:行编辑框
TextEdit:文本编辑框
PlainTextEdit:纯文本编辑框
SpinBox:单自旋盒
DoubleSpinBox:双自旋盒
TimeEdit:时间编辑器
DateEdit:日期编辑器
DateTimeEdit:日期时间编辑器
Dial:拨号器
HorizontalScrollBar:水平滚动条
VerticalScrollBar:垂直滚动条
HorizontalSlider:水平滑块
VerticalSlider:垂直滑块
KeySequenceEdit:关键字序列编辑框
2.5.2.2 仍然是创建Qt Widget Application,不要创建UI界面,将类名命名为InputWidgetsDemo
在inputwidgetsdemo.h中输入以下代码
#ifndef INPUTWIDGETSDEMO_H #define INPUTWIDGETSDEMO_H #include<QDebug> #include<QMainWindow> //1.Qt中除了我们刚刚讲的QPushButton,QToolButton,QDialogButtonBox,QCommandLinkButton,QCheckBox,QRadioButton //这些按钮控件之外,还有一些常用的输入控件:ComboBox,FontComboBox,LineEdit,TextEdit,PlainTextEdit,SpinBox, //DoubleSpinBox,TimeEdit,DateEdit,DateTimeEdit,Dial,HorizontalScrollBar,VerticalScrollBar //HorizontalSlider,VerticalSlider,KeySequenceEdit //2.我们来加入这些控件对应的头文件来看看它们 #include<QComboBox>//组合框 #include<QFontComboBox>//字体组合框 #include<QLineEdit>//行编辑框 #include<QTextEdit>//文本编辑框(这个框是支持非纯文本内容的) #include<QPlainTextEdit>//纯文本编辑框(这个编辑框只能显示文本内容) #include<QSpinBox>//自旋盒(用于选择一位数字的自旋盒)0~9 #include<QDoubleSpinBox>//双自选盒(可以支持浮点数的选择)0.0~9.9 #include<QTimeEdit>//时间编辑框 #include<QDateEdit>//日期编辑框 #include<QDateTimeEdit>//时间和日期编辑框 #include<QDial>//拨码盘(类似于上个世纪的那种拨码电话的拨码盘) #include<QScrollBar>//滚动条(这个本身是没有垂直滚动条和水平滚动的说法的,但是可以根据枚举来指定这个Scrollbar是垂直还是水平的 #include<QSlider>//进度滑条(这个同样可以通过枚举来指定这是垂直的滑动条还是水平的滑动条) #include<QKeySequenceEdit>//按键序列编辑框 class InputWidgetsDemo : public QMainWindow { Q_OBJECT public: InputWidgetsDemo(QWidget *parent = nullptr); ~InputWidgetsDemo(); private: QComboBox*combo_box;//组合框 QFontComboBox*fontcombo_box;//字体组合框 QLineEdit*line_edit;//行编辑框 QTextEdit*text_edit;//文本编辑框 QPlainTextEdit*plaintext_edit;//纯文本编辑框 QSpinBox*spin_box;//单自旋盒 QDoubleSpinBox*doublespin_box;//双自旋盒 QTimeEdit*time_edit;//时间编辑器 QDateEdit*date_edit;//日期编辑器 QDateTimeEdit*datetime_edit;//日期时间编辑器 QDial*dial;//拨号器 QScrollBar*horizontal_bar;//水平滚动条 QScrollBar*vertical_bar;//垂直滚动条 QSlider*horizontal_slider;//垂直滑块 QSlider*vertical_slider;//水平滑块 QKeySequenceEdit*keysequence_edit;//按键序列编辑框 }; #endif // INPUTWIDGETSDEMO_H
在inputwidgetsdemo.cpp中输入以下代码
#include"inputwidgetsdemo.h" InputWidgetsDemo::InputWidgetsDemo(QWidget *parent):QMainWindow(parent) { //设置初始窗口的大小 this->setMaximumSize(QSize(500,600)); this->setMinimumSize(QSize(500,600)); //1.组合框 ///1.1 创建一个组合框对象 this->combo_box = new QComboBox(this); ///1.2 设置这个组合框的位置 this->combo_box->move(10,20); ///1.3 往这个组合框中添加一些条目 for(int i = 0;i<4;i++) { this->combo_box->insertItem(i,QString("条目%1").arg(i+1)); } //2.字体组合框 ///2.1 创建一个字体组合框对象 this->fontcombo_box = new QFontComboBox(this); ///2.2 设置这个字体组合框的位置 this->fontcombo_box->move(120,20); //3.行编辑框 ///3.1 创建一个行编辑框对象 this->line_edit = new QLineEdit(this); ///3.2 设置行编辑框的位置 this->line_edit->move(280,20); //4.文本编辑框 ///4.1 创建文本编辑框对象 this->text_edit = new QTextEdit(this); ///4.2 设置这个文本编辑框的大小 this->text_edit->resize(50,60); ///4.3 将这个文本编辑框的位置移动一下 this->text_edit->move(10,60); //5.纯文本编辑框 ///5.1 创建纯文本编辑框对象 this->plaintext_edit = new QPlainTextEdit(this); ///5.2 设置这个纯文本编辑框的大小 this->plaintext_edit->resize(50,60); ///5.3 移动这个纯文本编辑框的位置 this->plaintext_edit->move(120,60); //6.单自旋盒 ///6.1 创建单自旋盒对象 this->spin_box = new QSpinBox(this); ///6.2 移动这个单自旋盒的位置 this->spin_box->move(240,60); //7.双自旋盒 ///7.1 创建双自旋盒对象 this->doublespin_box = new QDoubleSpinBox(this); ///7.2 移动这个双自旋盒的位置 this->doublespin_box->move(360,60); ///7.3 设置这个双自旋盒的数字范围 this->doublespin_box->setRange(0.000,100.000); ///7.4 设置这个双自旋盒最大的精度(小数点后4位) this->doublespin_box->setDecimals(4); ///7.5 设置自增幅度 this->doublespin_box->setSingleStep(0.0001); //8.时间编辑器 ///8.1 创建时间编辑器对象(我这里可以通过构造函数指定初始状态显示的时间) this->time_edit = new QTimeEdit(QTime(QTime::currentTime()),this); ///8.2 移动这个时间编辑器的位置 this->time_edit->move(10,120); //9.日期编辑器 ///9.1 创建日期编辑器并默认显示为当前日期 this->date_edit = new QDateEdit(QDate::currentDate(),this); ///9.2 移动这个日期编辑器的位置 this->date_edit->move(120,120); //10.日期时间编辑器 //10.1 创建日期时间编辑器并默认显示为当前日期 this->datetime_edit = new QDateTimeEdit(QDateTime::currentDateTime(),this); //10.2 设置日期时间编辑器的位置 this->datetime_edit->move(240,120); //11.拨号器 ///11.1 创建一个拨号器对象 this->dial = new QDial(this); ///11.2 设置拨号器的位置 this->dial->move(320,120); //12.水平滚动条 ///12.1 创建水平滚动条(本来是没有水平滚动条的,因此我们只能通过枚举来设置) this->horizontal_bar = new QScrollBar(Qt::Orientation::Horizontal,this); ///12.2 设置位置 this->horizontal_bar->move(10,240); //13.垂直滚动条 ///13.1 创建垂直滚动条 this->vertical_bar = new QScrollBar(Qt::Orientation::Vertical,this); this->vertical_bar->move(120,240); //14.水平滑块 ///14.1 创建水平滑块(同样需要枚举来指定) this->horizontal_slider = new QSlider(Qt::Orientation::Horizontal,this); this->horizontal_slider->move(240,240); //15.垂直滑块 ///15.1 创建垂直滑块 this->vertical_slider = new QSlider(Qt::Orientation::Vertical,this); ///15.2 移动一下位置 this->vertical_slider->move(360,240); //16.按键序列编辑框 ///16.1 创建按键序列编辑框 this->keysequence_edit = new QKeySequenceEdit(this); ///16.2 设置位置 this->keysequence_edit->move(10,280); } InputWidgetsDemo::~InputWidgetsDemo() { delete this->combo_box; delete this->fontcombo_box; delete this->line_edit; delete this->text_edit; delete this->plaintext_edit; delete this->spin_box; delete this->doublespin_box; delete this->time_edit; delete this->date_edit; delete this->datetime_edit; delete this->dial; delete this->horizontal_bar; delete this->vertical_bar; delete this->horizontal_slider; delete this->vertical_slider; delete this->keysequence_edit; }
运行效果:

2.5.3 显示控件组(Display Widgets)
Qt的显示控件是专用于显示数据,图像的

2.5.3.1 在displaywidgets.h中加入如下代码
#ifndef DISPLAYWIDGETSDEMO_H #define DISPLAYWIDGETSDEMO_H #include<QDebug> #include<QMainWindow> //1.除了按钮控件组,输入控件组之外,还有显示控件组(Label,TextBrowser,GraphicsView,CalenderWidget,LCDNumber //ProgressBar,HorizontalLine,VerticalLine,OpenGLWidget,QQuickWidget(这个只有Qt6才有) #include<QLabel>//标签 #include<QTextBrowser>//文本浏览器 #include<QGraphicsView>//图形浏览器 #include<QCalendarWidget>//日历 #include<QLCDNumber>//液晶数字 #include<QProgressBar>//进度条 #include<QLine>//线 #include<QOpenGLWidget>//开放式图形工具库 class DisplayWidgetsDemo : public QMainWindow { Q_OBJECT public: DisplayWidgetsDemo(QWidget *parent = nullptr); ~DisplayWidgetsDemo(); private: QLabel*label;//1.标签控件 /*2.文本浏览器 * 文本浏览器是一种"只读的"文本编辑器,顾名思义只能对其进行阅读,不能修改里面的具体文字 * QTextBrowser继承于QTextEdit类,只不过QTextEdit还有链接文本的作用 */ QTextBrowser*textbrowser;//2.文本浏览器 QGraphicsView*graphicsview;//3.图像浏览器 QCalendarWidget*calenderwidget;//4.日历组件 QLCDNumber*lcdnumber;//5.液晶显示器 QProgressBar*progressbar;//6.进度条 QLine*horizontal_line;//7.水平线 QLine*vertical_line;//8.垂直线 QOpenGLWidget*opegl_widget;//9.OpenGL控件 }; #endif // DISPLAYWIDGETSDEMO_H
2.5.3.2 在displaywidgets.cpp中插入如下代码
#include"displaywidgetsdemo.h" DisplayWidgetsDemo::DisplayWidgetsDemo(QWidget *parent):QMainWindow(parent) { this->setMaximumWidth(800); this->setMaximumHeight(600); this->resize(800,600); //1.Label标签 ///1.1 创建一个Label对象,并设置其初始文字为"Label" this->label = new QLabel(tr("Label"),this); ///1.2 移动这个标签的位置 this->label->move(10,10); //2.TextBrowser(文本浏览器) ///2.1 创建文本浏览器对象 this->textbrowser = new QTextBrowser(this); this->textbrowser->move(60,10); //3.GraphicsView(图像浏览器) ///3.1 创建一个图像浏览器 this->graphicsview = new QGraphicsView(this); ///3.2 移动位置 this->graphicsview->move(180,10); //4.CalenderWidget日历组件 ///4.1 创建日历组件 this->calenderwidget = new QCalendarWidget(this); ///4.2 重新调整一下大小 this->calenderwidget->resize(300,300); ///4.3 移动位置 this->calenderwidget->move(10,50); //5.LCDNumber(液晶显示器) ///5.1 创建液晶显示器对象,并默认设置最多显示4位数 this->lcdnumber = new QLCDNumber(4,this); ///5.2 我们这里直接显示3.14 this->lcdnumber->display(3.14); ///5.2 移动一下位置 this->lcdnumber->move(360,10); //6.ProgressBar(进度条) ///6.1 创建进度条 this->progressbar = new QProgressBar(this); ///6.2 设置进度条的位置 this->progressbar->move(480,10); //7.水平线 ///7.1 创建水平线(这个要坐标来决定是水平线还是垂直线) this->horizontal_line = new QLine(QPoint(300,100),QPoint(200,100)); //8.垂直线 ///8.1 创建垂直线 this->vertical_line = new QLine(QPoint(400,100),QPoint(400,200)); //9.OpenGL组件 ///9.1 创建OpenGL组件 this->opegl_widget = new QOpenGLWidget(this); ///9.2 移动一下位置 this->opegl_widget->move(400,400); } DisplayWidgetsDemo::~DisplayWidgetsDemo() { delete this->label; delete this->textbrowser; delete this->graphicsview; delete this->calenderwidget; delete this->lcdnumber; delete this->progressbar; delete this->horizontal_line; delete this->vertical_line; delete this->opegl_widget; }
2.5.4 Spacers(空间间隔组)
这个空间间隔组实际上是分为了两种间隔,一种是水平间隔(HorizontalSpacer),一种是垂直间隔(VerticalSpacer)

2.5.5 布局管理器(这个是很重要的概念)
布局管理器实际上就是对窗口中的各个控件进行布局的,它分为4种布局:

Horizontal Layout:水平布局(对应的类是QHBoxLayout)
Vertical Layout:垂直布局(对应的类是QVBoxLayout)
Grid Layout:网格布局(对应的类是QGridLayout)
Form Layout:表格布局(对应的类是FormLayout)
2.5.6 Containers(容器组)
容器组可以理解为是用来"装"一些部件的,比如我们QQ的好友列表就用到了Tab Widget(标签组)

GroupBox:组框
ScrollArea:滚动区域
ToolBox:工具盒
TabWidget:标签控件
StackedWidget:堆栈窗体
Frame:帧
Widget:组件
MDIArea:MDI区域
DockWidget:停靠窗口部件
2.5.7 关于QWidget类(这个非常非常重要!!!)
2.5.7.1 什么是QWidget类?
QWidget类是一切Qt与GUI有关的类的基类,实际上所有的Qt与GUI有关的类都是派生自QWidget类的,那QWidget类的基类又是谁呢?其实是QObject类,QObject类是一切Qt类的基类。所有的GUI的部件都会依赖于QWidget类,而QWidget类本身可以对窗口的一些事件进行处理和接收(比如能够支持对键盘和鼠标事件进行接收),另外QWidget类本身不是一个抽象类,因此它可以直接作为承接其他任何GUI窗口类的容器部件来使用
2.5.7.2 QWidget类
我们先来看一下QWidget类的构造函数
QWidget::QWidget(QWidget *parent = nullptr,//这个是用于描述当前的QWidget的父窗口是谁
Qt::WindowFlags f = Qt::WindowFlags()//这个使用用来描述该QWidget的窗口标识的
)
什么是窗口标识?
窗口标识,又称为WindowFlags,这是用来描述窗口属性的一种枚举值(一个窗口可以有多个枚举值,可以使用|运算符来连接它们,表示他们有这些窗口属性)
另外我们不仅仅可以在QWidget的构造函数中来直接指定窗口标识,还可以直接使用QWidget::setWidowFlag()来一次设置一个窗口的标识从而影响到窗口的属性,还可以直接来使用QWidget::setWindowFlags()来一次性对同一个窗口设置多个窗口标识(使用|运算符连接);如果我们想随时设置该窗口的父窗口,还可以使用QWidget::setParent()函数来设置该窗口的父窗口,这些函数的原型如下:
void QWidget::setWindowFlag(Qt::WindowType flag,bool on = true);
void QWidget::setWindowFlags(Qt::WindowFlags type);
void QWidget::setParent(QWidget*parent);//这个只是设置该QWidget对象的父窗口
void QWidget::setParent(QWidget*parent,Qt::WindowFlags f);//这个不仅仅可以设置父窗口,还可以同时指定当前QWidget的窗口标识
关于parent参数:这个参数用于指定当前的窗口是否有父窗口,如果为nullptr或NULL或0,那么该Widget部件就是一个独立的窗口,如果有父窗体,那么这个创建的Widget就会作为其父窗口中一个组成部分来存在,另外若当父窗口在被释放时,位于其内的所有的子窗口都会被清理释放(这一点一定要注意),其他情况则需要手动释放内存。
案例1:创建一个窗口,并让其能够显示出来
1 //创建一个Qt Application工程,将main.cpp中的main函数中的内容改为 2 QWidget mywidget; 3 mywidget.resize(300,400); 4 QPushButton button; 5 button.setParent(&mywidget); 6 button.move(200,200); 7 mywidget.show();
在本例中,我们创建了一个QWidget的对象mywidget,我们没有为它指定父窗口指针,因此,这个窗口是一个独立的窗口存在的,另外我们又创建了一个QPushbutton,而我们使用了它的setParent方法为它设置了它的父窗口是mywidget,然后我们顺便移动了一下这个button在mywidget中的位置,运行之后,我们会发现,在mywidget窗口里面有一个button按钮。
当我们的mywidget被释放时,其子窗口button也会被释放(注意,如果对button进行隐藏则不会销毁内存中的button,此时button还是会驻留在内存中,直到mywidget被删除)
2.5.7.3 布局器类
当我们在一个窗口中放很多的子窗口(控件)时,如果我们不指定这些控件位于中国父窗口的什么位置,那么这些控件默认都会"挤"在这个父窗口的最左上角的位置(0,0)坐标的位置,这时候我们可以单独对每一个控件使用move方法来移动他们的坐标,使得他们均匀分布在父窗口的各个不同的位置使得他们不会重叠。但是这样子一来每次都要提前想好这些控件的坐标,岂不是很麻烦,因此,我们可以使用布局管理器来对这些控件的位置进行布局,我们前面介绍了4种布局(水平,垂直,网格,表单)分别对应着(QHboxLayout,QVBoxLayout,QGridLayout,QFormLayout)这四个布局管理的类.我们来看一下他们的常用的方法
我们以QHBoxLayout为例,假设我们当前的窗口中有两个控件button1和button2都需要进行水平方向的布局,那么此时我们需要这样子做
1 QPushButton*button1 = new QPushButton(tr("button1")); 2 QPushButton*button2 = new QPushButton(tr("button2")); 3 QHBoxLayout*mainLayout = new QHBoxLayout(this); 4 mainLayout->addWidget(button1); 5 mainLayout->addWidget(button2); 6 delete button1; 7 delete button2;
在上面的代码中,我们意图将两个Button进行横向排列(即水平布局),我们用到了QHBoxLayout这个类,我们定义了一个水平布局器对象,并指定凡是该布局管理器里面的对象都是当前主窗口的子控件对象,然后我们使用了addWidget分别将button1和button2放到布局器里面,这意味着,button1的位置在button2的左边
2.5.8 Item Views(项目视图组)

ListView列表视图
TreeView树形视图
TableView表单视图
ColumnView列视图
这里有一个QTableView和QTableWidget,它们之间有什么区别呢?
| 区别点 | QTableView | QTableWidget |
| 继承关系 | QTableWidget继承于QTableView | |
| setModel | 可以使用setModel来设置数据模型 | QTableWidget的setModel是私有的,不能使用setModel来设置数据模型 |
| 能否显示setCheckState复选框 | 没有对setCheckState进行实现,因此不能使用 | 该QTableWidget中的QTableWidgetItem有setCheckState函数,可以使用复选框 |
| 能否套用(绑定)QSqlTableModel | 可以套用 | 不能套用 |
那么什么是View和Model呢?
View实际上就是视图,Model实际上就是模型,在Qt5中将视图和模型实现了分离,这类似于C++的标准容器库中将容器和操作容器的迭代器做了分离,这一点会提高代码的复用性和后期改动的灵活性
在Qt中,所有的视图类都以抽象类QAbstractItemView作为基类的;所有的模型类都以QAbstractItemModel
案例:测试QSqlTableModel对象是否可以设置在QTableWidget或QTableView上
tableviewmodeldemo.h中写入以下代码
1 #ifndef TABLEVIEWMODELDEMO_H 2 #define TABLEVIEWMODELDEMO_H 3 #include<QMainWindow> 4 #include<QSqlTableModel> 5 #include<QTableView> 6 #include<QTableWidget> 7 class TableViewModelDemo : public QMainWindow 8 { 9 Q_OBJECT 10 public: 11 TableViewModelDemo(QWidget *parent = nullptr); 12 ~TableViewModelDemo(); 13 private: 14 QSqlTableModel*sqlTableModel; 15 QTabWidget*tableWidget; 16 QTableView*tableView; 17 }; 18 #endif // TABLEVIEWMODELDEMO_H
tableviewmodeldemo.cpp中有如下代码
1 #include "tableviewmodeldemo.h" 2 TableViewModelDemo::TableViewModelDemo(QWidget *parent):QMainWindow(parent) 3 { 4 //我们创建一个QSqlTableModel对象 5 this->sqlTableModel = new QSqlTableModel; 6 this->sqlTableModel->setTable(QString("SQLTable"));//我们在这里设置一下SQLTable的名字 7 this->sqlTableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);//设置该表单是否可编辑 8 this->sqlTableModel->select();// 9 this->sqlTableModel->removeColumns(0,0);//不显示每一个行头的序号 10 this->sqlTableModel->setHeaderData(0,Qt::Orientation::Horizontal,tr("姓名")); 11 this->sqlTableModel->setHeaderData(1,Qt::Orientation::Horizontal,tr("姓名")); 12 //再创建一个QTableView对象 13 this->tableView = new QTableView(this); 14 this->tableView->setModel(this->sqlTableModel);//我们的QTableView是可以设置模型的 15 //创建一个QTableWidget对象 16 this->tableWidget = new QTabWidget(this); 17 //this->tableWidget->setModel();//但是QTableWidget不能设置模型 18 } 19 TableViewModelDemo::~TableViewModelDemo() 20 { 21 delete this->sqlTableModel; 22 delete this->tableView; 23 delete this->tableWidget; 24 }
注意:视图在和模型绑定时,模型必须要使用new的方式来创建,否则视图不会随模型的改变而改变
2.5.8 案例(创建带有树状复选框的创建)
打开Qt Creator,创建一个Qt Widget项目,项目名称叫做TreeWidget,记得勾选创建界面文件的复选框,在ui编辑框中拖入一个QTreeWidget的控件,然后修改以下代码
2.5.8.1 在widget.h中添加以下代码
#ifndef WIDGET_H
#define WIDGET_H
#include<QWidget>
#include<QDebug>
#include<QTreeWidgetItem>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
private:
void initTreeWidgetItem();
private slots:
void treeItemChanged(QTreeWidgetItem*item,int colmun);
private:
QTreeWidgetItem*m_group1;
QTreeWidgetItem*m_group2;
};
#endif // WIDGET_H
2.5.8.2 在widget.cpp中
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent):QWidget(parent),ui(new Ui::Widget)
{
ui->setupUi(this);
this->initTreeWidgetItem();
connect(this->ui->treeWidget,SIGNAL(itemChanged(QTreeWidgetItem*,int)),this,SLOT(treeItemChanged(QTreeWidgetItem*,int)));
}
Widget::~Widget()
{
delete ui;
}
void Widget::initTreeWidgetItem()
{
//组别一
this->m_group1 = new QTreeWidgetItem(this->ui->treeWidget);
m_group1->setText(0,tr("组别一"));
m_group1->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
m_group1->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem*subItem1ForGroup1 = new QTreeWidgetItem(this->m_group1);
subItem1ForGroup1->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
subItem1ForGroup1->setText(0,tr("选项一"));
subItem1ForGroup1->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem*subItem2ForGroup1 = new QTreeWidgetItem(this->m_group1);
subItem2ForGroup1->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
subItem2ForGroup1->setText(0,tr("选项二"));
subItem2ForGroup1->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem*subItem3ForGroup1 = new QTreeWidgetItem(this->m_group1);
subItem3ForGroup1->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
subItem3ForGroup1->setText(0,tr("选项三"));
subItem3ForGroup1->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem*subItem4ForGroup1 = new QTreeWidgetItem(this->m_group1);
subItem4ForGroup1->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
subItem4ForGroup1->setText(0,tr("选项四"));
subItem4ForGroup1->setCheckState(0,Qt::Unchecked);
///组别二
this->m_group2 = new QTreeWidgetItem(this->ui->treeWidget);
m_group2->setText(0,tr("组别二"));
m_group2->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
m_group2->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem*subItem1ForGroup2 = new QTreeWidgetItem(this->m_group2);
subItem1ForGroup2->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
subItem1ForGroup2->setText(0,tr("选项一"));
subItem1ForGroup2->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem*subItem2ForGroup2 = new QTreeWidgetItem(this->m_group2);
subItem2ForGroup2->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
subItem2ForGroup2->setText(0,tr("选项二"));
subItem2ForGroup2->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem*subItem3ForGroup2 = new QTreeWidgetItem(this->m_group2);
subItem3ForGroup2->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
subItem3ForGroup2->setText(0,tr("选项三"));
subItem3ForGroup2->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem*subItem4ForGroup2 = new QTreeWidgetItem(this->m_group2);
subItem4ForGroup2->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
subItem4ForGroup2->setText(0,tr("选项四"));
subItem4ForGroup2->setCheckState(0,Qt::Unchecked);
}
void Widget::treeItemChanged(QTreeWidgetItem *item, int colmun)
{
//1.首先,要判断这个节点是不是组别节点,我们可以使用childCount来判断
if(item->childCount()>0)//说明是组别节点
{
if(item->checkState(0)==Qt::Checked)//如果组别节点被选中,那其所有的选项节点都要被选中
{
for (int i = 0;i < item->childCount();i++)
{
item->child(i)->setCheckState(0,Qt::Checked);
}
}
else if(item->checkState(0)==Qt::Unchecked)//如果组别节点没有选中,那其所有的选项节点都不要被选中
{
for (int i = 0;i < item->childCount();i++)
{
item->child(i)->setCheckState(0,Qt::Unchecked);
}
}
}
else//那就说明这个结点只是一个单独的选项节点
{
//那么我们应该要知道用户一共选择了多少个选项结点,以及该选项节点的父结点一共有多少个选项节点
static int selectCnt = 0;
QTreeWidgetItem*parent = item->parent();
int totalCnt = parent->childCount();
//遍历这些子结点,看看哪些是被选中的,得到被选中的子选项的个数
for (int i = 0;i<totalCnt;i++)
{
if(parent->child(i)->checkState(0)==Qt::Checked)
{
selectCnt++;
}
}
if(selectCnt>0&&selectCnt<totalCnt)//如果子选项被选中的个数大于0但小于总的子选项个数
{
parent->setCheckState(0,Qt::PartiallyChecked);
selectCnt = 0;
}
else if(selectCnt==totalCnt)
{
parent->setCheckState(0,Qt::Checked);
selectCnt = 0;
}
else if(selectCnt==0)
{
parent->setCheckState(0,Qt::Unchecked);
}
}
}
2.5.8.3 运行

2.5.9 多控件的实例
在本案例中,我们将使用图形化ui的方式创建一个结合到正则表达式的行编辑框以及两个button,来根据用户输入的字符串是否符合正则表达式的规范来控制OK按钮是否可用被点击
2.5.9.1 在Qt中建立一个QWidget类型的项目,配置为如下

2.5.9.2 由于要用到正则表达式相关的类,因此需要在GoToCell.pro文件中引入这个模块QT += core

2.5.9.3 在ui的编辑界面中拖入两个PushButton,一个LineEdit,一个水平弹簧控件,一个Label,并将它们的对象名命名为旁边的这种名称

2.5.9.4 之后我们需要将弹簧控件和两个button做水平布局
选择弹簧控件,确定按钮,取消按钮之后点击上面的水平布局即是下面的这种效果

2.5.9.5 照此办理将Label和LineEdit也做水平布局

2.5.9.6 之后选中整个GoToCell部件,这意味着里面的所有的将被再次布局,我们点击垂直布局

2.5.9.7 整体看起来很大,我们点击自适应控件大小按钮,就变成了这样子

2.5.9.8 在gotocell.h中添加以下代码
#ifndef GOTOCELL_H
#define GOTOCELL_H
#include<QWidget>
#include<QRegularExpression>
#include<QRegularExpressionValidator>
QT_BEGIN_NAMESPACE
namespace Ui { class GoToCell; }
QT_END_NAMESPACE
class GoToCell : public QWidget
{
Q_OBJECT
public:
GoToCell(QWidget *parent = nullptr);
~GoToCell();
private:
Ui::GoToCell *ui;
private slots:
void onLineEditTextChanged();
};
#endif // GOTOCELL_H
2.5.9.9 在gotocell.cpp中实现以下代码
#include "gotocell.h"
#include "ui_gotocell.h"
GoToCell::GoToCell(QWidget *parent):QWidget(parent),ui(new Ui::GoToCell)
{
ui->setupUi(this);
QRegularExpression regExp("[0-1][2-3][3-4]");
this->ui->lineEdit->setValidator(new QRegularExpressionValidator(regExp,this));
connect(this->ui->lineEdit,SIGNAL(textChanged(QString)),this,SLOT(onLineEditTextChanged()));
}
GoToCell::~GoToCell()
{
delete ui;
}
void GoToCell::onLineEditTextChanged()
{
this->ui->okButton->setEnabled(this->ui->lineEdit->hasAcceptableInput());
}
2.5.9.10 运行
只有当我们输入符合我们刚刚规定的正则表达式的字符串后,确定按钮才可以被点击

如果不符合,确定按钮就被禁用了


浙公网安备 33010602011771号