QT使用数据库

数据库就是保存数据的文件。可以存储大量数据,包括插入数据、更新数据、截取数据等。用专业术语来说,数据库是“按照数据结构来组织、存储和管理数据的仓库”。
什么时候需要数据库?在嵌入式里,存储大量数据,或者记录数据,就需要用到数据库。比如手机的闹钟就使用到了数据库,我们设置的闹钟数据将会保存到数据库里,闹钟程序运行时会从数据库里读取出上次保存的闹钟数据。如果没有数据库,则闹钟程序关机了数据不保存在物理储存设备里,下次运行闹钟时就没有上次设置的闹钟数据,这显然是不合理的。所以我们需要用到数据库。想要在项目中使用Qt SQL模块,需要在项目配置文件里添加QT += core gui sql

Qt SQL模块为数据库提供了编程支持,Qt支持很多种常见的数据库,如MySQL、Oracle、MS SQL Server、SQLite等。Qt SQL模块里包含了很多个类,可以轻松实现数据库的连接、执行SQL语句,获取数据库里的数据与界面显示等功能,一般数据与界面之间会采用Model/View架构,很方便的显示数据界面和操作数据库。在嵌入式里,一般常用的数据库就是Sqlite3。SQLite是非常小的,是轻量级的,完全配置时小于400KB,省略可选功能配置时小于250KB。SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的SQL数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。就像其他数据库SQLite引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接。SQLite可以直接访问其存储文件。

pro文件

QT       += core gui sqlgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0SOURCES += \main.cpp \mainwindow.cpp \numberpicker.cpp \switchbutton.cppHEADERS += \mainwindow.h \numberpicker.h \switchbutton.h# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += targetRESOURCES += \res.qrc

main.cpp

#include "mainwindow.h"
#include <QApplication>
#include <QFile>
int main(int argc, char *argv[])
{QApplication a(argc, argv);/* 指定文件 */QFile file(":/style.qss");/* 判断文件是否存在 */if (file.exists() ) {/* 以只读的方式打开 */file.open(QFile::ReadOnly);/* 以字符串的方式保存读出的结果 */QString styleSheet = QLatin1String(file.readAll());/* 设置全局样式 */qApp->setStyleSheet(styleSheet);/* 关闭文件 */file.close();}MainWindow w;w.show();return a.exec();
}

 

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QSqlDatabase>
#include <QSqlQuery>
#include <QMainWindow>
#include <QDialog>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QListWidget>
#include <QLabel>
#include <QTime>
#include <QSqlTableModel>
#include "numberpicker.h"
#include "switchbutton.h"class NumberPicker;
class SwitchButton;/* ListWiget项结构体 */
struct ItemObjectInfo {/* 闹钟开关 */SwitchButton *switchButton;/* Widget容器 */QWidget *widget;/* 水平布局 */QHBoxLayout *hBoxLayout;
};class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:/* 数据库连接类 */QSqlDatabase sqlDatabase;/* 数据库操作模型 */QSqlTableModel *model;/* 时针选择器 */NumberPicker *hourPicker;/* 分钟选择器 */NumberPicker *minutePicker;/* 弹出选择时间对话框 */QDialog *alarmDialog;/* 水平布局 */QHBoxLayout *hBoxLayout[3];/* 垂直布局 */QVBoxLayout *vBoxLayout[2];/* 显示闹钟列表 */QListWidget *listWidget;/* 主Widget */QWidget *mainWidget;/* 底部Wiget */QWidget *bottomWidget;/* 弹出对话框布局窗口选择时间容器 */QWidget *timeWidget;/* 弹出对话框布局窗口按钮容器 */QWidget *btWidget;/* 添加闹钟按钮 */QPushButton *addAlarm;/* 确认按钮 */QPushButton *yesButton;/* 取消按钮 */QPushButton *cancelButton;/* listWiget项信息存储 */QVector<ItemObjectInfo> itemObjectInfo;private slots:/* 添加闹钟按钮被点击 */void addAlarmClicked();/* 列表被点击 */void listWidgetItemClicked(QListWidgetItem *);/* 确认按钮被点击 */void yesButtonClicked();/* 取消按钮被点击 */void cancelButtonClicked();/* 开关按钮点击 */void switchButtonClicked(bool);
};
#endif // MAINWINDOW_H

 MainWindow.cpp

#include "mainwindow.h"
#include <QDebug>
#include <QSqlError>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{/* 设置主窗体的显示位置与大小 */this->setGeometry(0, 0, 800, 480);/* 查看本机可用的数据库驱动 */QStringList drivers = QSqlDatabase::drivers();foreach(QString driver, drivers) {qDebug()<<driver;}/* 以QSQLITE驱动方式打开或者创建数据库 */sqlDatabase = QSqlDatabase::addDatabase("QSQLITE");sqlDatabase.setDatabaseName("alarm.db");/* 以open的方式打开alarm.db数据库,则会创建一个alarm.db */if (!sqlDatabase.open())qDebug()<<"连接数据库错误"<<sqlDatabase.lastError()<<endl;elseqDebug()<<"连接数据库成功"<<endl;QSqlQuery query(sqlDatabase);/* 使用指令式创建表 */query.exec("create table alarm (id int primary key, time vchar(15), flag vchar(5))");/* 以指令的方式插入数据 *///query.exec("insert into alarm values(0, '06:00', 'false')");model = new QSqlTableModel(this, sqlDatabase);/* 模型设置表的名字,需要与数据库的表的名字相同 */model->setTable("alarm");/* 如果有修改则同步修改到数据库,* 注意这个规则需要与tabview这样的控件才生效,* 因为tabview可以直接编辑表里的内容 */model->setEditStrategy(QSqlTableModel::OnFieldChange);/* 成功则返回true,查看数据库里是否有alarm这个表格 */model->select();/* 如果数据表数据为空,则添加两个闹钟 */if (model->rowCount() == 0) {/* 插入一行 */model->insertRow(model->rowCount());/* 在该行插入数据 */model->setData(model->index(0, 0), 1);model->setData(model->index(0, 1), "06:00");model->setData(model->index(0, 2), "false");/* 插入数据后记得提交 */model->submit();/* 再插入一行 */model->insertRow(model->rowCount());model->setData(model->index(1, 0), 2);model->setData(model->index(1, 1), "18:00");model->setData(model->index(1, 2), "true");/* 提交 */model->submit();}hourPicker = new NumberPicker(this);hourPicker->setRange(0, 24);minutePicker = new NumberPicker(this);minutePicker->setRange(0, 60);/* 标签,用于显示时&分 */QLabel *label[3];label[0] = new QLabel();label[1] = new QLabel();label[2] = new QLabel();QFont font;font.setBold(true);font.setPixelSize(10);QPalette pal;pal.setBrush(QPalette::WindowText, QColor(0, 0, 0));label[0]->setFont(font);label[1]->setFont(font);label[2]->setFont(font);label[0]->setText(" ");label[1]->setText("时");label[2]->setText("分");/* 主布局初始化 */listWidget = new QListWidget();mainWidget = new QWidget();bottomWidget = new QWidget();alarmDialog = new QDialog(this);timeWidget = new QWidget();btWidget = new QWidget();addAlarm = new QPushButton();yesButton = new QPushButton();cancelButton = new QPushButton();vBoxLayout[0] = new QVBoxLayout();vBoxLayout[1] = new QVBoxLayout();hBoxLayout[0] = new QHBoxLayout();hBoxLayout[1] = new QHBoxLayout();hBoxLayout[2] = new QHBoxLayout();addAlarm->setMaximumSize(84, 84);addAlarm->setObjectName("addAlarm");addAlarm->setMinimumSize(84, 84);bottomWidget->setMinimumHeight(84);bottomWidget->setMaximumHeight(84);yesButton->setText("确认");cancelButton->setText("取消");yesButton->setMaximumSize(100, 50);yesButton->setMinimumSize(100, 50);cancelButton->setMinimumSize(100, 50);cancelButton->setMaximumSize(100, 50);btWidget->setMaximumHeight(70);btWidget->setMinimumHeight(70);alarmDialog->setMinimumSize(300, 300);alarmDialog->setMaximumSize(300, 300);alarmDialog->setModal(true);yesButton->setObjectName("yesButton");cancelButton->setObjectName("cancelButton");/* 主布局 */vBoxLayout[0]->addWidget(listWidget);vBoxLayout[0]->addWidget(bottomWidget);vBoxLayout[0]->setContentsMargins(0, 0, 0, 0);mainWidget->setLayout(vBoxLayout[0]);setCentralWidget(mainWidget);/* 底部按钮布局 */hBoxLayout[0]->addWidget(addAlarm);hBoxLayout[0]->setContentsMargins(0, 0, 0, 0);bottomWidget->setLayout(hBoxLayout[0]);/* 对话框布局 */vBoxLayout[1]->addWidget(timeWidget);vBoxLayout[1]->addWidget(btWidget);vBoxLayout[1]->setContentsMargins(0, 0, 0, 0);alarmDialog->setLayout(vBoxLayout[1]);hBoxLayout[1]->addWidget(label[0]);hBoxLayout[1]->addWidget(hourPicker);hBoxLayout[1]->addWidget(label[1]);hBoxLayout[1]->addWidget(minutePicker);hBoxLayout[1]->addWidget(label[2]);hBoxLayout[1]->setContentsMargins(0, 0, 0, 0);timeWidget->setLayout(hBoxLayout[1]);hBoxLayout[2]->addWidget(yesButton);hBoxLayout[2]->addWidget(cancelButton);btWidget->setLayout(hBoxLayout[2]);/* 打印出闹钟数据库里的信息 */for (int i = 0; i < model->rowCount(); i++) {for (int j = 0; j < 3; j++) {QModelIndex qindex = model->index(i, j);switch (j) {case 0:qDebug()<<"第"<<model->data(qindex).toInt()<<"行数据";break;case 1:listWidget->addItem(model->data(qindex).toString());qDebug()<<"闹钟时间为:"<<model->data(qindex).toString();break;case 2:qDebug()<<"闹钟状态为:"<<model->data(qindex).toString()<<endl;if (model->data(qindex).toString() != "true")listWidget->item(i)->setTextColor(QColor(22, 22, 22, 60));elselistWidget->item(i)->setTextColor(QColor(22, 22, 22, 225));break;default:break;}}}/* 在列表里添加闹钟开关 */for (int i = 0; i < model->rowCount(); i++) {ItemObjectInfo info;info.widget = new QWidget();info.switchButton = new SwitchButton();info.hBoxLayout = new QHBoxLayout();info.switchButton->setMaximumSize(55, 30);info.switchButton->setMinimumSize(55, 30);info.hBoxLayout->setContentsMargins(0, 0, 0, 0);info.hBoxLayout->setAlignment(Qt::AlignRight);info.hBoxLayout->addWidget(info.switchButton);info.widget->setLayout(info.hBoxLayout);listWidget->setItemWidget(listWidget->item(i),info.widget);itemObjectInfo.append(info);/* 连接信号槽 */connect(info.switchButton,SIGNAL(toggled(bool)),this,SLOT(switchButtonClicked(bool)));/* 获取数据库里的闹钟开关状态 */QModelIndex qindex = model->index(i, 2);if (model->data(qindex).toBool())/* 设置列表里的闹钟开关按钮状态 */info.switchButton->setToggle(true);}/* 按钮 */connect(addAlarm, SIGNAL(clicked()), this,SLOT(addAlarmClicked()));connect(yesButton, SIGNAL(clicked()), this,SLOT(yesButtonClicked()));connect(cancelButton, SIGNAL(clicked()), this,SLOT(cancelButtonClicked()));/* 列表 */connect(listWidget,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(listWidgetItemClicked(QListWidgetItem*)));
}MainWindow::~MainWindow()
{/* 关闭数据库 */sqlDatabase.close();
}void MainWindow::addAlarmClicked()
{/* 选择时间对话框里显示当前系统时间 */hourPicker->setValue(QTime::currentTime().hour());minutePicker->setValue(QTime::currentTime().minute());/* 取消按钮显示文本为"取消" */cancelButton->setText("取消");/* 如果是点击添加闹钟的按钮,则设置闹钟列表的索引index为-1 */listWidget->setCurrentRow(-1);/* 显示对话框 */alarmDialog->show();
}void MainWindow::listWidgetItemClicked(QListWidgetItem *item)
{/* 从被点击项里获取闹钟数据 */QStringList list =listWidget->item(listWidget->row(item))->text().split(":");/* 选择时间对话框里显示被选择项的时间 */hourPicker->setValue(list.at(0).toInt());minutePicker->setValue(list.at(1).toInt());/* 取消按钮显示文本为"删除" */cancelButton->setText("删除");/* 显示闹钟选择对话框 */alarmDialog->show();/* 作用使其失去选择 */listWidget->clearSelection();
}void MainWindow::yesButtonClicked()
{/* 获取数值选择值的数据,转为字符串 */QString hour;QString minute;if (hourPicker->readValue() < 10)hour = "0" + QString::number(hourPicker->readValue()) + ":";elsehour = QString::number(hourPicker->readValue()) + ":";if (minutePicker->readValue() < 10)minute = "0" + QString::number(minutePicker->readValue());elseminute = QString::number(minutePicker->readValue());/* 如果不是选中闹钟列表的数据 */if (listWidget->currentRow() == -1) {/* 插入一行数据,闹钟时间为选择的闹钟时间 */int row = model->rowCount();/* 插入数据到数据库 */model->insertRow(row);model->setData(model->index(row, 0), row + 1);model->setData(model->index(row, 1), hour + minute);model->setData(model->index(row, 2), "true");model->submit();/* 添加闹钟到列表 */listWidget->addItem(hour + minute);/* 添加到容器 */ItemObjectInfo info;info.widget = new QWidget();info.switchButton = new SwitchButton();info.hBoxLayout = new QHBoxLayout();info.switchButton->setMaximumSize(55, 30);info.switchButton->setMinimumSize(55, 30);info.hBoxLayout->setContentsMargins(0, 0, 0, 0);info.hBoxLayout->setAlignment(Qt::AlignRight);info.hBoxLayout->addWidget(info.switchButton);info.widget->setLayout(info.hBoxLayout);info.switchButton->setToggle(true);/* 连接信号槽 */connect(info.switchButton, SIGNAL(toggled(bool)), this,SLOT(switchButtonClicked(bool)));listWidget->setItemWidget(listWidget->item(listWidget->count() - 1),info.widget);itemObjectInfo.append(info);} else {/* 修改数据(更新闹钟数据) */int row =  listWidget->currentRow();model->setData(model->index(row, 0), row + 1);model->setData(model->index(row, 1), hour + minute);model->setData(model->index(row, 2), "true");model->submit();/* 设置当前项的闹钟文本 */listWidget->currentItem()->setText(hour + minute);}/* 再确保提交 */if (model->isDirty())model->submitAll();/* 关闭对话框 */alarmDialog->close();
}void MainWindow::cancelButtonClicked()
{if (cancelButton->text() == "删除") {/* 删除数据库整一行数据 */model->removeRow(listWidget->currentRow());model->submit();/* 执行上面语句 */model->select();itemObjectInfo.remove(listWidget->currentRow());listWidget->takeItem(listWidget->currentRow());}/* 再确保提交 */if (model->isDirty())model->submitAll();/* 关闭对话框 */alarmDialog->close();
}/* 当点击闹钟开关时,将闹钟开关状态同步更新到数据库里 */
void MainWindow::switchButtonClicked(bool checked)
{listWidget->clearSelection();SwitchButton *button = (SwitchButton *)sender();for (int i = 0; i < itemObjectInfo.count(); i++) {if (button == itemObjectInfo.at(i).switchButton) {if (checked) {model->setData(model->index(i, 2), "true");listWidget->item(i)->setTextColor(QColor(22, 22, 22, 225));} else {model->setData(model->index(i, 2), "false");listWidget->item(i)->setTextColor(QColor(22, 22, 22, 60));}model->submit();break;}}
}

numberpicker.h

#ifndef NUMBERPICKER_H
#define NUMBERPICKER_H#include <QMainWindow>
#include <QPropertyAnimation>class NumberPicker : public QWidget
{Q_OBJECTQ_PROPERTY(int deviation READ readDeviation WRITE setDeviation )
public:NumberPicker(QWidget *parent = nullptr);~NumberPicker();/* 设置最大值与最小值的范围 */void setRange(int min, int max);/* 读取当前值 */int readValue();protected:void mousePressEvent(QMouseEvent *);void mouseMoveEvent(QMouseEvent *);void mouseReleaseEvent(QMouseEvent *);void wheelEvent(QWheelEvent *);void paintEvent(QPaintEvent *);public:/* 描绘数字 */void paintNum(QPainter &painter, int num, int deviation);/* 使选中的数字回到屏幕中间 */void homing();/* 鼠标移动偏移量,默认为0 */int readDeviation();/* 设置偏移量 */void setDeviation(int n);/* 设置字体大小 */void setNumSize(int);/* 设置间隔大小 */void setInterval(int);/* 设置分格数量,一般设置为3、5、7... */void setDevide(int);/* 设置数字颜色,设置rgb的数值 */void setNumberColor(QRgb rgb);/* 设置当前值 */void setValue(int value);signals:void currentValueChanged(int value);void deviationChange(int deviation);private:/* 最小值 */int minRange;/* 最大值 */int maxRange;/* 当前选中的值 */int currentValue;/* 鼠标是否按下 */bool isDragging;/* 偏移量,记录鼠标按下后移动的垂直距离 */int deviation;/* 鼠标按下的垂直位置 */int mouseSrcPos;/* 数字大小 */int numSize;/* 动画 */QPropertyAnimation *homingAni;/* 间隔大小 */int interval;/* 分格数量 */int devide;/* 数字颜色 */QColor numberColor;
};
#endif // NUMBERPICKER_H

numberpicker.cpp

#include <QMouseEvent>
#include <QDebug>
#include "numberpicker.h"
#include <QPainter>NumberPicker::NumberPicker(QWidget *parent) :/* 最小值默认为0 */minRange(0),/* 最大值默认60 */maxRange(60),/* 当前值默认0 */currentValue(0),/* 按下标志位为假 */isDragging(false),/* 默认偏移量为0 */deviation(0),/* 数值越大 */numSize(15),/* 间隔为1 */interval(1),/* 默认分成3格 */devide(3),/* 默认颜色黑色 */numberColor(0, 0, 0)
{setParent(parent);setMinimumSize(50, 150);homingAni = new QPropertyAnimation(this, "deviation");homingAni->setDuration(300);homingAni->setEasingCurve(QEasingCurve::OutQuad);
}NumberPicker::~NumberPicker()
{}void NumberPicker::setRange(int min, int max)
{minRange = min;maxRange = max;if (currentValue < min) {currentValue = min;}if (currentValue > max) {currentValue = max;}repaint();
}int NumberPicker::readValue()
{return currentValue;
}void NumberPicker::mousePressEvent(QMouseEvent *e)
{homingAni->stop();isDragging = true;mouseSrcPos = e->pos().y();QWidget::mousePressEvent(e);
}void NumberPicker::mouseMoveEvent(QMouseEvent *e)
{if (isDragging){deviation = e->pos().y() - mouseSrcPos;/* 若移动速度过快,则进行限制 */if (deviation > (height() - 1) / devide) {deviation = (height() - 1) / devide;} else if (deviation < -(height() - 1) / devide) {deviation = -( height() - 1) / devide;}emit deviationChange(deviation / ((height() - 1) / devide));repaint();}
}void NumberPicker::mouseReleaseEvent(QMouseEvent *)
{if (isDragging) {isDragging = false;homing();}
}void NumberPicker::wheelEvent(QWheelEvent *e)
{if (e->delta() > 0) {deviation = (this->height() - 1) / devide;} else {deviation = -(this->height() - 1) / devide;}homing();repaint();
}void NumberPicker::paintEvent(QPaintEvent *)
{QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);int Height = height() - 1;if (deviation >= Height / devide && currentValue > minRange ) {mouseSrcPos += Height / devide;deviation -= Height / devide;currentValue -= interval;/* 负数处理 */if (currentValue < 0)currentValue = maxRange + currentValue;}if (deviation <= -Height / devide && currentValue < maxRange ) {mouseSrcPos -= Height / devide;deviation += Height / devide;currentValue += interval;}if (qAbs(int(currentValue)) >= int(maxRange))currentValue = minRange;paintNum(painter, qAbs(int(currentValue + maxRange) % maxRange),deviation);paintNum(painter,qAbs((currentValue - interval + maxRange) % maxRange),deviation - Height / devide);paintNum(painter,qAbs((currentValue + interval + maxRange) % maxRange),deviation + Height / devide);for (int i = 2; i <= devide / 2; ++i) {if (qAbs(currentValue - interval * i) >= minRange) {paintNum(painter,qAbs((currentValue - interval * i + maxRange)% maxRange),deviation - Height / devide * i);}if (qAbs(currentValue + interval * i) <= maxRange) {paintNum(painter,qAbs((currentValue + interval * i + maxRange)% maxRange),deviation + Height / devide * i);}}
}void NumberPicker::paintNum(QPainter &painter, int num, int deviation)
{int Width = width() - 1;int Height = height() - 1;/* 偏移量越大,数字越小 *///int size = (Height - qAbs(deviation)) / numSize;int size = (Height - qAbs(deviation)) * numSize / 80;int transparency = 255 - 255 * qAbs(deviation) / Height;int height = Height / devide;int y = Height / 2 + deviation - height / 2;QFont font;font.setPixelSize(size);painter.setFont(font);painter.setPen(QColor(numberColor.red(),numberColor.green(),numberColor.blue(),transparency));if ( y >= 0 && y + height < Height) {//painter.drawRect(0, y, Width, height);if (num < 10)painter.drawText(QRectF(0, y, Width, height),Qt::AlignCenter,"0" + QString::number(num, 'f', 0));elsepainter.drawText(QRectF(0, y, Width, height),Qt::AlignCenter,QString::number(num, 'f', 0));}
}void NumberPicker::homing()
{if (deviation > height() / 10) {homingAni->setStartValue((height() - 1 ) / 8 - deviation);homingAni->setEndValue(0);currentValue -= interval;} else if (deviation > -height() / 10) {homingAni->setStartValue(deviation);homingAni->setEndValue(0);} else if (deviation < -height() / 10) {homingAni->setStartValue(-(height() - 1) / 8 - deviation);homingAni->setEndValue(0);currentValue += interval;}emit currentValueChanged(currentValue);homingAni->start();
}int NumberPicker::readDeviation()
{return deviation;
}void NumberPicker::setDeviation(int n)
{deviation = n;repaint();
}void NumberPicker::setNumSize(int size)
{numSize = size;repaint();
}void NumberPicker::setInterval(int n)
{interval = n;repaint();
}void NumberPicker::setDevide(int n)
{devide = n;repaint();
}void NumberPicker::setNumberColor(QRgb rgb)
{numberColor.setRgb(rgb);repaint();
}void NumberPicker::setValue(int value)
{if (value < minRange || value > maxRange) {qDebug()<<"数值设置必须在"<<minRange<<"和"<<maxRange<<"之间"<<endl;return;}currentValue = value;repaint();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/291547.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【项目技术介绍篇】若依开源项目RuoYi-Cloud后端技术介绍

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过大学刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0…

双端队列deque和vector以及list的优缺点比较

参考:https://blog.csdn.net/TWRenHao/article/details/123483085 一、vector vector具体用法详情点这里 优点&#xff1a; 支持随机访问 CPU高速环缓存命中率很高 缺点&#xff1a; 空间不够&#xff0c;便需要增容。而增容代价很大&#xff0c;还存在一定的空间浪费。 头部…

在同一个网站上自动下载多个子页面内容

一、问题现象 第一次遇到这样的问题&#xff0c;如下图&#xff1a; 即在同一个网站上下载多个内容时&#xff0c;第一个内容明明已经正常get到了&#xff0c;但开始第二个页面的查询 以后&#xff0c;原来已经查出的内容就找不到了。 二、解决办法 我不知道大家是不是遇到…

C++项目——集群聊天服务器项目(七)Model层设计、注册业务实现

在前几节的研究中&#xff0c;我们已经实现网络层与业务层分离&#xff0c;本节实现数据层与业务层分离&#xff0c;降低各层之间的耦合性&#xff0c;同时实现用户注册业务。 网络层专注于处理网络通信与读写事件 业务层专注于处理读写事件到来时所需求的各项业务 数据层专…

msvcr110.dll文件丢失要怎么办?教你多种解决msvcr110.dll文件的方法

面对“程序无法启动&#xff0c;因为电脑中缺失msvcr110.dll”的错误提示&#xff0c;你可能会觉得你的工作或者休闲时间被意外中断了&#xff0c;这确实很让人烦恼。这种问题对于很多Windows用户来说并不陌生&#xff0c;但幸运的是&#xff0c;它通常可以通过几个简单的步骤得…

node.js学习(2)

版权声明 以下文章为尚硅谷PDF资料&#xff0c;B站视频链接&#xff1a;【尚硅谷Node.js零基础视频教程&#xff0c;nodejs新手到高手】仅供个人学习交流使用。如涉及侵权问题&#xff0c;请立即与本人联系&#xff0c;本人将积极配合删除相关内容。感谢理解和支持&#xff0c;…

Python3:ModuleNotFoundError: No module named ‘elftools‘

问题背景 问题 ModuleNotFoundError: No module named ‘elftools’ 解决方法 pip3 install pyelftools 成功&#xff01;&#xff01;&#xff01;

哲♂学家带你深♂入理解c语言的编译与链接

目录 前言&#xff1a; 一、翻译环境 二、预处理 三、编译 1.词法分析 2.语法分析 3、语义分析 四、汇编 五、链接 总结&#xff1a; 前言&#xff1a; 编译和链接能够帮我们更好的理解c语言中程序执行前是如何运行的&#xff0c;今天由本哲学家带你深入理解c语言的编译…

iOS - Runloop的运行逻辑

文章目录 iOS - Runloop的运行逻辑1. 苹果官方的Runloop执行图2. Mode里面的东西2.1 Source02.2 Source12.3 Timers2.4 Observers 3. 执行流程3.1 注意点 4. Runloop休眠 iOS - Runloop的运行逻辑 1. 苹果官方的Runloop执行图 2. Mode里面的东西 2.1 Source0 触摸事件处理pe…

Unity Mesh 生成图形(一)

目录 一、概述 二、获取顶点坐标和索引 三、绘制正方形 1.显示顶点坐标 2.顶点坐标的顺序 3.顶点排序 4.绘制最终效果 结束 一、概述 Unity 的 Mesh 是用于表示三维物体的网格数据结构。它是由一系列顶点和三角形组成的网格&#xff0c;用于描述物体的形状和外观。 M…

Java8之接口默认方法

Java8之接口默认方法 一、介绍二、代码1、接口2、实现类3、测试代码4、效果 一、介绍 在Java8中&#xff0c;允许为接口方法提供一个默认的实现。必须用default修饰符标记这样一个方法。默认方法也可以调用其他方法 二、代码 1、接口 public interface PersonService {void…

python 进程、线程、协程基本使用

1、进程、线程以及协程【1】进程概念【2】线程的概念线程的生命周期进程与线程的区别 【3】协程(Coroutines) 2、多线程实现【1】threading模块【2】互斥锁【3】线程池【4】线程应用 3、多进程实现4、协程实现【1】yield与协程【2】asyncio模块【3】3.8版本【4】aiohttp 1. 并发…

EasyDarwin 、ffmpeg 音视频推流拉流;OBS视频推理软件、obs-rtspserver服务器;python读取rtsp流

参考&#xff1a;https://blog.csdn.net/N71FS1/article/details/130019563 一、EasyDarwin ffmpeg ffmpeg 推送音视频流到rtsp流服务器 EasyDarwin 作为rtsp流服务器 &#xff08;下载&#xff1a;https://www.easydarwin.org/p/easydarwin.html&#xff09;OBS 直播音视频录…

是德科技keysight N9000B 信号分析仪

181/2461/8938产品概述&#xff1a; 工程的内涵就是将各种创意有机地联系起来&#xff0c;并解决遇到的问题。 CXA 信号分析仪具有出色的实际性能&#xff0c;它是一款出类拔萃、经济高效的基本信号表征工具。 它的功能十分强大&#xff0c;为一般用途和教育行业的用户执行测试…

【Linux】体验一款开源的Linux服务器运维管理工具

今天为大家介绍一款开源的 Linux 服务器运维管理工具 - 1panel。 一、安装 根据官方那个提供的在线文档&#xff0c;这款工具的安装需要执行在线安装&#xff0c; # Redhat / CentOScurl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start…

【学习心得】神经网络知识中的符号解释

这里我对我学到的神经网络知识中&#xff0c;常见的符号做一下记录和总结&#xff0c;方便自己在后面学习中复习。下图二分类识别图像识别猫为例。为了保存一张图片&#xff0c;需要三个矩阵&#xff0c;它们分别对应图片中的红、绿、蓝三种颜色通道&#xff0c;如果图片大小为…

Docker 部署 FRP 内网穿透 实现端口映射

Frp 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、HTTPS 等多种协议&#xff0c;且支持 P2P 通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。 官网地址&#xff1a;https://github.com/fatedier/frp 准备工作…

Linux重点思考(上)--权限/解压/定时任务/性能

Linux重点思考(上&#xff09;--权限/解压/定时任务 权限修改格式chmod使用 打包解压tar -zcvf ab.tar&#xff08;打包&#xff09;tar -xvf ab.tar -C/usr &#xff08;解压&#xff09; 系统防火墙service iptables statussystemctl status iptables区别 定时任务定时任务-c…

Map集合

1、Map集合实例化 步骤&#xff1a; 导包&#xff0c;java.util.Map包通过HashMap创建对象语法格式&#xff1a; Map<引用数据类型,引用数据类型> map new HashMap<>(); HashMap类的特点&#xff1a; HashMap是一个散列表&#xff0c;它存储的…

hadoop 高可用(HA)、HDFS HA、Yarn HA

目录 hadoop 高可用(HA) HDFS高可用 HDFS高可用架构 QJM 主备切换&#xff1a; Yarn高可用 hadoop 高可用(HA) HDFS高可用 HDFS高可用架构 QJM 主备切换&#xff1a; Yarn高可用