Ubuntu20使用QT6.1.1进行开发实例。主要进行界面的布局,进行MySQL8的创建和调用.本文注释比较详细,作为初学者,从本次demo开始学好QT。
文中主要文件如下所示。
S.pro
#2021.5.14,QT界面及MVC 实例demo
QT += core gui sql #表明使用哪些模块,模块就是类的集合。
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets #版本大于4的要添加widgets
CONFIG += c++11
TARGET = Ss #指定生成目标文件的名称
TEMPLATE = app #使用app模块,表明是应用程序
SOURCES += \
main.cpp \
dialog.cpp \
mysql.cpp \
simdialog.cpp
HEADERS += \
connection.h \
dialog.h \
mysql.h \
simdialog.h
FORMS += \
dialog.ui \
mysql.ui \
simdialog.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
qss.qrc
connection.h
#ifndef CONNECTION_H
#define CONNECTION_H
#include <QMessageBox> //提供一个模态对话框,用于通知用户或询问用户一个问题并接收答案。
#include <QSqlDatabase> //表示一个数据库链接
#include <QSqlQuery> //提供了对数据库记录的Select、Insert、Update、Delete操作
static bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); //静态连接
db.setHostName("127.0.0.1"); //主机名
db.setDatabaseName("test"); //数据库名
db.setUserName("root"); //用户名
db.setPassword("123123"); //密码
if (!db.open()) { //open函数创建实际的物理连接
QMessageBox::critical(0, QObject::tr("无法打开数据库"),"无法创建数据库连接! ", QMessageBox::Cancel);
return false;
}
//下面来创建表,如果 MySQL 数据库中已经存在同名的表,那么下面的代码不会执行
QSqlQuery query(db); //指定数据库
query.exec("SET NAMES 'Latin1'"); //使数据库支持中文
// 创建 course 表
query.exec("create table course (""id int primary key, ""name varchar(20),teacher varchar(20),ter varchar(20))");
query.exec("insert into course values(0, '数学', '刘老师','s')");
query.exec("insert into course values(1, '英语', '张老师','d')");
query.exec("insert into course values(2, '计算机', '李老师','ew')");
query.exec("insert into course values(3, '计算机1', '李老师1','ew2')");
query.exec("insert into course values(5, '计算机3', '李老师1','ew2')");
return true;
}
#endif // CONNECTION_H
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QStandardItemModel>
#include <QTableView>
#include <QDialog>
#include "simdialog.h"
#include "mysql.h"
#include <QPushButton>
/*
QT5-----MCV-MCD
model:
QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel:存取数据库数
据如果上面和下面的标准模型不能满足你的需要,就必须继承QAbstractItemModel、
QAbstractListModel或者QAbstractTableModel,创建自己的模型类。
view:
QListView用于显示列表,QTableView用于显示表格,QTreeView用于显示层次数据。
这些类都是QAbstractItemView的子类。
delegate:
QAbstractItemDelegate则是所有委托的抽象基类,默认的委托实现是QStyledItemDelegate。
但是,QStyledItemDelegate和QItemDelegate都可以作为视图的编辑器,二者的区别在于,
QStyledItemDelegate使用当前样式进行绘制。在实现自定义委托时,推荐使
用QStyledItemDelegate作为基类,或者结合 Qt style sheets。
#include <QAbstractItemModel>//所有模型都是它的子类,这个类定义了供视图和委托访问数据的接口
#include <QStringList> //存储简单的字符串列表
#include <QFileSystemModel> //本地系统的文件和目录信息
#include <QStandardItemModel>//用于树形结构的存储
*/
QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT //信号与槽需要用到
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private slots:
void initForm();
void RadioButtonClick(); //必须初始化
private slots:
void on_pushButton_Minimize_clicked();
void on_pushButton_Maximize_clicked();
void on_pushButton_Close_clicked();
void on_pushButton_Start_clicked();
void on_pushButton_Stop_clicked();
void on_pushButton_Set_clicked();
void on_pushButton_Debug_clicked();
void on_pushButton_Alarm_clicked();
void on_pushButton_Form_clicked();
void mySlot();
private:
Ui::Dialog *ui;
simDialog *siDialog;
mysql *mysqlwindow;
QStandardItemModel *mModel; //定义,后面得初始化
QPushButton b1;
QPushButton *b2;
};
#endif // DIALOG_H
mysql.h
#ifndef MYSQL_H
#define MYSQL_H
#include <QWidget>
#include <QSqlTableModel>
namespace Ui {
class mysql;
}
class mysql : public QWidget
{
Q_OBJECT
public:
explicit mysql(QWidget *parent = nullptr);
~mysql();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
void on_pushButton_5_clicked();
void on_pushButton_6_clicked();
void on_pushButton_7_clicked();
void on_pushButton_8_clicked();
void on_pushButton_9_clicked();
private:
Ui::mysql *ui;
QSqlTableModel *model;
};
#endif // MYSQL_H
simdialog.h
#ifndef SIMDIALOG_H
#define SIMDIALOG_H
#include <QDialog>
namespace Ui {
class simDialog;
}
class simDialog : public QDialog
{
Q_OBJECT
public:
explicit simDialog(QWidget *parent = nullptr);
~simDialog();
private slots:
void on_pushButton_clicked();
private:
Ui::simDialog *ui;
};
#endif // SIMDIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
#include <QScreen>
#include <QMenu>
#include <QMenuBar>
#include <QAction>
#include <QDebug>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QTextEdit>
#include <QDockWidget>
#include <QMainWindow>
//换行符问题解决,主要是在代码中用中文字符,导致的,加入下面代码即可。
#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif
Dialog::Dialog(QWidget *parent) //构造函数
: QDialog(parent), mModel(new QStandardItemModel()) //初始化
, ui(new Ui::Dialog)
{
// b1.setParent(this);
// b1.setText("close");
// b1.move(1,1);
//指定父对象后,直接或间接继承于QObject.子对象如果动态创建空间new,不需要手动delete.
// b2 = new QPushButton(this);
// b2->setText("sdwwe");
// //(信号发出者,指针类型/&发送者的类名::信号名字/this信号接收者/曹函数:&接收的类名::槽函数名字)
// connect(&b1,&QPushButton::pressed ,this,&Dialog::close);
// //自定义曹函数,普通函数的用法
// connect(b2,&QPushButton::released,this,&Dialog::mySlot);
// connect(b2,&QPushButton::released,&b1,&QPushButton::hide);
//this->xxx指本类的xxx
//ui->xxx指ui文件上的xxx
//如果本类包含ui文件,那么ui->xxx,this->ui->xxx一样。 //设置表头
mModel->setHorizontalHeaderItem(0, new QStandardItem(QObject::tr("Name")));
mModel->setHorizontalHeaderItem(1, new QStandardItem(QObject::tr("Type")));
mModel->setHorizontalHeaderItem(2, new QStandardItem(QObject::tr("Size")));
mModel->setHorizontalHeaderItem(3, new QStandardItem(QObject::tr("Time")));
for(int i =0;i<5;i++)
{
QList<QStandardItem *> item;
item.append(new QStandardItem(QObject::tr("次出场")));
item.append(new QStandardItem(QObject::tr("cs和s")));
item.append(new QStandardItem(QObject::tr("1009")));
item.append(new QStandardItem(QObject::tr("2021-5-14")));
mModel->appendRow(item);
}
ui->setupUi(this); //界面初始化,setupUi是我们画界面和写程序之间的桥梁。
ui->mtableView->setModel(mModel); //绑定model和view
this->initForm();
}
void Dialog::mySlot()
{
b2->setText("123");
}
Dialog::~Dialog() //析构函数
{
delete ui;
}
void Dialog::initForm()
{
//定义一个QList范型类的对象变量,里面保存的都是QRadioButton类型的指针。
//对于范型类型T,用法就要这样子T<M> a 或者T<M> *b,前者和你提问的情况一样,
//后者就是定义了一个指针,使用的时候还需要b=new T<M>
//获取当前窗口所有的QRadioButton控件,返回给Qlist容器。
//findChildren<QRadioButton *>(),就是嵌套页面上的QToolButton,不好直接引用,
//而()里是控件的objectName
QList<QRadioButton *> tbtns = ui->widgetRadio->findChildren<QRadioButton *>();
foreach (QRadioButton *btn, tbtns) {
btn->setCheckable(true);
connect(btn, SIGNAL(clicked()), this, SLOT(RadioButtonClick()));
}
ui->radioButton_Cameraview->click();
}
void Dialog::RadioButtonClick()
{
QRadioButton *b = (QRadioButton *)sender();//sender获取发出信号的对象;
QString name = b->text();
QList<QRadioButton *> tbtns = ui->widgetRadio->findChildren<QRadioButton *>();
foreach (QRadioButton *btn, tbtns) { //foreach 关键字用于遍历容器中所有的项
if (btn == b) {
btn->setChecked(true);
} else {
btn->setChecked(false);
}
}
if (name == "相机视图") {
ui->stackedWidget->setCurrentIndex(0);//按页面号打开页面
} else if (name == "详细") {
ui->stackedWidget->setCurrentIndex(1);
} else if (name == "概览") {
ui->stackedWidget->setCurrentIndex(2);
} else if (name == "分类") {
ui->stackedWidget->setCurrentIndex(3);
}
}
void Dialog::on_pushButton_Minimize_clicked()
{
this->showMinimized();
}
void Dialog::on_pushButton_Maximize_clicked()
{
static bool max = false;
static QRect location = this->geometry();
if (max) {
this->setGeometry(location); //回复窗口原大小和位置
// ui->maxBtn->setIcon(QIcon(":/MAX_.png"));
}else {
// ui->maxBtn->setIcon(QIcon(":/minMAX.png"));
location = this->geometry(); //最大化前记录窗口大小和位置
//this->setGeometry(qApp->desktop()->availableGeometry());
this->showFullScreen(); //设置窗口铺满全屏
}
max = !max;
}
void Dialog::on_pushButton_Close_clicked()
{
close();
}
void Dialog::on_pushButton_Start_clicked()
{
}
void Dialog::on_pushButton_Stop_clicked()
{
}
void Dialog::on_pushButton_Set_clicked()
{
siDialog = new simDialog(this);
siDialog->setModal(false);
siDialog->setWindowFlags(Qt::FramelessWindowHint);
siDialog->show();
}
void Dialog::on_pushButton_Debug_clicked()
{
}
void Dialog::on_pushButton_Alarm_clicked()
{
}
void Dialog::on_pushButton_Form_clicked()
{
mysqlwindow =new mysql(this);
mysqlwindow->show();
mysqlwindow->move (this->geometry().center() - mysqlwindow->rect().center());
}
main.cpp
#include "dialog.h"
//应用程序类,头文件和类名一样。
#include <QApplication>
#include <QPushButton>
#include <QtCore/QCoreApplication>
#include <QSqlDatabase>
#include <QDebug>
#include "connection.h"
int main(int argc, char *argv[])
{
//有且只有一个应用程序类的对象
QApplication a(argc, argv);
//w就是一个窗口
Dialog w; //在这里会执行Dialog的构造函数。
//隐藏窗体标题栏
w.setWindowFlags(Qt::FramelessWindowHint);
//w.setWindowTitle("XXXX你好");//设置标题
//窗口创建默认是隐藏,需要人为显示
// w.show();
if (!createConnection()) return 1;
w.showMaximized();
//设置按钮。
// QPushButton b;
// b.setText("ddd");//按钮显示
// b.setParent(&w); //指定父对象
// b.move(100,100); //移动坐标
// b.show(); //得指定父对象,不然单独显示。
//指定父对象:1,setParent 2,通过构造函数传参。
//让程序一直执行,等待用户操作,等待事件的发生。
return a.exec();
}
mysql.cpp
#include "mysql.h"
#include "ui_mysql.h"
#include <QSqlQuery>
#include <QSqlTableModel>
#include <QSqlError>
#include <QMessageBox>
mysql::mysql(QWidget *parent) :
QWidget(parent),
ui(new Ui::mysql)
{
ui->setupUi(this);
model = new QSqlTableModel(this);
model->setTable("course");
model->select();
// 设置编辑策略
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
ui->tableView->setModel(model);
}
mysql::~mysql()
{
delete ui;
}
void mysql::on_pushButton_clicked()
{
// 开始事务操作
model->database().transaction();
if (model->submitAll()) {
model->database().commit(); //提交
} else {
model->database().rollback(); //回滚
QMessageBox::warning(this, tr("tableModel"),
tr("数据库错误: %1").arg(model->lastError().text()));
}
}
void mysql::on_pushButton_2_clicked()
{
model->revertAll();
}
void mysql::on_pushButton_3_clicked()
{
// 获得表的行数
int rowNum = model->rowCount();
// 添加一行
model->insertRow(rowNum);
model->setData(model->index(rowNum,0),rowNum+1);
}
void mysql::on_pushButton_4_clicked()
{
// 获取选中的行
int curRow = ui->tableView->currentIndex().row();
// 删除该行
model->removeRow(curRow);
int ok = QMessageBox::warning(this,tr("删除当前行!"),
tr("你确定删除当前行吗? "),QMessageBox::Yes, QMessageBox::No);
if(ok == QMessageBox::No)
{ // 如果不删除, 则撤销
model->revertAll();
} else { // 否则提交, 在数据库中删除该行
model->submitAll();
}
}
void mysql::on_pushButton_5_clicked()
{
//id 属性, 即第 0 列, 升序排列
model->setSort(0, Qt::AscendingOrder);
model->select();
}
void mysql::on_pushButton_6_clicked()
{
model->setSort(0, Qt::DescendingOrder);
model->select();
}
void mysql::on_pushButton_7_clicked()
{
QString name = ui->lineEdit->text();
if(name.length()){
//根据姓名进行筛选, 一定要使用单引号
model->setFilter(QString("teacher = '%1'").arg(name));
model->select();
}else
{ QMessageBox::warning(this, tr("Warning"),tr("姓名不能为空") );
}
}
void mysql::on_pushButton_8_clicked()
{
model->setTable("course");
model->select();
}
void mysql::on_pushButton_9_clicked()
{
close();
}
simdialog.cpp
#include "simdialog.h"
#include "ui_simdialog.h"
simDialog::simDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::simDialog)
{
ui->setupUi(this);
}
simDialog::~simDialog()
{
delete ui;
}
void simDialog::on_pushButton_clicked()
{
close();
}
dialog.ui
mysql.ui
simdialog.ui