《Qt应用开发》笔记p5
QMainWindow (主窗口)
Qt的 QMainWindow 用于创建具有标准组件的桌面应用程序,是构建复杂桌面应用程序用户界面的基础。
特点:
- 标准化结构
- 提高开发效率
- 功能清晰。
五个常用的部分:
- 菜单栏 Menu Bar
- 工具条 Tool Bar
- 停靠部件 Dock Widgets
- 中心部件 Central Widget
- 状态栏 Status Bar
图示:
模式对话框
模式对话框是指独占所有输入的对话框,在此对话框结束之前,所有的对话框都禁止使用的对话框。
消息对话框
消息对话框属于模式对话框。
QMessageBox::question // 带问号图标的对话框
QMessageBox::information // 带蓝色叹号的对话框
QMessageBox::warning // 带红色叹号的对话框
QMessageBox::critical // 带致命错误图标的对话框
QFileDialog 对话框
Qt 提供的一些标准的对话框,如文件操作对话框(QFileDialog等)方便用户调用并获取信息。
QFileDialog(
QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &directory = QString(),
const QString &filter = QString()
)
QDialog 对话框
QDialog 对话框是模式对话框的基类,用它可以自定义模式和非模式对话框。
QDialog 的槽函数有:
// 接受(返回QDialog::Accepted --> 1)
virtual void accept()
// 返回 自定义的值。
virtual void done(int r)
virtual int exec() // 显示为模式对话框
// 拒绝(QDialog::Rejected --> 0)
virtual void reject()
SQLite 数据库
数据库介绍
数据库从字面意思解释就是存储数据的仓库。
数据库按存储数据的方式可以分为:
-
关系型数据库
- 以数据表的形式存储,表和表之间建立逻辑关系,如:
- Oracle、MySQL、SQLite等。
-
非关系型数据库
-
以键值对或字典等方式存储,如:
- Redis、MongoDB等。
-
数据表 table
- 列:字段(每个字段有统一的数据类型),各个字段的类型可以不同。
- 行:记录,用于记录数据,每一行称之为一条数据。
- 数据表:有行列组成。
数据表student
ID | 姓名 | 年龄 |
---|---|---|
1 | 张三 | 18 |
2 | 李四 | 19 |
INSERT INTO student VALUES(1, "张三", 18);
INSERT INTO student(name, age, id) VALUES("李四", 19, 2);
SELECT * FROM student;
数据表科目 subject
id | 科目 |
---|---|
1 | 语文 |
2 | 数学 |
INSERT INTO sub VALUES(1, "语文");
INSERT INTO sub VALUES(2, "数学");
SELECT * FROM sub;
数据表 score
id | 学生 ID | 科目ID | 成绩 |
---|---|---|---|
1 | 1 | 1 | 100 |
2 | 1 | 2 | 88 |
3 | 2 | 1 | 99 |
4 | 2 | 2 | 66 |
INSERT INTO scr VALUES(1, 1, 1, 100);
INSERT INTO scr VALUES(2, 1, 2, 88);
INSERT INTO scr VALUES(3, 2, 1, 99);
INSERT INTO scr VALUES(4, 2, 2, 66);
SELECT * FROM scr;
SQLite 数据库简介
SQLite 是一个轻量级的关系型数据库
SQLite = SQL + Lite
SQL(Structured Query Language) 是结构化查询语言。
Lite 是轻量的意思。
SQLite专门为嵌入式设计,仅仅需要几百K内存就可以运行。
SQLite 支持多个操作系统:Windows,Linux,UNIX等。
SQLite 数据库是遵守ACID规则的数据库。
ACID是数据库管理的四个特征
-
原子性(Atomicity)
- 支持事务操作,要么全部执行,要么都不执行。
-
一致性(Consistency)
- 在事务开始前和事务结束后,数据库是完整的,没有给破坏过。
-
隔离性(Isolation)
- 允许多个事务进行并发的对数据库进行读写和修改,隔离性可以防止在并发执行时导致数据的不一致性。
-
持久性(Durability)
- 在事务完成后,对于数据库的修改会持久的保存在数据库中,并不会被恢复。
安装 SQLite
sudo apt install sqlite3 libsqlite3-dev -y
SQLite3 官网 https://www.sqlite.org/
使用 sqlite3 命令来操作数据库
sqlite3 [数据库文件名]
示例
$ sqlite3 test.db
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite>
SQLite3 控制台的基本操作
.version // 查看数据库的版本信息
.help // 查看所有的SQLite命令
.quit/.exit // 退出数据库控制台
.print // 打印一些信息
.tables // 查看当前数据库中的所有数据表。
.schema [数据表] // 查看数据表的创建结构。
SQLite3数据库基础数据类型
存储类 | 说明 | 常见声明的类型 |
---|---|---|
NULL | 空值 | |
INTEGER | 带符号整数 | INTEGER, INT, BIGINT, TINYINT |
REAL | 浮点数 | REAL, FLOAT, DOUBLE |
TEXT | 文本字符串 | TEXT, VARCHAR(N), CHAR(N), CLOB |
BLOB | 二进制数据 | BLOB(如果没有声明类型,默认也是 BLOB) |
SQL 语言的语句的两种类型
- DDL(数据定义语言)
- DML(数据操作语言)
SQL 语句的关键字不区分大小写,即(CREATE、create 和CrEaTe都是一样的)
DDL(数据定义语言)-- 用来操作数据表
DDL用于定义和管理数据库的结构,包括创建、修改和删除数据库对象(如表)
创建数据表的SQL语句
-- 格式
CREATE TABLE 表名(字段名1 字段数据类型1,字段名2 字段数据类型2,...);
示例
CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER);
CREATE TABLE sub(id INTEGER PRIMARY KEY AUTOINCREMENT, subject VARCHAR(20) NOT NULL UNIQUE);
CREATE TABLE scr(id INTEGER PRIMARY KEY AUTOINCREMENT, stu_id INTEGER, sub_id INTEGER, score INT);
SQL 中的约束关键字
NOT NULL // 非空(不允许没有值)
UNIQUE // 唯一(字段内不允许重复)
PRIMARY KEY // 主键(非空且唯一,通常作为唯一标识使用)
AUTOINCREMENT // 整数值自动递增。
删除数据表的SQL语句
DROP TABLE 表名
示例
DROP TABLE student;
DROP TABLE scr;
DROP TABLE sub;
DML 数据操作语言 -- 用来操作数据记录的
DML包括的命令有
- INSERT - 插入记录
- UPDATE - 更新(修改)记录的值
- DELETE - 删除记录
- SELECT - 查询记录
插入数据记录 INSERT
作用:向数据表中插入记录
语法格式
INSERT INTO 数据表名(字段名1, 字段名2,...) VALUES(字段数据1,字段数据2,...);
// 或
INSERT INTO 数据表名 VALUES(字段数据1,字段数据2,...);
示例
INSERT INTO student(id, name, age) VALUES(1, "zhang3", 18);
INSERT INTO student(name, age) VALUES('li4', 19);
INSERT INTO student VALUES(3, 'wang5', 17);
查询记录 SELECT
作用:用于查询记录
语法规则
SELECT 字段名1, 字段名2, ... FROM 表名;
SELECT * FROM 表名;
SELECT 字段名1, 字段名2, ... FROM 表名 WHERE 条件;
示例
SELECT * FROM student;
SELECT name, age FROM student;
SELECT name FROM student;
SELECT name, age, id FROM student;
// 查询 年龄小于 18 周岁的学生的姓名和年龄
SELECT name,age FROM student WHERE age < 18;
修改数据记录 UPDATE
作用:修改指定条件的数据记录的某个字段的值
语法规则
UPDATE 表名 SET 字段名1=字段值1, 字段名2=字段值2, ... WHERE 条件;
示例
// 修改ID 为 1 的用户的 姓名为 张三丰 年龄为 19 周岁
UPDATE student SET name="张三丰",age=19 WHERE id=1;
SQL 中的比较运算
> 大于 >= 大于等于 < 小于 <= 小于等于 = 等于 != <> 不等于
SQL 中的逻辑运算
AND 与运算 OR 或运算 NOT 非运算
删除记录 DELETE
作用:删除指定条件的数据记录。
语法规则
DELETE FROM 表名 WHERE 条件;
示例
// 删除 ID 为 1 的用户
DELETE FROM student WHERE id=1;
// 删除所有记录但不删除数据表
DELETE FROM student;
Linux 下SQLite数据的查询工具 sqlitebrowser
# 安装方法
sudo apt install sqlitebrowser
# 运行方法
sqlitebrowser SQLite.db文件
联合UNION查询
// 查询 所有 成绩中大于 80 的成绩
SELECT * FROM scr WHERE score >80;
// 查询 所有 成绩中大于 80 的语文成绩
SELECT * FROM scr WHERE score >80 and sub_id = 1;// 将三张表拼接成一张大表
SELECT * FROM scrJOIN studentON scr.stu_id = student.idJOIN sub ON scr.sub_id = sub.id;// 查询 语文 成绩中大于 80 的学生姓名
SELECT name, subject, score FROM scrJOIN studentON scr.stu_id = student.idJOIN sub ON scr.sub_id = sub.idWHERE subject="语文" and score >80;// 查询 数学 成绩中大于 80 的学生姓名
SELECT name, subject, score FROM scrJOIN studentON scr.stu_id = student.idJOIN sub ON scr.sub_id = sub.idWHERE subject="数学" and score >80;
笛卡尔积图示
SQLite3 的C语言接口
详见:/usr/include/sqlite3.h 文件
相关函数
sqlite3_open()
sqlite3_exec();
sqlite3_close()sqlite3_step()
sqlite3_prepare()
示例
#include <stdio.h>
#include <sqlite3.h>static int callback(void *NotUsed, int argc, char **argv, char **azColName){int i;for(i=0; i<argc; i++){printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");}printf("\n");return 0;
}int main(int argc, char **argv){sqlite3 *db;char *zErrMsg = 0;int rc;if( argc!=3 ){fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);return(1);}rc = sqlite3_open(argv[1], &db);if( rc ){fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));sqlite3_close(db);return(1);}rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);if( rc!=SQLITE_OK ){fprintf(stderr, "SQL error: %s\n", zErrMsg);sqlite3_free(zErrMsg);}sqlite3_close(db);return 0;
}
编译
gcc 01_sqlite_demo.cpp -lsqlite3
运行
./a.out test.db "SELECT * FROM student;"
或
./a.out test.db "SELECT * FROM sub;"
SQLite 的Qt接口
Qt 提供了两个类 QSqlDatabase 和 QSqlQuery 用于数据库操作,
他们的作用如下:
- QSqlDatabase 用于连接数据库。
- QSqlQuery 用于查询操作
使用步骤:
- 在 .pro 项目文件中加入:
QT += sql
来让数据库模块参加编译 - 使用
QSqlDatabase
连接数据库,并检测连接是否正常。 - 使用
QSqlQuery
调用SQL
语句进行查询等DML
操作并得到结果。
示例
sqlitewidget.h
#ifndef SQLITEWIDGET_H
#define SQLITEWIDGET_H#include <QSqlDatabase>
#include <QSqlQuery>
#include <QTextEdit>
#include <QWidget>class SQLiteWidget : public QWidget
{Q_OBJECT
public:SQLiteWidget(QWidget *parent = nullptr);~SQLiteWidget();
protected:void initSqlite(void);void initUI(void);void onSqlExecBtn(void);
private:QTextEdit * textEdit; // 用于输入SQL 语句QSqlDatabase db; // 用于记录数据库连接
};#endif // SQLITEWIDGET_H
sqlitewidget.cpp
#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>#include "sqlitewidget.h"SQLiteWidget::SQLiteWidget(QWidget *parent): QWidget(parent)
{initSqlite();initUI();
}SQLiteWidget::~SQLiteWidget()
{
}void SQLiteWidget::initSqlite(void)
{// 添加SQLITE 数据库引擎,并生成数据库对象dbdb = QSqlDatabase::addDatabase("QSQLITE");// 连接 test.db 数据库。db.setDatabaseName("../test.db");// 打开数据库,并判断是否成功连接if (db.open()) {qDebug() << "数据库连接成功!";} else {qDebug() << "数据库连接失败!";}}
void SQLiteWidget::initUI(void)
{textEdit = new QTextEdit;textEdit->setPlaceholderText("请输入SQL语句");QPushButton * btn = new QPushButton("运行SQL");QVBoxLayout * vlayout = new QVBoxLayout(this);vlayout->addWidget(textEdit);vlayout->addWidget(btn);connect(btn, &QPushButton::pressed,this, &SQLiteWidget::onSqlExecBtn);
}
void SQLiteWidget::onSqlExecBtn(void)
{// 获取用户输入的信息的纯文本。QString sql = textEdit->toPlainText();qDebug() << sql;// 创建查询对象QSqlQuery query;// 执行SQL 语句if (!query.exec(sql)) {qDebug() << "SQL 语句执行失败!";return;}// qDebug() << "查询到" << query.size() << "条记录!";// 遍历每一条数据记录while(query.next()) {// 根据 列名称返回该条记录对应的列,并转为整数。int id = query.value("id").toInt();QString name = query.value("name").toString();// 根据 列号(列索引)返回该条记录对应的列,并转为整数。int age = query.value(2).toInt();qDebug() << "id:" << id << "name:" << name<< "age:" << age;}
}