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
View Code

   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()被触发";
}
View Code

运行效果:

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
View Code

  在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;
}
View Code

  运行效果:

 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
View Code

  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;
}
View Code

 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();
View Code

    在本例中,我们创建了一个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;
View Code

    在上面的代码中,我们意图将两个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
View Code

  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 }
View Code

   注意:视图在和模型绑定时,模型必须要使用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 运行

  只有当我们输入符合我们刚刚规定的正则表达式的字符串后,确定按钮才可以被点击

  

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

  

 

posted @ 2023-10-07 23:47  蜡笔小新Pointer  阅读(68)  评论(0)    收藏  举报