算法及正则表达式
首先介绍Qt的 和 模块中几种常用算法,然后再介绍基本的正则表达式。
常用算法
#include "widget.h" #include <QApplication> #include <QDebug> int main(int argc, char *argv[]) { QApplication a0(argc, argv); double a = -19.3, b = 9.7; double c = qAbs(a);//返回a的绝对值 double max = qMax(b, c);//返回两个数值中最大值 int bn = qRound(b);//返回一个与浮点数最接近的整数值。 int cn = qRound(c); qDebug() << "a = " << a; qDebug() << "b = " << b; qDebug() << "c = qAbs(a) = " << c; qDebug() << "qMax(b,c)" << max; qDebug() << "bn = qRound(b) = " << bn; qDebug() << "cn = qRound(c) = " << cn; qSwap(bn, cn);//交换两个数的值 qDebug() <<"qSwap(bn, cn) : " << "bn = " << bn << ", cn = " << cn; return a0.exec(); }
基本的正则表达式
使用正则表达式可以方便地完成处理字符串的一些操作,如验证、查找、替换和分割等。Qt的QRegExp类是正则表达式的表示类,它基于Perl的正则表达式语言,完全支持Unicode。
正则表达式由表达式(expressions)、量词(quantifiers)和断言(assertions)组成。
- 最简单的表达式是一个字符。字符集可以使用表达式如“[AEIOU]”,表示匹配所有的大写元音字母;使用“[^AEIOU]” 则表示匹配所有非元音字母,即辅音字母;连续的字符集可以使用表达式“[a-z]”,表示匹配所有的小写英文字母。
- 量词说明表达式出现的次数。如“x[1,2]”表示“x”可以至少有一个,最多两个。
在计算机语言中,标识符通常要求以字母或下划线开头,后面可以是字母、数字和下划线。满足条件的标识符表示为:
" [A-Za-z_]+[A-Za-z_0-9]* "
其中,表达式中的“+”表示“[A-Za-z]”至少出现一次,可以出现多次;“ * ”表示“[A-Za-z_0-9]”可以出现0次或者多次。
- 类似的正则表达式的量词如下:
量词 含义 量词 含义
E? 匹配0次或1次 E[n,] 至少匹配n次
E+ 匹配1次或者多次 E[,m] 最多匹配m次
E* 匹配0次或多次 E[n,m] 至少匹配n次,最多匹配m次
E[n] 匹配n次 – –
- 正则表达式的断言:
符号 含义 符号 含义
^ 表示在字符串开头进行匹配 \B 非单词边界
$ 表示在字符串结尾进行匹配 (?=E) 表示表达式后缀紧随E才匹配
\b 单词边界 (?!E) 表示表达式后不跟随E才匹配
控件
本节简单介绍几个常用的控件,以便对Qt的控件有一个初步认识。
按钮组(Buttons)
具体如下 :
- Push Button:按钮。
- Tool Button:工具按钮。
- Radio Button:单选按钮。
- Check Box:复选框
- Command Link Button:命令链接按钮。
- Dialog Button Box:对话框按钮盒。
示例:
- 新建项目“PushButtonTest”,基类选择QWideget选项,取消“创建界面”复选框。
- widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); }; #endif // WIDGET_H
- widget.cpp
#include "widget.h" #include <qapplication.h> #include <qpushbutton.h> #include <qfont.h> Widget::Widget(QWidget *parent) : QWidget(parent) { setMinimumSize(200, 120); setMaximumSize(200, 120); QPushButton *quit = new QPushButton("Quit", this); quit->setGeometry(62, 40, 75, 30); quit->setFont(QFont("Times", 18, QFont::Bold)); connect(quit, SIGNAL(clicked()), qApp, SLOT(quit())); } Widget::~Widget() { }
- main.cpp
#include "widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.setGeometry(100, 100, 200, 120); w.show(); return a.exec(); }
- 执行结果
输入部件(Input Widgets)
输入部件(Input Widgets)如下图:
- Combo Box:组合框。
- Font Combo Box:字体组合框。
- Line Edit:行编辑框。
- Text Edit:文本编辑框。
- Plain Text Edit:纯文本编辑框。
- Spin Box:数字显示框(自旋盒)。
- Double Spin Box:双自旋盒。
- Time Edit:时间编辑。
- Date Edit:日期编辑。
- Date/Time Edit:日期/时间编辑。
- Horizontal Scroll Bar:横向滚动条。
- Vertical Scroll Bar:垂直滚动条。
- Horizontal Slider:横向滑块。
- Vertical Slider:垂直滑块。
- Key Sequence Edit:按键序列编辑框。
QDateTime类
Date/Time Edit对应于QDateTime类,在Qt5中可以使用它获得系统时间。通过QDateTime::currentDateTime()来获取本地系统的时间和日期信息。可以通过date()和time()来返回datetime中的日期和时间部分。典型代码如下:
QLabel *datalbel = new QLabel(); QDateTime *datatime = new QDateTime(QDateTime::currentDateTime()); datalbel->setText(datatime->date().toString()); datalbel->show();
QTimer类
定时器(QTimer)的使用非常简单,只需要以下几个步骤就可以完成定时器的应用。
- 新建一个定时器
QTimer *timer_clock = new QTimer(parent);
- 连接这个定时器的信号和槽,利用定时器的timeout()。
connect(timer_clock, SIGNAL(timeout()), this, SLOT(slottimedone());
即定时时间一刀就会发生timeout()信号,从而触发slottimedone()槽去完成某件事情。
- 开启定时器,并设定定时周期。
定时器定时有两种方式:start(int time)和setSingleShot(true)。其中,start(int time)表示每隔“time”毫秒会重启定时器,可以重复触发定时,利用stop()将定时器关闭;而setSingleShot(true)是仅启动定时器一次。
time_clock->start(2000);
显示控件组(Display Widgets)
显示控件组(Display Widgets)如下图所示:
- Label:标签。
- Text Browser:文本浏览器。
- Graphics View:图像视图
- Calendar Widget:日历。
- LCD Number:液晶数字。
- Progress Bar:进度条。
- Horizontal Line:水平线。
- Vertical Line:垂直线。
- OpenGL Widget:开放式图形库工具。
- QQuick Widget:嵌入QML工具。
Graphics View
Graphics View 对应于QGraphicsView类,提供了Qt5的图像视图框架。
Text Browser
Text Browser 对应于QTextBrowser类,QTextBrowser类继承自QTextEdit,而且仅是只读的,对里面的内容并不能继续更改,但是相对于QTextEdit来讲,它还具有链接文本的作用。
modified : const bool //通过布尔值来说明内容是否被修改 openExternalLinks : bool openLinks : bool readOnly : const bool searchPaths : QStringList source : QUrl undoRedoEnabled : const bool
通过以上属性设置,可以设定QTextBrowser是否允许外部链接,是否为只读属性,外部链接的路径及链接内容,是否可以进行撤销等操作。
QTextBrowser还提供了几种比较有用的槽函数。
virtual void backward();//上一页 virtual void forward();//下一页 virtual void home(); //主页
可以通过链接这几个槽函数来达到“翻页”的效果。
QQuickWidget
QQuickWidget是Qt5.3发布的一个组件,传统的QWidget程序可以用它来嵌入QML代码,为Qt开发者将桌面应用迁移到Qt Quick提供了方便,但目前QML中尚不能嵌入其他非QML窗口,因为QML的渲染机制和QWidget是不一样的。
空间间隔组(Spaacers)
- Horizontal Spacer:水平间隔。
- Vertical Spacer:垂直间隔。
布局管理组(Layouts)
- Vertical Layout:垂直布局,
- Horizontal Layout:水平布局。
- Grid Layout:网格布局。
- Form Layout:表单布局。
容器组(Containers)
- Group Box:组框。
- Scroll Area:滚动区域。
- Tool Box:工具箱。
- Tab Widget:标签小部件。
- Stackerd Widget:堆叠部件。
- Frrame:帧。
- Widget:小部件。
- MDI Area:MDI区域。
- Dock Widget:停靠窗体部件。
- QAxWidget:封装flash的ActiveX控件。
Widget对应的QWidget类的用法
Widget是使用Qt编写的图像用户界面(GUI)应用程序的基本生成块。每个GUI组件,如按钮、标签或文本编辑器,都是一个Widget,并可以放置在现有的用户界面中或作为单独的窗口显示。每种类型的组件都是由QWidget的特殊子类提供的,而QWidget自身又是QObject的子类。
QWidget是所以QtGUI界面类的基类,它接收鼠标、键盘及其他窗口事件,并在显示器上绘制自己。
通过传入QWidget构造函数的参数(或者调用QWidget::setWindowFlags() 和 QWidget::setParent() 函数)可以指定一个窗口部件的窗口标识(window flag)和父窗口部件。
窗口部件的窗口标识(window flag)定义了窗口部件的窗口类型和窗口提示(hint)。窗口类型指定了窗口部件的窗口系统属性(window-system properties),一个窗口部件只能有一个窗口类型,窗口提示定义了顶层窗口的外观,一个窗口可以由多个提示。
没有父窗口部件的Widget对象是一个窗口,窗口通常具有一个窗口边框(frame)和一个标题栏。而子窗口部件通常处在父窗口部件的内部,没有窗口边框和标题栏。
QWidget窗口部件的构造函数为:
QWidget(QWidget *parent = 0, Qt::WindowFlags f = 0); /* parent:指定窗口部件的父窗口部件。如果为0则新建窗口部件蒋帅一个窗口。否则新建窗口将会出现在父窗口部件的界面内部。 f:指定了新窗口的窗口标识。默认是0,及Qt::Widget. */
示例:
- 创建窗口
QWidget *window = new QWidget(); window->resize(320, 240); window->show(); QPushButton *button = new QPushButton(QObject::tr("Press me"), window); button->move(100, 100); button->show();
使用布局: QWidget *window = new QWidget(); //新建label进行布局 QLabel *label = new QLabel(QObject::tr("Name:")); QLineEdit *lineEdit = new QLineEdit(); QHBoxLayout *layout = new QHBoxLayout(); layout->addWidget(label); layout->addWidget(lineEdit); window->setLayout(layout); window->resize(320, 240); window->show(); QPushButton *button = new QPushButton(QObject::tr("Press me"), window); button->move(20, 20); button->show();
- 设计复杂关系的窗口视图
QWidget *window = new QWidget(); QLabel *queryLabel = new QLabel(); QLineEdit *queryEdit = new QLineEdit(); QTableView *resultView = new QTableView(); QHBoxLayout *queryLayout = new QHBoxLayout(); queryLayout->addWidget(queryLabel); queryLayout->addWidget(queryEdit); QVBoxLayout *mainLayout = new QVBoxLayout(); mainLayout->addLayout(queryLayout); mainLayout->addWidget(resultView); window->setLayout(mainLayout); window->show();
项目视图组(Item Views)
- List View:清单视图。
- Tree View:树视图。
- Table View:表视图。
- Column View:列视图。
Table View与Table Widget的区别
具体如下表:
区别点 QTableView QTableWidget
继承关系 – QTableWidget集成子QTableView
使用数据模型setModel 可以使用setModel设置数据模型 setModel是私有函数,不能使用该函数设置数据模型
显示复选框setCheckState 没有函数实现复选框 QTableWidgetItem类中的setCheckState(Qt::Checked):可以设置复选框。
与QSqlTableModel 绑定 QTableView能与QSqlTableModel绑定 QTableWidget不能与QSqlTableModel绑定
- 模型:所有的模型都是基于QAbstractItemModel类,该类是抽象基类。
- 视图:所有的视图都从抽象基类QAbstractItemView继承。
Qt5中引入了模型/视图框架用于完成数据与表现的分离,这在Qt5中成为InterView框架,类似于常用的MVC设计模式。
MVC设计模式是起源于Smalltalk语言的一种与用户界面相关的设计模式。MVC包括三个元素:模型(model)表示数据;视图(view)表示用户界面;控制(controller)定义了用户在界面上的操作。同使用MVC模式,有效地分离了数据和用户界面,使得设计更为灵活,更能适应变化。
示例:
- 简单使用:
QSqlTableModel *model = new QSqlTableModel(); model->setTable("employee"); model->setEditStrategy(QSqlTableModel::OnManualSubmit); model->select(); model->removeColumn(0); model->setHeaderData(0, Qt::Horizontal, QObject::tr("Name")); model->setHeaderData(1, Qt::Horizontal, QObject::tr("Salary")); QTableView *view = new QTableView(); view->setModel(model); view->show();
* 视图与模型绑定,模型必须使用new创建,否则视图不能随模型的改变而改变。
// QStandardItemModel model(4, 2); 错误,没有使用new创建。 QStandardItemModel *model = new QStandardItemModel(4, 2); //正确,应该使用new创建model。 model->setHeaderData(0, Qt::Horizontal, QObject::tr("Label")); model->setHeaderData(1, Qt::Horizontal, QObject::tr("Quantity")); ui->tableView->setModel(model); for(int row = 0; row <4 ; ++row) { for(int column = 0; column < 2; ++column) { QModelIndex index = model->index(row, column, QModelIndex()); model->setData(index, QVariant((row + 1) *(column + 1))); } }
项目控件组(Item Widgets)
- List Widget:清单控件。
- Tree Widget:树形控件。
- Table Widget:表控件。
树形控件实例
树形控件QTree Widget,其中控件的树节点成为QTreeWidgetItem,这种控件有时很有用处。例如,在飞信软件群发短信时选择联系人的界面中就用到这种有复选框的树形控件。
接下来实现一个简单的树形控件实例。
1、新建项目,保持“创建界面”复选框选择状态。
2、双击“widget.ui”文件,打开Qt的设计器,拖拽一个QTreeWidget控件到widget窗口中。
3、添加以下代码
- widget.cpp
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); init(); connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(treeItemChanged(QTreeWidgetItem *, int))); } Widget::~Widget() { delete ui; } void Widget::init() { ui->treeWidget->clear(); //第一个分组 QTreeWidgetItem *group1 = new QTreeWidgetItem(ui->treeWidget); group1->setText(0, "group1"); group1->setFlags(Qt::ItemIsUserCheckable |Qt::ItemIsEnabled |Qt::ItemIsSelectable); group1->setCheckState(0, Qt::Unchecked); QTreeWidgetItem *subItem11 = new QTreeWidgetItem(group1); subItem11->setFlags(Qt::ItemIsUserCheckable |Qt::ItemIsEnabled |Qt::ItemIsSelectable); subItem11->setText(0, "subItem11"); subItem11->setCheckState(0, Qt::Unchecked); QTreeWidgetItem *subItem12 = new QTreeWidgetItem(group1); subItem12->setFlags(Qt::ItemIsUserCheckable |Qt::ItemIsEnabled |Qt::ItemIsSelectable); subItem12->setText(0, "subItem12"); subItem12->setCheckState(0, Qt::Unchecked); QTreeWidgetItem *subItem13 = new QTreeWidgetItem(group1); subItem13->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable); subItem13->setText(0, "subItem13"); subItem13->setCheckState(0, Qt::Unchecked); QTreeWidgetItem *subItem14 = new QTreeWidgetItem(group1); subItem14->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable); subItem14->setText(0, "subItem14"); subItem14->setCheckState(0, Qt::Unchecked); //第二个分组 QTreeWidgetItem *group2 = new QTreeWidgetItem(ui->treeWidget); group2->setText(0, "group2"); group2->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); group2->setCheckState(0, Qt::Unchecked); QTreeWidgetItem *subItem21 = new QTreeWidgetItem(group2); subItem21->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable); subItem21->setText(0, "subItem21"); subItem21->setCheckState(0, Qt::Unchecked); QTreeWidgetItem *subItem22 = new QTreeWidgetItem(group2); subItem22->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable); subItem22->setText(0, "subItem22"); subItem22->setCheckState(0, Qt::Unchecked); QTreeWidgetItem *subItem23 = new QTreeWidgetItem(group2); subItem23->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable); subItem23->setText(0, "subItem23"); subItem23->setCheckState(0, Qt::Unchecked); QTreeWidgetItem *subItem24 = new QTreeWidgetItem(group2); subItem24->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable); subItem24->setText(0, "subItem24"); subItem24->setCheckState(0, Qt::Unchecked); } void Widget::treeItemChanged(QTreeWidgetItem *item, int column) { QString itemText = item->text(0); //选中时 if(Qt::Checked == item->checkState(0)) { QTreeWidgetItem *parent = item->parent(); int count = item->childCount(); if(count > 0) { for(int i = 0; i <count; i++) { //子字节也选中 item->child(i)->setCheckState(0, Qt::Checked); } } else { //是子节点 updateParentItem(item); } } else if (Qt::Unchecked == item->checkState(0)) { int count = item->childCount(); if(count > 0) { for(int i = 0; i <count; i++) { //子字节也选中 item->child(i)->setCheckState(0, Qt::Unchecked); } } else { //是子节点 updateParentItem(item); } } } void Widget::updateParentItem(QTreeWidgetItem *item) { QTreeWidgetItem *parent = item->parent(); if(parent == NULL) { return ; } //选中子节点个数 int selectedCount = 0; int childCount = parent->childCount(); for(int i = 0; i <childCount; i++) { QTreeWidgetItem *childItem = parent->child(i); if(childItem->checkState(0) == Qt::Checked) { selectedCount++; } } if(selectedCount <= 0) { //未选中状态 parent->setCheckState(0, Qt::Unchecked); } else if (selectedCount > 0 &&selectedCount <childCount) { //部分选中 parent->setCheckState(0, Qt::PartiallyChecked); } else if (selectedCount == childCount) { //选中状态 parent->setCheckState(0, Qt::Checked); } }
- widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTreeWidget> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = nullptr); ~Widget(); void init(); void updateParentItem(QTreeWidgetItem *item); public slots: void treeItemChanged(QTreeWidgetItem *item, int column); private: Ui::Widget *ui; }; #endif // WIDGET_H
- 执行结果