城乡和住房建设厅网站,网站产品图怎么做,百度电视剧风云榜,宁德市人口数据库
数据库是什么#xff1f;简易言之#xff0c;就是保存数据的文件。可以存储大量数据#xff0c;包括插入数据、更 新数据、截取数据等。用专业术语来说#xff0c;数据库是“按照数据结构来组织、存储和管理数据的 仓库”。是一个长期存储在计算机内的、有组织的、…数据库
数据库是什么简易言之就是保存数据的文件。可以存储大量数据包括插入数据、更 新数据、截取数据等。用专业术语来说数据库是“按照数据结构来组织、存储和管理数据的 仓库”。是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。
什么时候需要数据库在嵌入式里存储大量数据或者记录数据就需要用到数据库。 举个简单的例子比如手机的闹钟就使用到了数据库我们设置的闹钟数据将会保存到数据库 里闹钟程序运行时会从数据库里读取出上次保存的闹钟数据。如果没有数据库则闹钟程序 关机了数据不保存在物理储存设备里下次运行闹钟时就没有上次设置的闹钟数据这显然是 不合理的。所以我们需要用到数据库。
本章认为读者已经基本了解数据库已经对数据库有一定的认识如果没有对数据库了解 请自行学习毕竟本书是讲 Qt 的不是讲数据库数据库知识很多而我们只是讲解 Qt 怎么 去用数据库对数据库的简单操作目的就是在 Qt 里使用数据库
想要在项目中使用 Qt SQL 模块需要在项目配置文件里添加如下语句。 QT core gui sql
Qt SQL 简介
Qt SQL 模块为数据库提供了编程支持Qt 支持很多种常见的数据库如 MySQL、Oracle、
MS SQL Server、SQLite 等。Qt SQL 模块里包含了很多个类可以轻松实现数据库的连接、执 行 SQL 语句获取数据库里的数据与界面显示等功能一般数据与界面之间会采用 Model/View
架构从而很方便的显示数据界面和操作数据库。
在嵌入式里一般常用的数据库就是 Sqlite3。SQLite 是非常小的是轻量级的完全配置 时小于 400KiB省略可选功能配置时小于 250KiB。SQLite 是一个进程内的库实现了自给自 足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库这意 味着与其他数据库不一样您不需要在系统中配置。就像其他数据库SQLite 引擎不是一个独 立的进程可以按应用程序需求进行静态或动态连接。SQLite 可以直接访问其存储文件。
本章主要对 Sqlite3 进行实验。需要用其他数据库的请自行学习在我们正点原子里 Linux
开发板里就是用 sqlite3文件系统里不提供其他数据库类型。嵌入式一般是用 sqlite3如需要 其他类型数据库请自行移植与学习
应用实例
本章不讲解数据库中的语法本书认为读者是已经数据库语法有一定了解的了请知悉 详细声明请看本章前言本章前言。 Model(模型)复杂的事情往往可以简单化Qt 提供了 QSqlDatabase 类用于建立数据库的 连接往往以指定加载的数据库驱动然后设置数据库的登录参数如主机地址用户名、登 录密码等。这些都是服务器类型的数据库所需要做的操作。恰好单机型本地数据库类型的
Sqlite3 数据库不需要设置登录参数就可以方便的打开数据库进行操作了。在 QSqlDatabase 连接 数据库后用 QSqlTableModel 从数据库里读取出表格模型然后通过 Qt 的 QTableView 类显示 数据库的内容在我们面前。需要对数据库的数据进行修改可以使用 QSqlQuery或者直接修改
QSqlTableModel 对象修改里面的模型数据即可Qt 对数据库的基本操作流程大概是这样子 当然 Qt 提供了很多操作数据库的类我们只讲解基本的与常用的就已经足够了。下面用个图示 来再对上面的操作稍微了解一下。
实用闹钟非 QTableView 显示
一般显示数据库表格会使用 QTableView 显示但是 QTableView 适合专业看数员看且适用 于对界面操作要求不高的开发人员看。如果直接用这种表格展示给一般用户看估计用户看数 据得头皮发麻。本例就如本章开头所说结合数据库开发一个闹钟实例记录新建的闹钟数据 可以对闹钟进行增、删、改等操作。注意闹钟不做响铃操作设计。可后期使用本例自行开发 本例主要讲解不使用 QTableView 如何对数据库表格的操作。本小节开发的闹钟实例很好理解 它与手机的闹钟操作基本一模一样读者理解起来不会很吃力。本例程序篇幅过长请注意 我们只需要关注 mainwindow.h 和 mainwindow.cpp 这两个文件即可其他的.h 和.cpp 文件是笔 者为了界面的好看参考了一些博客而设计的程序。主要实现了数字选择器的功能和闹钟开关按 钮的功能因为 Qt C里它本身没有这种好看的控件所以得自行设计。由于篇幅过长数字 选择器与闹钟开关的代码不作分析有兴趣自行分析我们可以直接将它们当作普通的控件来 用即可重点是 mainwindow.h 和 mainwindow.cpp 里的数据库操作。笔者写这个例子都要好长 时间希望读者不要一口吃个胖老虎急于求成本例界面看似简单可能大多数读者可能对 数据库并不是很了解理解这个例子时笔者担心是在看天书一样抓住我们想要理解的重点 即可不必要每句都去理解
本例目的了解不使用 QTableView 的情况下也能把数据表完好展示在用户面前。
例 17_sqlite_alarm实用闹钟难度很难【为什么定义为很难笔者认为大多数读者对 数据库没有一定的了解】。项目路径为 Qt/2/17_sqlite_alarm。
项目文件 17_sqlite_alarm 文件第一行添加的代码部分如下。
17_sqlite_alarm.pro 编程后的代码
QT core gui sql
2 3 greaterThan(QT_MAJOR_VERSION, 4): QT widgets 4 5 CONFIG c11 6 7 # The following define makes your compiler emit warnings if you use 8 # any Qt feature that has been marked deprecated (the exact warnings 9 # depend on your compiler). Please consult the documentation of the 10 # deprecated API in order to know how to port your code away from it. 11 DEFINES QT_DEPRECATED_WARNINGS 12 13 # You can also make your code fail to compile if it uses deprecated APIs. 14 # In order to do so, uncomment the following line. 15 # You can also select to disable deprecated APIs only up to a certain
version of Qt. 16 #DEFINES QT_DISABLE_DEPRECATED_BEFORE0x060000 # disables all the
APIs deprecated before Qt 6.0.0 17 18 SOURCES \ 19 main.cpp \ 20 mainwindow.cpp \ 21 numberpicker.cpp \ 22 switchbutton.cpp 23 24 HEADERS \ 25 mainwindow.h \ 26 numberpicker.h \ 27 switchbutton.h 28 29 # Default rules for deployment. 30 qnx: target.path /tmp/$${TARGET}/bin 31 else: unix:!android: target.path /opt/$${TARGET}/bin 32 !isEmpty(target.path): INSTALLS target 33 34 RESOURCES \ 35 res.qrc 在头文件“mainwindow.h”具体代码如下。
mainwindow.h 编程后的代码 /****************************************************************** Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. * projectName 17_sqlite_example * brief mainwindow.h * author Deng Zhimao
* email 1252699831qq.com * net www.openedv.com * date 2021-05-15 *******************************************************************/ 1 #ifndef MAINWINDOW_H 2 #define MAINWINDOW_H 3 4 #include QSqlDatabase 5 #include QSqlQuery 6 #include QMainWindow 7 #include QDialog 8 #include QHBoxLayout 9 #include QVBoxLayout 10 #include QPushButton 11 #include QListWidget 12 #include QLabel 13 #include QTime 14 #include QSqlTableModel 15 #include numberpicker.h 16 #include switchbutton.h 17 18 class NumberPicker; 19 class SwitchButton; 20 21 /* ListWiget 项结构体 */ 22 struct ItemObjectInfo { 23 /* 闹钟开关 */ 24 SwitchButton *switchButton; 25 /* Widget 容器 */ 26 QWidget *widget; 27 /* 水平布局 */ 28 QHBoxLayout *hBoxLayout; 29 }; 30 31 32 class MainWindow : public QMainWindow 33 { 34 Q_OBJECT 35 36 public: 37 MainWindow(QWidget *parent nullptr); 38 ~MainWindow(); 39 40 private: 41 42 /* 数据库连接类 */ 43 QSqlDatabase sqlDatabase; 44 45 /* 数据库操作模型 */ 46 QSqlTableModel *model; 47 48 /* 时针选择器 */ 49 NumberPicker *hourPicker; 50 51 /* 分钟选择器 */ 52 NumberPicker *minutePicker; 53 54 /* 弹出选择时间对话框 */ 55 QDialog *alarmDialog; 56 57 /* 水平布局 */ 58 QHBoxLayout *hBoxLayout[3]; 59 60 /* 垂直布局 */ 61 QVBoxLayout *vBoxLayout[2]; 62 63 /* 显示闹钟列表 */ 64 QListWidget *listWidget; 65 66 /* 主 Widget */ 67 QWidget *mainWidget; 68 69 /* 底部 Wiget */ 70 QWidget *bottomWidget; 71 72 /* 弹出对话框布局窗口选择时间容器 */ 73 QWidget *timeWidget; 74 75 /* 弹出对话框布局窗口按钮容器 */ 76 QWidget *btWidget; 77 78 /* 添加闹钟按钮 */ 79 QPushButton *addAlarm; 80 81 /* 确认按钮 */ 82 QPushButton *yesButton; 83 84 /* 取消按钮 */ 85 QPushButton *cancelButton; 86 87 /* listWiget 项信息存储 */ 88 QVectorItemObjectInfo itemObjectInfo; 89 90 private slots: 91 /* 添加闹钟按钮被点击 */ 92 void addAlarmClicked(); 93 94 /* 列表被点击 */ 95 void listWidgetItemClicked(QListWidgetItem *); 96 97 /* 确认按钮被点击 */ 98 void yesButtonClicked(); 99 100 /* 取消按钮被点击 */ 101 void cancelButtonClicked(); 102 103 /* 开关按钮点击 */ 104 void switchButtonClicked(bool); 105 }; 106 #endif // MAINWINDOW_H 头文件主要声明布局用的类和数据库重要关注是 QSqlDatabase 和 QSqlTableModel。这里 声明的是全局变量。
在源文件“mainwindow.cpp”具体代码如下。
mainwindow.cpp 编程后的代码 /****************************************************************** Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. * projectName 17_sqlite_example * brief mainwindow.cpp * author Deng Zhimao * email 1252699831qq.com * net www.openedv.com * date 2021-05-15 *******************************************************************/ 1 #include mainwindow.h 2 #include QDebug 3 #include QSqlError 4 5 MainWindow::MainWindow(QWidget *parent) 6 : QMainWindow(parent) 7 { 8 /* 设置主窗体的显示位置与大小 */ 9 this-setGeometry(0, 0, 800, 480); 11 /* 查看本机可用的数据库驱动 */ 12 QStringList drivers QSqlDatabase::drivers(); 13 foreach(QString driver, drivers) { 14 qDebug()driver; 15 } 16 17 /* 以 QSQLITE 驱动方式打开或者创建数据库 */ 18 sqlDatabase QSqlDatabase::addDatabase(QSQLITE); 19 sqlDatabase.setDatabaseName(alarm.db); 20 /* 以 open 的方式打开 alarm.db 数据库则会创建一个 alarm.db */ 21 if (!sqlDatabase.open()) 22 qDebug()连接数据库错误sqlDatabase.lastError()endl; 23 else 24 qDebug()连接数据库成功endl; 25 26 QSqlQuery query(sqlDatabase); 27 /* 使用指令式创建表 */ 28 query.exec(create table alarm (id int primary key, time vchar(15),
flag vchar(5))); 29 /* 以指令的方式插入数据 */ 30 //query.exec(insert into alarm values(0, 06:00, false)); 31 32 model new QSqlTableModel(this, sqlDatabase); 33 34 /* 模型设置表的名字需要与数据库的表的名字相同 */ 35 model-setTable(alarm); 36 37 /* 如果有修改则同步修改到数据库
38 * 注意这个规则需要与 tabview 这样的控件才生效
39 * 因为 tabview 可以直接编辑表里的内容 */ 40 model-setEditStrategy(QSqlTableModel::OnFieldChange); 41 42 /* 成功则返回 true查看数据库里是否有 alarm 这个表格 */ 43 model-select(); 44 45 /* 如果数据表数据为空则添加两个闹钟 */ 46 if (model-rowCount() 0) { 47 /* 插入一行 */ 48 model-insertRow(model-rowCount()); 49 /* 在该行插入数据 */ 50 model-setData(model-index(0, 0), 1); 51 model-setData(model-index(0, 1), 06:00); 52 model-setData(model-index(0, 2), false); 53 /* 插入数据后记得提交 */ 54 model-submit(); 55 56 /* 再插入一行 */ 57 model-insertRow(model-rowCount()); 58 model-setData(model-index(1, 0), 2); 59 model-setData(model-index(1, 1), 18:00); 60 model-setData(model-index(1, 2), true); 61 /* 提交 */ 62 model-submit(); 63 } 64 65 hourPicker new NumberPicker(this); 66 hourPicker-setRange(0, 24); 67 68 minutePicker new NumberPicker(this); 69 minutePicker-setRange(0, 60); 70 71 /* 标签用于显示时分 */ 72 QLabel *label[3]; 73 label[0] new QLabel(); 74 label[1] new QLabel(); 75 label[2] new QLabel(); 76 77 QFont font; 78 font.setBold(true); 79 font.setPixelSize(10); 80 QPalette pal; 81 pal.setBrush(QPalette::WindowText, QColor(0, 0, 0)); 82 83 label[0]-setFont(font); 84 label[1]-setFont(font); 85 label[2]-setFont(font); 86 87 label[0]-setText( ); 88 label[1]-setText(时); 89 label[2]-setText(分); 90 91 /* 主布局初始化 */ 92 listWidget new QListWidget(); 93 mainWidget new QWidget(); 94 bottomWidget new QWidget(); 95 alarmDialog new QDialog(this); 96 timeWidget new QWidget(); 97 btWidget new QWidget(); 98 addAlarm new QPushButton(); 99 yesButton new QPushButton(); 100 cancelButton new QPushButton(); 101 vBoxLayout[0] new QVBoxLayout(); 102 vBoxLayout[1] new QVBoxLayout(); 103 hBoxLayout[0] new QHBoxLayout(); 104 hBoxLayout[1] new QHBoxLayout(); 105 hBoxLayout[2] new QHBoxLayout(); 106 107 addAlarm-setMaximumSize(84, 84); 108 addAlarm-setObjectName(addAlarm); 109 addAlarm-setMinimumSize(84, 84); 110 bottomWidget-setMinimumHeight(84); 111 bottomWidget-setMaximumHeight(84); 112 yesButton-setText(确认); 113 cancelButton-setText(取消); 114 yesButton-setMaximumSize(100, 50); 115 yesButton-setMinimumSize(100, 50); 116 cancelButton-setMinimumSize(100, 50); 117 cancelButton-setMaximumSize(100, 50); 118 btWidget-setMaximumHeight(70); 119 btWidget-setMinimumHeight(70); 120 alarmDialog-setMinimumSize(300, 300); 121 alarmDialog-setMaximumSize(300, 300); 122 alarmDialog-setModal(true); 123 yesButton-setObjectName(yesButton); 124 cancelButton-setObjectName(cancelButton); 125
126 /* 主布局 */ 127 vBoxLayout[0]-addWidget(listWidget); 128 vBoxLayout[0]-addWidget(bottomWidget); 129 vBoxLayout[0]-setContentsMargins(0, 0, 0, 0); 130 131 mainWidget-setLayout(vBoxLayout[0]); 132 133 setCentralWidget(mainWidget); 134 135 /* 底部按钮布局 */ 136 hBoxLayout[0]-addWidget(addAlarm); 137 hBoxLayout[0]-setContentsMargins(0, 0, 0, 0); 138 bottomWidget-setLayout(hBoxLayout[0]); 139 140 /* 对话框布局 */ 141 vBoxLayout[1]-addWidget(timeWidget); 142 vBoxLayout[1]-addWidget(btWidget); 143 vBoxLayout[1]-setContentsMargins(0, 0, 0, 0); 144 alarmDialog-setLayout(vBoxLayout[1]); 145 146 hBoxLayout[1]-addWidget(label[0]); 147 hBoxLayout[1]-addWidget(hourPicker); 148 hBoxLayout[1]-addWidget(label[1]); 149 hBoxLayout[1]-addWidget(minutePicker); 150 hBoxLayout[1]-addWidget(label[2]); 151 hBoxLayout[1]-setContentsMargins(0, 0, 0, 0); 152 timeWidget-setLayout(hBoxLayout[1]); 153 154 hBoxLayout[2]-addWidget(yesButton); 155 hBoxLayout[2]-addWidget(cancelButton); 156 157 btWidget-setLayout(hBoxLayout[2]); 158 159 /* 打印出闹钟数据库里的信息 */ 160 for (int i 0; i model-rowCount(); i) { 161 for (int j 0; j 3; j) { 162 QModelIndex qindex model-index(i, j); 163 switch (j) { 164 case 0: 165 qDebug()第model-data(qindex).toInt()行数据; 166 break; 167 case 1: 168 listWidget-addItem(model-data(qindex).toString()); 169 qDebug()闹钟时间为model-data(qindex).toString(); 170 break; 171 case 2: 172 qDebug()闹钟状态为 173 model-data(qindex).toString()endl; 174 if (model-data(qindex).toString() ! true) 175 listWidget-item(i) 176 -setTextColor(QColor(22, 22, 22, 60)); 177 else 178 listWidget-item(i) 179 -setTextColor(QColor(22, 22, 22, 225)); 180 break; 181 default: 182 break; 183 } 184 } 185 } 186 187 /* 在列表里添加闹钟开关 */ 188 for (int i 0; i model-rowCount(); i) { 189 ItemObjectInfo info; 190 info.widget new QWidget(); 191 info.switchButton new SwitchButton(); 192 info.hBoxLayout new QHBoxLayout(); 193 info.switchButton-setMaximumSize(55, 30); 194 info.switchButton-setMinimumSize(55, 30); 195 info.hBoxLayout-setContentsMargins(0, 0, 0, 0); 196 info.hBoxLayout-setAlignment(Qt::AlignRight); 197 info.hBoxLayout-addWidget(info.switchButton); 198 info.widget-setLayout(info.hBoxLayout); 199 listWidget-setItemWidget(listWidget-item(i), 200 info.widget); 201 itemObjectInfo.append(info); 202 203 /* 连接信号槽 */ 204 connect(info.switchButton, 205 SIGNAL(toggled(bool)), 206 this, 207 SLOT(switchButtonClicked(bool))); 208 209 /* 获取数据库里的闹钟开关状态 */ 210 QModelIndex qindex model-index(i, 2); 211 if (model-data(qindex).toBool()) 212 /* 设置列表里的闹钟开关按钮状态 */ 213 info.switchButton-setToggle(true); 214 } 215 216 /* 按钮 */ 217 connect(addAlarm, SIGNAL(clicked()), this, 218 SLOT(addAlarmClicked())); 219 220 connect(yesButton, SIGNAL(clicked()), this, 221 SLOT(yesButtonClicked())); 222 223 connect(cancelButton, SIGNAL(clicked()), this, 224 SLOT(cancelButtonClicked())); 225 226 /* 列表 */ 227 connect(listWidget, 228 SIGNAL(itemClicked(QListWidgetItem*)), 229 this, 230 SLOT(listWidgetItemClicked(QListWidgetItem*))); 231 } 232 233 MainWindow::~MainWindow() 234 { 235 /* 关闭数据库 */ 236 sqlDatabase.close(); 237 } 238 239 void MainWindow::addAlarmClicked() 240 { 241 /* 选择时间对话框里显示当前系统时间 */ 242 hourPicker-setValue(QTime::currentTime().hour()); 243 minutePicker-setValue(QTime::currentTime().minute()); 244 245 /* 取消按钮显示文本为取消 */ 246 cancelButton-setText(取消); 247 248 /* 如果是点击添加闹钟的按钮则设置闹钟列表的索引 index 为-1 */ 249 listWidget-setCurrentRow(-1); 250 251 /* 显示对话框 */ 252 alarmDialog-show(); 253 } 254 255 void MainWindow::listWidgetItemClicked(QListWidgetItem *item) 256 { 257 /* 从被点击项里获取闹钟数据 */ 258 QStringList list 259
listWidget-item(listWidget-row(item))-text().split(:); 260 261 /* 选择时间对话框里显示被选择项的时间 */ 262 hourPicker-setValue(list.at(0).toInt()); 263 minutePicker-setValue(list.at(1).toInt()); 264 265 /* 取消按钮显示文本为删除 */ 266 cancelButton-setText(删除); 267 268 /* 显示闹钟选择对话框 */ 269 alarmDialog-show(); 270 271 /* 作用使其失去选择 */ 272 listWidget-clearSelection(); 273 } 274 275 void MainWindow::yesButtonClicked() 276 { 277 /* 获取数值选择值的数据转为字符串 */ 278 QString hour; 279 QString minute; 280 281 if (hourPicker-readValue() 10) 282 hour 0 QString::number(hourPicker-readValue()) :; 283 else 284 hour QString::number(hourPicker-readValue()) :; 285 286 if (minutePicker-readValue() 10) 287 minute 0 QString::number(minutePicker-readValue()); 288 else 289 minute QString::number(minutePicker-readValue()); 290 291 /* 如果不是选中闹钟列表的数据 */ 292 if (listWidget-currentRow() -1) { 293 /* 插入一行数据闹钟时间为选择的闹钟时间 */ 294 int row model-rowCount(); 295 296 /* 插入数据到数据库 */ 297 model-insertRow(row); 298 model-setData(model-index(row, 0), row 1); 299 model-setData(model-index(row, 1), hour minute); 300 model-setData(model-index(row, 2), true); 301 model-submit(); 302 303 /* 添加闹钟到列表 */ 304 listWidget-addItem(hour minute); 305 306 /* 添加到容器 */ 307 ItemObjectInfo info; 308 info.widget new QWidget(); 309 info.switchButton new SwitchButton(); 310 info.hBoxLayout new QHBoxLayout(); 311 info.switchButton-setMaximumSize(55, 30); 312 info.switchButton-setMinimumSize(55, 30); 313 info.hBoxLayout-setContentsMargins(0, 0, 0, 0); 314 info.hBoxLayout-setAlignment(Qt::AlignRight); 315 info.hBoxLayout-addWidget(info.switchButton); 316 info.widget-setLayout(info.hBoxLayout); 317 info.switchButton-setToggle(true); 318 319 /* 连接信号槽 */ 320 connect(info.switchButton, SIGNAL(toggled(bool)), this, 321 SLOT(switchButtonClicked(bool))); 322 323 listWidget-setItemWidget( 324 listWidget-item(listWidget-count() - 1), 325 info.widget); 326 itemObjectInfo.append(info); 327 } else { 328 /* 修改数据更新闹钟数据 */ 329 int row listWidget-currentRow(); 330 model-setData(model-index(row, 0), row 1); 331 model-setData(model-index(row, 1), hour minute); 332 model-setData(model-index(row, 2), true); 333 model-submit(); 334 335 /* 设置当前项的闹钟文本 */ 336 listWidget-currentItem()-setText(hour minute); 337 } 338 339 /* 再确保提交 */ 340 if (model-isDirty()) 341 model-submitAll(); 342 343 /* 关闭对话框 */ 344 alarmDialog-close(); 345 } 346 347 void MainWindow::cancelButtonClicked() 348 { 349 if (cancelButton-text() 删除) { 350 /* 删除数据库整一行数据 */ 351 model-removeRow(listWidget-currentRow()); 352 model-submit(); 353 /* 执行上面语句 */ 354 model-select(); 355 itemObjectInfo.remove(listWidget-currentRow()); 356 listWidget-takeItem(listWidget-currentRow()); 357 } 358 359 /* 再确保提交 */ 360 if (model-isDirty()) 361 model-submitAll(); 362 363 /* 关闭对话框 */ 364 alarmDialog-close(); 365 } 366 367 368 /* 当点击闹钟开关时将闹钟开关状态同步更新到数据库里 */ 369 void MainWindow::switchButtonClicked(bool checked) 370 { 371 listWidget-clearSelection(); 372 373 SwitchButton *button (SwitchButton *)sender(); 374 for (int i 0; i itemObjectInfo.count(); i) { 375 if (button itemObjectInfo.at(i).switchButton) { 376 if (checked) { 377 model-setData(model-index(i, 2), true); 378 listWidget-item(i) 379 -setTextColor(QColor(22, 22, 22, 225)); 380 } else { 381 model-setData(model-index(i, 2), false); 382 listWidget-item(i) 383 -setTextColor(QColor(22, 22, 22, 60)); 384 } 385 386 model-submit(); 387 break; 388 } 389 } 390 } 第 5~231 行数据库的连接、建立模型和界面布局等。界面布局这些不再详细说这些在 前面章节已经讲过很多次。在这部分代码里我们发现没有用到 QTableView 来展示我们的闹 钟数据原因很简单因为我们的界面需要适合大众眼光而不是展示一个表格应该展示一 个闹钟列表进而笔者设计使用了 QListWidget 这个控件。恰好与手机里的闹钟的列表相似。 12~15 行查看本地主机可用的数据库驱动。一般 Qt 安装时都会自带 Sqlite3 驱动。注意 了如果本地主机没有可用的数据库则实验不可操作不可生搬硬套到其他开发板子测试。 所以查看本地主机的数据库操作是调试时候必须的 18~24 行添加一个数据库以 QSQLITE 驱动方式打开或者连接名字为 alarm.db 的数据库 文件。数据库存储的形式为一个 alarm.db 文件。 26~28 行在数据库里创建一个名字为 alarm 的表格。如果已经创建也会覆盖这个表格 名字但是不会覆盖表格内容。必须先创建表格才可以对表格的数据进行操作增删查减等。 32~43 行新建模型 model使用通过 setTable()设置的表中的数据填充模型使用指定的 过滤器和排序条件如果成功返回 true;否则返回 false。注意:调用 select()将恢复任何未提交的 更改并删除任何插入的列。
46~63 行笔者在这里判断如果是刚运行该程序发现数据库表中没有数据则默认设 置两行闹钟数据数据 ID 为 1闹钟时间为 06:00状态为关另一条是数据 ID 为 2闹钟时 间为 18:00状态为开。到这里我们就已经学会在数据库里插入数据记得插入数据后需要手动 执行 submit()函数表示提交。不提交是不会记录保存到数据库里的。 328~336 行直接设置数据库里的行数据即可覆盖该行数据的内容。 347~363 行model 对象直接移除某一行的数据就完成删除数据库里某行内容。注意可以 移除一行或者一列闹钟数据是以每行记录保存所以这里是移除一行。移除之后记得提交。 其他的内容都是一些逻辑与界面设计的内容重点讲解的是 Qt 对数据库操作的步骤。其他 内容请根据源码的注释理解即可。或者运行程序去理解本例逻辑。 main.cpp 内容如下主要是加载 qss 样式文件。
1 #include mainwindow.h 2 3 #include QApplication 4 #include QFile 5 6 int main(int argc, char *argv[]) 7 { 8 QApplication a(argc, argv); 9 /* 指定文件 */ 10 QFile file(:/style.qss); 11 12 /* 判断文件是否存在 */ 13 if (file.exists() ) { 14 /* 以只读的方式打开 */ 15 file.open(QFile::ReadOnly); 16 /* 以字符串的方式保存读出的结果 */ 17 QString styleSheet QLatin1String(file.readAll()); 18 /* 设置全局样式 */ 19 qApp-setStyleSheet(styleSheet); 20 /* 关闭文件 */ 21 file.close(); 22 } 23 24 MainWindow w; 25 w.show(); 26 return a.exec(); 27 } style.qss 样式文件如下。素材已经在源码处提供。注意下面的 style.qss 不能有注释
1 QListWidget { 2 font-size: 30px; 3 outline:none; 4 } 5 6 QListWidget::item:active { 7 background: transparent; 8 } 9 10 QListWidget::item { 11 height:80; 12 } 13 14 QListWidget::item:selected:hover { 15 background:#22222222; 16 } 17 18 QListWidget::item:selected { 19 background:transparent; 20 color:#ee222222; 21 } 22 23 QPushButton#addAlarm { 24 border-image:url(:/icons/addalarm1.png); 25 background:transparent; 26 outline: none; 27 } 28 29 QPushButton#addAlarm:hover { 30 border-image:url(:/icons/addalarm2.png); 31 } 32 33 QPushButton#yesButton { 34 border: 1px solid #22222222; 35 border-radius: 25px; 36 background:#22222222; 37 outline:none; 38 } 39 40 QPushButton#yesButton:pressed { 41 background:#44222222; 42 color:white; 43 } 44 45 QPushButton#cancelButton { 46 border: 1px solid #22222222; 47 border-radius: 25px; 48 background:#22222222; 49 outline:none; 50 } 51 52 QPushButton#cancelButton:pressed { 53 background:#44222222; 54 color:white; 55 } 56 57 QScrollBar:vertical { 58 width:30px; 59 background:rgba(255, 255, 255, 100%) 60 } 61 62 QScrollBar::handle:vertical { 63 width:30px; 64 background:rgba(200, 200, 200, 20%); 65 border-radius:15px; 66 } 67 68 QScrollBar::add-line:vertical { 69 width:0px; height:0px; 70 } 71 QScrollBar::sub-line:vertical { 72 width:0px; 73 height:0px; 74 } 75 QScrollBar::handle:vertical:hover { 76 width:30px; 77 background:rgba(200, 200, 200, 80%); 78 border-radius:15px; 79 } 80 QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical { 81 background:rgba(255, 255, 255, 100%) 82 } 其中数字选择器与闹钟开关按钮的代码代码笔者参考了一些博客优化后写成的代码。有 兴趣可以细读代码不作为本章注释讲解的代码。 数字选择器的作用是选择闹钟的时间效果如下通过上下滑动可以选择数字作为时钟的 时针和分针数据。通过点击对话框确认后存储到数据库里。 数字选择器的头文件“numberpicker.h”代码如下。 /****************************************************************** Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. * projectName NumberPicker * brief numberpicker.h * author Deng Zhimao * email 1252699831qq.com * net www.openedv.com * date 2021-05-14 *******************************************************************/ 1 #ifndef NUMBERPICKER_H 2 #define NUMBERPICKER_H 3 4 #include QMainWindow 5 #include QPropertyAnimation 6 7 class NumberPicker : public QWidget 8 { 9 Q_OBJECT 10 11 Q_PROPERTY(int deviation READ readDeviation WRITE setDeviation ) 12 public: 13 NumberPicker(QWidget *parent nullptr); 14 ~NumberPicker(); 15 16 /* 设置最大值与最小值的范围 */ 17 void setRange(int min, int max); 18 19 /* 读取当前值 */ 20 int readValue(); 21 22 protected: 23 void mousePressEvent(QMouseEvent *); 24 25 void mouseMoveEvent(QMouseEvent *); 26 27 void mouseReleaseEvent(QMouseEvent *); 28 29 void wheelEvent(QWheelEvent *); 30 31 void paintEvent(QPaintEvent *); 32 33 public: 34 /* 描绘数字 */ 35 void paintNum(QPainter painter, int num, int deviation); 36 37 /* 使选中的数字回到屏幕中间 */ 38 void homing(); 39 40 /* 鼠标移动偏移量默认为 0 */ 41 int readDeviation(); 42 43 /* 设置偏移量 */ 44 void setDeviation(int n); 45 46 /* 设置字体大小 */ 47 void setNumSize(int); 48 49 /* 设置间隔大小 */ 50 void setInterval(int); 51 52 /* 设置分格数量一般设置为 3、5、7... */ 53 void setDevide(int); 54 55 /* 设置数字颜色,设置 rgb 的数值 */ 56 void setNumberColor(QRgb rgb); 57 58 /* 设置当前值 */ 59 void setValue(int value); 60 61 signals: 62 63 void currentValueChanged(int value); 64 65 void deviationChange(int deviation); 66 67 private: 68 /* 最小值 */ 69 int minRange; 70 71 /* 最大值 */ 72 int maxRange; 73 74 /* 当前选中的值 */ 75 int currentValue; 76 77 /* 鼠标是否按下 */ 78 bool isDragging; 79 80 /* 偏移量,记录鼠标按下后移动的垂直距离 */ 81 int deviation; 82 83 /* 鼠标按下的垂直位置 */ 84 int mouseSrcPos; 85 86 /* 数字大小 */ 87 int numSize; 88 89 /* 动画 */ 90 QPropertyAnimation *homingAni; 91 92 /* 间隔大小 */ 93 int interval; 94 95 /* 分格数量 */ 96 int devide; 97 98 /* 数字颜色 */ 99 QColor numberColor; 100 }; 101 #endif // NUMBERPICKER_H 数字选择器的源文件“numberpicker.cpp”代码如下。 /****************************************************************** Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. * projectName NumberPicker * brief numberpicker.cpp * author Deng Zhimao * email 1252699831qq.com * * net www.openedv.com * date 2021-05-14 *******************************************************************/ 1 #include QMouseEvent 2 #include QDebug 3 #include numberpicker.h 4 #include QPainter 5 6 NumberPicker::NumberPicker(QWidget *parent) : 7 /* 最小值默认为 0 */ 8 minRange(0), 9 10 /* 最大值默认 60 */ 11 maxRange(60), 12 13 /* 当前值默认 0 */ 14 currentValue(0), 15 16 /* 按下标志位为假 */ 17 isDragging(false), 18 19 /* 默认偏移量为 0 */ 20 deviation(0), 21 22 /* 数值越大 */ 23 numSize(15), 24 25 /* 间隔为 1 */ 26 interval(1), 27 28 /* 默认分成 3 格 */ 29 devide(3), 30 31 /* 默认颜色黑色 */ 32 numberColor(0, 0, 0) 33 { 34 setParent(parent); 35 setMinimumSize(50, 150); 36 homingAni new QPropertyAnimation(this, deviation); 37 homingAni-setDuration(300); 38 homingAni-setEasingCurve(QEasingCurve::OutQuad); 39 } 40 41 NumberPicker::~NumberPicker() 42 { 43 44 } 45 46 void NumberPicker::setRange(int min, int max) 47 { 48 minRange min; 49 maxRange max; 50 if (currentValue min) { 51 currentValue min; 52 } 53 if (currentValue max) { 54 currentValue max; 55 }
56 repaint(); 57 } 58 59 int NumberPicker::readValue() 60 { 61 return currentValue; 62 } 63 64 void NumberPicker::mousePressEvent(QMouseEvent *e) 65 { 66 homingAni-stop(); 67 isDragging true; 68 mouseSrcPos e-pos().y(); 69 QWidget::mousePressEvent(e); 70 } 71 72 void NumberPicker::mouseMoveEvent(QMouseEvent *e) 73 { 74 if (isDragging){ 75 deviation e-pos().y() - mouseSrcPos; 76 77 /* 若移动速度过快则进行限制 */ 78 if (deviation (height() - 1) / devide) { 79 deviation (height() - 1) / devide; 80 } else if (deviation -(height() - 1) / devide) { 81 deviation -( height() - 1) / devide; 82 } 83 84 emit deviationChange(deviation / ((height() - 1) / devide)); 85 repaint(); 86 } 87 } 88 89 void NumberPicker::mouseReleaseEvent(QMouseEvent *) 90 { 91 if (isDragging) { 92 isDragging false; 93 homing(); 94 } 95 } 96 97 void NumberPicker::wheelEvent(QWheelEvent *e) 98 { 99 if (e-delta() 0) { 100 deviation (this-height() - 1) / devide; 101 } else { 102 deviation -(this-height() - 1) / devide; 103 } 104 105 homing(); 106 repaint(); 107 } 108 109 void NumberPicker::paintEvent(QPaintEvent *) 110 { 111 QPainter painter(this); 112 painter.setRenderHint(QPainter::Antialiasing, true); 113 int Height height() - 1; 114
115 if (deviation Height / devide currentValue minRange ) { 116 mouseSrcPos Height / devide; 117 deviation - Height / devide; 118 currentValue - interval; 119 /* 负数处理 */ 120 if (currentValue 0) 121 currentValue maxRange currentValue; 122 } 123 124 if (deviation -Height / devide currentValue maxRange ) { 125 mouseSrcPos - Height / devide; 126 deviation Height / devide; 127 currentValue interval; 128 } 129 130 if (qAbs(int(currentValue)) int(maxRange)) 131 currentValue minRange; 132 133 paintNum(painter, qAbs(int(currentValue maxRange) % maxRange), 134 deviation); 135 136 paintNum(painter, 137 qAbs((currentValue - interval maxRange) % maxRange), 138 deviation - Height / devide); 139 140 paintNum(painter, 141 qAbs((currentValue interval maxRange) % maxRange), 142 deviation Height / devide); 143 144 for (int i 2; i devide / 2; i) { 145 if (qAbs(currentValue - interval * i) minRange) { 146 paintNum(painter, 147 qAbs((currentValue - interval * i maxRange) 148 % maxRange), 149 deviation - Height / devide * i); 150 } 151 152 if (qAbs(currentValue interval * i) maxRange) { 153 paintNum(painter, 154 qAbs((currentValue interval * i maxRange) 155 % maxRange), 156 deviation Height / devide * i); 157 } 158 } 159 } 160 161 void NumberPicker::paintNum(QPainter painter, int num, int deviation) 162 { 163 int Width width() - 1; 164 int Height height() - 1; 165 166 /* 偏移量越大数字越小 */ 167 //int size (Height - qAbs(deviation)) / numSize; 168 int size (Height - qAbs(deviation)) * numSize / 80; 169 int transparency 255 - 255 * qAbs(deviation) / Height; 170 int height Height / devide; 171 int y Height / 2 deviation - height / 2; 172 173 QFont font; 174 font.setPixelSize(size); 175 painter.setFont(font); 176 painter.setPen(QColor(numberColor.red(), 177 numberColor.green(), 178 numberColor.blue(), 179 transparency)); 180 181 if ( y 0 y height Height) { 182 //painter.drawRect(0, y, Width, height); 183 if (num 10) 184 painter.drawText(QRectF(0, y, Width, height), 185 Qt::AlignCenter, 186 0 QString::number(num, f, 0)); 187 else 188 painter.drawText(QRectF(0, y, Width, height), 189 Qt::AlignCenter, 190 QString::number(num, f, 0)); 191 } 192 } 193 194 void NumberPicker::homing() 195 { 196 if (deviation height() / 10) { 197 homingAni-setStartValue((height() - 1 ) / 8 - deviation); 198 homingAni-setEndValue(0); 199 currentValue - interval; 200 } else if (deviation -height() / 10) { 201 homingAni-setStartValue(deviation); 202 homingAni-setEndValue(0); 203 } else if (deviation -height() / 10) { 204 homingAni-setStartValue(-(height() - 1) / 8 - deviation); 205 homingAni-setEndValue(0); 206 currentValue interval; 207 } 208 209 emit currentValueChanged(currentValue); 210 homingAni-start(); 211 } 212 213 int NumberPicker::readDeviation() 214 { 215 return deviation; 216 } 217 218 void NumberPicker::setDeviation(int n) 219 { 220 deviation n; 221 repaint(); 222 } 223 224 void NumberPicker::setNumSize(int size) 225 { 226 numSize size; 227 repaint(); 228 } 229 230 void NumberPicker::setInterval(int n) 231 { 232 interval n; 233 repaint(); 234 } 235 236 void NumberPicker::setDevide(int n) 237 { 238 devide n; 239 repaint(); 240 } 241 242 void NumberPicker::setNumberColor(QRgb rgb) 243 { 244 numberColor.setRgb(rgb); 245 repaint(); 246 } 247 248 void NumberPicker::setValue(int value) 249 { 250 if (value minRange || value maxRange) { 251 qDebug()数值设置必须在minRange 252 和maxRange之间endl; 253 return; 254 } 255 currentValue value; 256 repaint(); 257 } 开关按钮的效果如下。运行时有动画效果类似 IOS 手册里的开关按钮一样。
开关按钮的头文件“switchbutton.h”代码如下。 /****************************************************************** Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. * projectName 17_sqlite_example * brief switchbutton.h * author Deng Zhimao * email 1252699831qq.com * net www.openedv.com * date 2021-05-14 *******************************************************************/ 1 #ifndef SWITCHBUTTON_H 2 #define SWITCHBUTTON_H 3 4 #include QWidget 5 #include QTimer 6 7 class SwitchButton : public QWidget 8 {
9 Q_OBJECT 10 11 public: 12 explicit SwitchButton(QWidget *parent nullptr); 13 14 /* 返回开关状态 - 打开true 关闭false */ 15 bool isToggled() const; 16 17 /* 设置开关状态 */ 18 void setToggle(bool checked); 19 20 /* 设置背景颜色 */ 21 void setBackgroundColor(QColor color); 22 23 /* 设置选中颜色 */ 24 void setCheckedColor(QColor color); 25 26 /* 设置不可用颜色 */ 27 void setDisbaledColor(QColor color); 28 29 protected: 30 /* 绘制开关 */ 31 void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; 32 33 /* 鼠标按下事件 */ 34 void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; 35 36 /* 鼠标释放事件 - 切换开关状态、发射 toggled()信号 */ 37 void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; 38 39 /* 大小改变事件 */ 40 void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; 41 42 /* 缺省大小 */ 43 QSize sizeHint() const Q_DECL_OVERRIDE; 44 QSize minimumSizeHint() const Q_DECL_OVERRIDE; 45 46 signals: 47 /* 状态改变时发射信号 */ 48 void toggled(bool checked); 49 50 private slots: 51 /* 状态切换时用于产生滑动效果 */ 52 void onTimeout(); 53 54 private: 55 /* 是否选中 */ 56 bool m_bChecked; 57 58 /* 背景颜色 */ 59 QColor m_background; 60 61 /* 选中颜色 */ 62 QColor m_checkedColor; 63 64 /* 不可用颜色 */ 65 QColor m_disabledColor; 66 67 /* 拇指颜色 */ 68 QColor m_thumbColor; 69 70 /* 圆角 */ 71 qreal m_radius; 72 73 /* x 点坐标 */ 74 qreal m_nX; 75 76 /* y 点坐标 */ 77 qreal m_nY; 78 79 /* 高度 */ 80 qint16 m_nHeight; 81 82 /* 外边距 */ 83 qint16 m_nMargin; 84 85 /* 定时器 */ 86 QTimer m_timer; 87 }; 88 #endif // SWITCHBUTTON_H 开关按钮的源文件“switchbutton.cpp”代码如下。 /****************************************************************** Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.
* projectName 17_sqlite_example * brief switchbutton.cpp * author Deng Zhimao * email 1252699831qq.com * net www.openedv.com * date 2021-05-14 *******************************************************************/ 1 #include switchbutton.h 2 3 #include QPainter 4 #include QMouseEvent 5 6 SwitchButton::SwitchButton(QWidget *parent) 7 : QWidget(parent), 8 m_bChecked(false), 9 m_background(Qt::gray), 10 m_checkedColor(34, 131, 246), 11 m_disabledColor(190, 190, 190), 12 m_thumbColor(Qt::gray), 13 m_radius(12.5), 14 m_nHeight(16), 15 m_nMargin(3) 16 { 17 /* 鼠标滑过光标形状 - 手型 */ 18 setCursor(Qt::PointingHandCursor); 19 20 /* 连接信号槽 */ 21 connect(m_timer, SIGNAL(timeout()), 22 this, SLOT(onTimeout())); 23 } 24 25 /* 绘制开关 */ 26 void SwitchButton::paintEvent(QPaintEvent *event) 27 { 28 Q_UNUSED(event) 29 30 QPainter painter(this); 31 painter.setPen(Qt::NoPen); 32 painter.setRenderHint(QPainter::Antialiasing); 33 34 QPainterPath path; 35 QColor background; 36 QColor thumbColor; 37 qreal dOpacity; 38 /* 可用状态 */ 39 if (isEnabled()) { 40 /* 打开状态 */ 41 if (m_bChecked) { 42 background m_checkedColor; 43 thumbColor m_checkedColor; 44 dOpacity 0.600; 45 /* 关闭状态 */ 46 } else { 47 background m_background; 48 thumbColor m_thumbColor; 49 dOpacity 0.800; 50 } 51 /* 不可用状态 */ 52 } else { 53 background m_background; 54 dOpacity 0.260; 55 thumbColor m_disabledColor; 56 } 57 /* 绘制大椭圆 */ 58 painter.setBrush(background); 59 painter.setOpacity(dOpacity); 60 path.addRoundedRect(QRectF(m_nMargin, 61 m_nMargin, width() - 2 * m_nMargin, 62 height() - 2 * m_nMargin), 63 m_radius, m_radius); 64 painter.drawPath(path.simplified()); 65 66 /* 绘制小椭圆 */ 67 painter.setBrush(thumbColor); 68 painter.setOpacity(1.0); 69 painter.drawEllipse(QRectF(m_nX - (m_nHeight / 2), 70 m_nY - (m_nHeight / 2), 71 height(), 72 height())); 73 } 74 75 /* 鼠标按下事件 */ 76 void SwitchButton::mousePressEvent(QMouseEvent *event) 77 { 78 if (isEnabled()) { 79 if (event-buttons() Qt::LeftButton) { 80 event-accept(); 81 } else { 82 event-ignore(); 83 } 84 } 85 } 86 87 /* 鼠标释放事件 - 切换开关状态、发射 toggled()信号 */ 88 void SwitchButton::mouseReleaseEvent(QMouseEvent *event) 89 { 90 if (isEnabled()) { 91 if ((event-type() QMouseEvent::MouseButtonRelease) 92 (event-button() Qt::LeftButton)) { 93 event-accept(); 94 m_bChecked !m_bChecked; 95 emit toggled(m_bChecked); 96 m_timer.start(10); 97 } else { 98 event-ignore(); 99 } 100 } 101 } 102 103 /* 大小改变事件 */ 104 void SwitchButton::resizeEvent(QResizeEvent *event) 105 { 106 m_nX m_nHeight / 2; 107 m_nY m_nHeight / 2; 108 QWidget::resizeEvent(event); 109 } 110 111 /* 默认大小 */ 112 QSize SwitchButton::sizeHint() const 113 { 114 return minimumSizeHint(); 115 } 116 117 /* 最小大小 */ 118 QSize SwitchButton::minimumSizeHint() const 119 { 120 return QSize(2 * (m_nHeight m_nMargin), 121 m_nHeight 2 * m_nMargin); 122 } 123 124 /* 切换状态 - 滑动 */125 void SwitchButton::onTimeout() 126 { 127 if (m_bChecked) { 128 m_nX 1; 129 if (m_nX width() - m_nHeight - m_nHeight / 2 ) { 130 m_timer.stop(); 131 m_nX - 1; 132 } 133 } else { 134 m_nX - 1; 135 if (m_nX m_nHeight / 2) { 136 m_timer.stop(); 137 m_nX 1; 138 } 139 } 140 update(); 141 } 142 143 /* 返回开关状态 - 打开true 关闭false */ 144 bool SwitchButton::isToggled() const 145 { 146 return m_bChecked; 147 } 148 149 /* 设置开关状态 */ 150 void SwitchButton::setToggle(bool checked) 151 { 152 m_bChecked checked; 153 m_timer.start(10); 154 } 155 156 /* 设置背景颜色 */ 157 void SwitchButton::setBackgroundColor(QColor color) 158 { 159 m_background color; 160 } 161 162 /* 设置选中颜色 */ 163 void SwitchButton::setCheckedColor(QColor color) 164 { 165 m_checkedColor color; 166 } 167 168 /* 设置不可用颜色 */
169 void SwitchButton::setDisbaledColor(QColor color) 170 { 171 m_disabledColor color; 172 }程序运行效果
点击程序正下方的“”按钮则开始添加闹钟数据根据当前系统的时间或者滑动选择闹 钟的时间点击确认即新增一条闹钟数据。 修改或者删除数据点击要修改闹钟的数据项目弹出的对话框可以重新设置闹钟或者 删除闹钟。并保存记录到数据库里下次运行打开时会从数据库里读取保存的闹钟数据。