C++ QT开发 学习笔记(1)

C++ QT开发 学习笔记(1)

考试系统

创建项目

新建Qt桌面应用程序,项目名:ExamSys。

类信息:类名LoginDialog继承自QDialog

(1) ExamSys.pro

工程文件,包含当前工程的相关信息。

QDialog 是 Qt 框架中用于创建对话框的基类。对话框是一种特殊类型的窗口,通常用于短期的交互和信息交换,比如用户输入、设置选项、文件选择等。QDialog 提供了许多专为这种用途设计的特性和功能。

ExamSys.pro

QT       += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = ExamSys
TEMPLATE = app

logindialog.h

#ifndef LOGINDIALOG_H
#define LOGINDIALOG_H#include <QDialog>namespace Ui {
class LoginDialog; //Ui_LoginDialog son class, use for describe the login window detail message.
}class LoginDialog : public QDialog
{Q_OBJECT  //Support signal and slotspublic:explicit LoginDialog(QWidget *parent = 0);~LoginDialog();private:Ui::LoginDialog *ui;
};#endif // LOGINDIALOG_H

logindialog.cpp

#include "logindialog.h"
#include "ui_logindialog.h"LoginDialog::LoginDialog(QWidget *parent) :QDialog(parent),ui(new Ui::LoginDialog)
{ui->setupUi(this);
}LoginDialog::~LoginDialog()
{delete ui;
}

main.cpp

#include "logindialog.h"
#include <QApplication>
#include <examdialog.h>int main(int argc, char *argv[])
{QApplication a(argc, argv); //Define the apps objectLoginDialog w;				//Define the window objectw.show();					//Display windowreturn a.exec();			//Enter APP execeute loop
}

logindialog.ui

登录窗口界面文件。

登录界面

设计模式下添加账号、密码标签,账号、密码输入框,登录、取消按钮,并修改对象名,添加资源文件imgage.qrc,给imgLabel添加图片资源做背景。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

logindialog.cpp构造函数中设置窗体标题、风格

LoginDialog::LoginDialog(QWidget *parent) :QDialog(parent),ui(new Ui::LoginDialog)
{ui->setupUi(this);this->resize(600,400);setFixedSize(width(),height());this->setWindowTitle("Cat Exam");this->setWindowFlags(Qt::Dialog| Qt::WindowCloseButtonHint);this->setWindowFlags(Qt::Window| Qt::WindowFullscreenButtonHint);
}

在这里插入图片描述

验证邮箱地址

给登录按钮添加响应点击信号的槽方法:

设计模式下,右键单击登录按钮,选择“转到槽”,选择点击信号clicked().

给槽方法void LoginDialog::on_loginBtn_clicked()添加如下代码:

void LoginDialog::on_login_Button_clicked()
{//QMessageBox::information(this,"Hint","Slot method used");//Verify the email address username@address   ex:123980@qq.com//Symbol decalration: ^string start  &string end//+match times>=1 *match any times(include 0 times)  {n,m}match times at least n times, at most m times.QRegExp rx("^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z0-9]{2,6}$");bool res = rx.exactMatch(ui->account_edit->text());if(!res)// If failed match{QMessageBox::information(this,"Hint","Invalid email address, please reenter the email address");}else{QMessageBox::information(this,"Hint","Welcome to the CAT exam!");}

注意:需要加上头文件 include <QMessageBox>

验证账号密码 (通过账号密码保存在文档的方式)

在logindialog.cpp添加头文件

#include <QFile>

#include <QTextStream>

这两个头文件的引入有特定的目的,主要涉及到文件处理和文本数据的流式读写

编辑 void LoginDialog::on_loginBtn_clicked()方法

void LoginDialog::on_login_Button_clicked()
{//QMessageBox::information(this,"Hint","Slot method used");//Verify the email address username@address   ex:123980@qq.com//Symbol decalration: ^string start  &string end//+match times>=1 *match any times(include 0 times)  {n,m}match times at least n times, at most m times.QRegExp rx("^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z0-9]{2,6}$");bool res = rx.exactMatch(ui->account_edit->text());if(!res)// If failed match{QMessageBox::information(this,"Hint","Invalid email address, please reenter the email address");ui->account_edit->clear();ui->code_edit->clear();ui->account_edit->setFocus();return;}else{//QMessageBox::information(this,"Hint","Welcome to the cat EXAM!");QString filename;       //Account & password data fileQString strAccInput;    //User input accountQString strCode;        //User input passwordQString strLine;        //Every line read dataQStringList strList;    //Use for seperate the line from strLine for account and passwordfilename = "../account.txt";    //According to the debug folder. so need to go previous folder get account.txtstrAccInput = ui->account_edit->text();strCode = ui->code_edit->text();QFile file(filename);QTextStream stream(&file);if (file.open(QIODevice::ReadOnly | QIODevice::Text)){while(!stream.atEnd()){strLine = stream.readLine();strList = strLine.split(",");if(strAccInput == strList.at(0)){if(strCode == strList.at(1)){QMessageBox::information(this,"Hint","Welcome to the CAT Exam");file.close();return;}else{QMessageBox::information(this,"Hint","The password is wrong! Please reenter your password");ui->code_edit->clear();ui->code_edit->setFocus();file.close();return;}}}QMessageBox::information(this,"Hint","Your account is invalid to login to the Exam! Please contact admin to register you account!");ui->account_edit->clear();ui->code_edit->clear();ui->account_edit->setFocus();file.close();return;}else{QMessageBox::information(this, "Hint","Abnormal! Not able to read the account");return;}}}
  1. QRegExp - 是一个类提供了对正则表达式的支持,使得开发者能够进行复杂的模式匹配和数据提取任务。QRegExp 已经在 Qt 5 中被标记为过时(deprecated),并在后续版本中被建议用更现代且功能更强大的 QRegularExpression 类替代。不过,对于旧代码的维护或者对性能要求极高的场合,了解 QRegExp 仍然是有意义的

  2. .exactMatch - 是 QRegExp 类中的一个方法,专门用于判断给定的字符串是否完全符合正则表达式的模式。这意味着整个字符串从头到尾需要与正则表达式完全匹配,而不是只匹配字符串中的某个部分。

  3. Ui::LoginDialog 类是由 Qt 的 uic 工具自动生成的,它定义了你在 Qt Designer 中设计的界面的布局和组件。这个类通常不包含任何业务逻辑,只是纯粹的界面布局描述。业务逻辑需要在一个相应的包装类中实现,这个类通常会使用一个 Ui::LoginDialog 对象来设置和管理界面

  4. *ui 成员指针是一种管理和访问由 Qt Designer 生成的界面元素的便捷方式。

  5. QString 是 Qt 中用于处理字符串的核心类,设计以支持多语言和高效的文本操作

QString::numberQString 类的一个静态方法,用于将各种数值类型转换为 QString 对象

​ 例子:

int myInt = 255;
QString str1 = QString::number(myInt);
  1. QStringList 是 Qt 框架中的一个类,专门用于处理字符串列表。它基本上是 QList<QString> 的一个类型别名,提供了一系列便利的方法来操作字符串数组,例如排序、搜索和合并字符串。QStringList 给常见的列表操作增加了很多针对字符串特定的功能,使得处理字符串集合更加方便。

考试时间

右键单击项目名新建C++类的考试窗口类,取名ExamDialog.

在这里插入图片描述

打开考试窗口类头文件,编辑构造方法,声明Q_OBJECT宏、初始化计时器成员方法、刷新考试时间的槽方法并定义计时器、考试时间数据。

examdialog.h

#ifndef EXAMDIALOG_H
#define EXAMDIALOG_H
#include <QDialog>
#include <QTimer>class ExamDialog : public QDialog
{Q_OBJECT
public:ExamDialog(QWidget* parent =0);void initTimer();private:QTimer *m_timer;    //Timer for the examint m_timeGo;       //Exam used timeprivate slots:void freshTime();};#endif // EXAMDIALOG_H

编辑ExamDialog类构造函数

ExamDialog::ExamDialog(QWidget* parent):QDialog(parent)
{setWindowTitle("Exam Time already used: 0 minutes 0 second");initTimer();
}

定义void initTimer()方法

void ExamDialog::initTimer()
{m_timeGo = 0;m_timer = new QTimer(this);  //this represent the current class is the 'father' of the QTimer class. So when current class is deconstruct, the QTimer class will also deconstructed.m_timer->setInterval(1000);m_timer->start();connect(m_timer,SIGNAL(timeout()),this,SLOT(freshTime()));
}
  • m_timer = new QTimer(this); - 这里是分配了内存空间,括号里的(this)带入原因是为了让QTimer成为当前类的子类,以便当当前的类被消除的时候,QTimer类也会被销毁.

  • m_timer->setInterval(1000); - 这行代码设置定时器的触发间隔为 1000 毫秒(1 秒)。setInterval 方法接受一个以毫秒为单位的整数,定义了 timeout() 信号的发送频率。

  • connect(m_timer,SIGNAL(timeout()),this,SLOT(freshTime())); - 这行代码的作用是在 m_timer 的定时器超时并发出 timeout() 信号时,自动调用与之连接的 freshTime() 方法。这是实现定时任务的常见方法,例如更新界面、刷新数据、或执行定时检查等。

定义 void freshTimer()方法

void ExamDialog::freshTime()
{//Refresh the exam timem_timeGo++;QString min = QString::number(m_timeGo / 60);QString second = QString::number(m_timeGo %60);setWindowTitle("Exam Time already used: " + min + " minutes " + second + " second");
}

编辑main.cpp文件中的main方法,并添加头文件 #include <examdialog.h>

#include "logindialog.h"
#include <QApplication>
#include <examdialog.h>int main(int argc, char *argv[])
{QApplication a(argc, argv);
//    LoginDialog w;
//    w.show();ExamDialog w;w.show();return a.exec();
}

初始化题库

examdialog.h添加头文件

#include <QTextEdit>
#include <QLabel>
#include <QRadioButton>
#include <QCheckBox>
#include <QGridLayout>

examdialog.h添加公有成员方法及私有数据

在这里插入图片描述

examdialog.cpp添加头文件

#include <QFile>
#include <QTextStream>
#include <QMessageBox>
#include <QApplication>

编辑ExamDialog类构造方法:

ExamDialog::ExamDialog(QWidget* parent):QDialog(parent)
{//Setup the font size;QFont font;font.setPointSize(12);this->setFont(font);//Setup the window bg coloursetPalette(QPalette(QColor(209,215,255)));setWindowTitle("Exam Time already used: 0 minutes 0 second");setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);resize(800,900);initTimer();initLayout();if(!initTextEditor()){QMessageBox::information(this,"Hint","Initial the question list error!");QTimer::singleShot(0,qApp,SLOT(quit()));   //qApp = current apps.}
}
  • QTFont - 在 Qt 框架中,QFont 类是用于处理字体相关属性的类。它封装了与字体相关的信息,如字体家族(如 Arial、Times New Roman 等)、字体风格(如斜体、粗体)、字体大小(点数或像素)、以及其他诸如字重、下划线、删除线等属性。

  • this->setFont(font); - 应用字体

  • setPalette(QPalette(QColor(209,215,255))); - QPalette 是 Qt 中一个非常重要的类,用于定义和管理用户界面元素的颜色方案。通过合理地使用 QPalette,开发者可以提供更丰富和符合设计需求的用户界面,增强应用程序的视觉吸引力和用户体验。

  • QTimer::singleShot 是一个非常有用的静态方法,用于在指定的延迟后执行一次给定的槽函数。这行代码实现了在程序中安排一个即刻执行的操作,该操作会导致应用程序退出

其中,0是定时器延迟的时间

qApp是全局指针,指向当前的 QApplication 实例

  • SLOT(quit()):这指定了当定时器触发时要调用的槽函数。quit()QCoreApplication(和其子类 QApplication)的一个槽

void initLayout() 成员方法添加定义:

void ExamDialog::initLayout()
{m_layout = new QGridLayout(this);m_layout->setSpacing(10);   //Setup the taskbar spacingm_layout->setMargin(10);    //Setup the window and the taskbar spacing
}

bool initTextEdit()添加成员方法:

bool ExamDialog::initTextEditor()
{QString strLine;    //Save the document read row dataQStringList strList;QString filename("../exam.txt");QFile file(filename);QTextStream stream(&file);stream.setCodec("UTF-8");if(file.open(QIODevice::ReadOnly | QIODevice::Text)){m_textEdit = new QTextEdit(this);m_textEdit->setReadOnly(true);QString strText;        //Used for saving the displayed data from the editorint nLines = 0;while(!stream.atEnd()){//Filter out the first row.if(nLines == 0){stream.readLine();nLines++;continue;}//Filter out the answer rowif((nLines >=6 && nLines <=6 *9 && (nLines % 6 ==0)) || (nLines == 6*9 +4) ){strLine = stream.readLine();strList = strLine.split(" ");m_answerList.append(strList.at(1));strText += "\n";nLines++;continue;}strText += stream.readLine();strText += "\n";nLines++;}m_textEdit->setText(strText);m_layout->addWidget(m_textEdit,0,0,1,10);file.close();return true;}else{return false;}
}
  • setCodec("UTF-8") 方法用于指定文本流应该使用的字符编码。这是确保文本数据以正确的格式读取和写入的关键设置

  • QTextEdit 类是一个富文本编辑器部件,提供了显示和编辑格式化文本的功能。这个类是基于 QWidget,可以用来处理纯文本和富文本,如 HTML

  • m_textEdit->setReadOnly(true) - 让文本无法被修改

  • setText() 方法属于 QTextEdit(或其他文本显示控件,如 QLabelQLineEdit 等)的成员函数之一。此方法用于设置控件的文本内容。当你在 QTextEdit 上调用 setText() 方法时,它会将控件当前显示的内容替换为你提供的新字符串

  • addWidget() 用于 QGridLayout 时,它不仅指定了要添加的控件,还指定了控件在网格中的位置和它应该占据的行和列数

  • 为什么addWidget(m_textEdit,0,0,1,10); 和 addWidget(m_textEdit,0,0,1,1); 看起来窗口一样大?

    • 因为QTextEdit 控件是窗口中唯一的或主要的控件,并且没有其他控件占用额外的空间,那么窗口的大小可能主要由 QTextEdit 的内容和默认尺寸决定。如果窗口没有设置固定大小或其他控件来影响其大小,它可能自动调整大小以适应内容或维持最小可接受尺寸

布局按键

examdialog.h添加头文件、定义单选按钮分组数据、声明void initButtons()公有成员方法:

#include <QButtonGroup>``````````````public:void initButtons();private:QButtonGroup* m_btnGroups[9]; 
  • QButtonGroup类的定义是为了把某些特定的按键加到特定的组里面,以便该组只有一个选项可选

examdialog.cpp中添加void ExamDialog::initButtons()定义。

同时添加头文件

#include <QPushButton>`````````````````````````````void ExamDialog::initButtons()
{QStringList strList = {"A","B","C","D"};for(int i=0; i<10; i++){//Question Labelm_titleLabels[i] = new QLabel(this);m_titleLabels[i]->setText("Question: " + QString::number(i+1) );m_layout->addWidget(m_titleLabels[i],1,i);if(i ==9){m_radioA = new QRadioButton(this);m_radioB = new QRadioButton(this);m_radioA -> setText ("正确");m_radioB -> setText ("错误");//Determine Questionm_layout->addWidget(m_radioA,2,9);m_layout->addWidget(m_radioB,3,9);m_btnGroup[8] = new QButtonGroup(this);m_btnGroup[8]->addButton(m_radioA);m_btnGroup[8]->addButton(m_radioB);break;}if(i<8) m_btnGroup[i] = new QButtonGroup(this);//Selection questionfor(int j=0; j<4; j++){//Multiple choice questionif(i==8){m_checkBtns[j] = new QCheckBox(this);m_checkBtns[j] -> setText(strList.at(j));m_layout->addWidget(m_checkBtns[j],2+j,8);}else{//Single choice questionm_radioBtns[4*i+j] = new QRadioButton(this);m_radioBtns[4*i+j] ->setText(strList.at(j));m_layout->addWidget(m_radioBtns[4*i+j],2+j,i);m_btnGroup[i]->addButton(m_radioBtns[4*i+j]);}}}QPushButton* submitBtn = new QPushButton(this);submitBtn->setText("Submit");submitBtn->setFixedSize(100,35);m_layout->addWidget(submitBtn,6,9);
}
  • 当发现程序有问题时,可以使用Debug调试方法查看问题在哪里.
    • 快捷键F9 - 设置Breakpoint
    • 快捷键F5 - Debug模式编译程序
    • 快捷键F11-进入该行程序的内部运行
    • 快捷键F10- 运行下一行程序
    • 快捷键F9(有Breakpoint时) - 删除该Breakpoint
    • CTRL+i - 快速对齐代码

提交试卷

void ExamDialog::initButtons()定义中将提交按钮的点击信号及响应的槽方法连接起来,添加红色标注的代码。

在这里插入图片描述

  • 上述的使用信号和槽机制方法和之前做UI的方式不一样,但目的都一样?为什么?

    • void LoginDialog::on_exit_Button_clicked()
      {done(Rejected);
      }
      
    • 上述UI方法更简洁,无需无需手动编写 connect 语句

    • 但是使用手动编写 connect() 语句连接信号与槽提供了更高的灵活性。这种方式适合于需要动态创建连接或者处理逻辑较为复杂的场景

examdialog.h声明:void getScore()槽方法、bool hasNoSelect()成员方法

public:
``````````````bool haveNoSelect();
private slots:void getScore();
  • 上述的 haveNoSelect() 我个人认为也可以写在 private slots里面

void ExamDialog::getScore()定义:

void ExamDialog::getScore()
{if(haveNoSelect()){QMessageBox::information(this,"Hint","You have incompleted question, please complete it!");return;}int scores = 0;for(int i=0; i<10; i++){if(i<8)   //Single choice question score calculation{if(m_btnGroup[i]->checkedButton()->text() == m_answerList.at(i)){scores+=10;}}if(i==8)   //Multiple choice question score calculation{QString answer = m_answerList.at(i);bool hasA = false;bool hasB = false;bool hasC = false;bool hasD = false;if(answer.contains("A")) hasA = true;if(answer.contains("B")) hasB = true;if(answer.contains("C")) hasC = true;if(answer.contains("D")) hasD = true;bool checkA = m_checkBtns[0]->checkState();bool checkB = m_checkBtns[1]->checkState();bool checkC = m_checkBtns[2]->checkState();bool checkD = m_checkBtns[3]->checkState();if(hasA != checkA) continue;if(hasB != checkB) continue;if(hasC != checkC) continue;if(hasD != checkD) continue;scores += 10;}if(i==9){if(m_btnGroup[8]->checkedButton()->text() == m_answerList.at(i)){scores += 10;}}}QString str = QString::number(scores);int res = QMessageBox::information(this,"Hint","Your total scores is: " + str +" Do you want to retest?",QMessageBox::Yes | QMessageBox::No);if(res == QMessageBox::Yes){return;}else{close();}}
*  `m_btnGroup[i]->checkedButton()->text()` - 可以直接抓取该按键群组有被点击的内容
*  `answer.contains("A")` - 可以检查该answer(QString类)的内容是否含有 "A"字母
*  `int res = QMessageBox::information(this,"Hint","..........",QMessageBox::Yes | QMessageBox::No); `- 第四个参数是让这个窗口下方拥有一个互动的Yes/No按钮给用户点击. 必须注意写成这种方式的话必须返回一个结果给int.
*  `if(res == QMessageBox::Yes)` - 代表上述的用于是否点击了Yes.
  • close(); - 这属于QWidget类的方法. 主要用于关闭当前窗口.

bool ExamDialog::hasNoSelect()定义:

bool ExamDialog::haveNoSelect()
{int radioSelects = 0;for(int i=0; i<8; i++){if(m_btnGroup[i]->checkedButton()){radioSelects++;}}if(radioSelects != 8){return true;}int checkSelects = 0;for(int i =0; i<4; i++){if(m_checkBtns[i]->isChecked()){checkSelects++;}}if(checkSelects <=1){return true;}if(!m_radioA->isChecked() && !m_radioB->isChecked()){return true;}return false;
}

窗口交互

登录窗口设计模式下,给取消按钮添加相应点击信号的槽方法。

logindialog.h头文件会自动添加相应槽方法的声明。

private slots:void on_cancelBtn_clicked();

logindialog.cpp 中编辑void LoginDialog::on_loginBtn_clicked()方法,添加done方法的那一行代码。

QDialog 类中的一个方法,用于结束对话框并设置对话框的返回值void LoginDialog::on_loginBtn_clicked()
{```````````````````````if(strCode == strList.at(1)){QMessageBox::information(this,"Hint","Welcome to the CAT Exam");file.close();done(Accepted);return;}```````````````````````````````
}
  • done()是QDialog 类中的一个方法,用于结束对话框并设置对话框的返回值.

定义void on_cancelBtn_clicked()槽方法

void LoginDialog::on_exit_Button_clicked()
{done(Rejected);
}

编辑mainc.pp中的程序入口函数:

#include "logindialog.h"
#include <QApplication>
#include <examdialog.h>int main(int argc, char *argv[])
{QApplication a(argc, argv);LoginDialog logDialog;int res = logDialog.exec();if(res == QDialog::Accepted){ExamDialog* examDialog;examDialog = new ExamDialog;}else{return 0;}return a.exec();}
  • 主函数里面调用.exec 和 .show 方法都用于显示窗口,但它们的行为和用途有显著的不同
    • .show() 方法用于显示窗口,但它不会阻塞程序执行。这意味着当你调用 .show() 后,程序会继续执行后面的代码而不等待该窗口关闭..show() 方法用于显示窗口,但它不会阻塞程序执行。这意味着当你调用 .show() 后,程序会继续执行后面的代码而不等待该窗口关闭
    • .exec() 方法用于模态对话框,它会显示窗口并阻塞其后的代码执行,直到关闭该窗口。这意味着应用程序的主事件循环会等待 .exec() 方法运行的对话框关闭后才继续。.exec() 还会返回一个整数,指示对话框是如何被关闭的(例如 QDialog::AcceptedQDialog::Rejected),这有助于根据用户的响应做出适当的处理.
  • 上述代码examDialog = new ExamDialog;是为了让 examDialog不会在运行时直接’'一闪而过"
    • 因为如果没有定义动态内存的话 examDialog的作用域仅在 {} 里面,一旦程序运行结束后会直接被销毁.

发布

发布之前,请大家将代码中访问数据文件的相对路径从上级目录改成当前路径,修改后再重新编译。

在这里插入图片描述

另外也在QT 的 Projects里面更改Working Directory 路径成 D:\QT\ExamSys

  1. 设置应用程序图标

    准备好login.ico文件,ExamSys.pro文件中添加如下一行的代码

    QT       += core gui
    RC_ICONS += beluga-cat-meme.ico
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    

​ 编译运行即可。

​ 注意:使用在线转icon方法

  1. 手动发布

    文件清单:

    ExamSys.exe

    account.txt、exam.txt

    Qt5Core.dll、Qt5Gui.dll、Qt5Widgets.dll

    libstdc+±6.dll、libwinpthread-1.dll、libgcc_s_sjlj-1.dll、libgcc_s_dw2-1.dll

    注意:运行时提示缺少xxx库,就补上xxx库,此清单仅可用于有Qt环境的电脑上运行。

    缺少的动态库路径(根据自己的实际安装路径查找):

    在这里插入图片描述

  2. windeployqt发布

    以下为桌面建立一个exam发布文件夹,将ExamSys.exe及account.txt、exam.txt放入文件夹中。

在这里插入图片描述

解决方法:

给mingw53_32的bin目录添加环境变量(System variables->Path->Edit),然后重新打开命令窗口:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(4)NSIS发布

  1. 在步骤(3)(windeployqt方法)发布的文件夹中添加程序安装图标、卸载图标及License.txt文件.如下图

在这里插入图片描述

注意生成图标时候像素选择大点,如256*256。License.txt文件内容可自行定义。

  1. 安装NSIS
  2. 安装脚本编辑器
  3. 运行脚本编辑器(NisEdit)
  4. 生成脚本文件

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

二、计划任务

1.什么是计划任务 对于一些特定的任务&#xff0c;可以设定任务&#xff0c;让服务在规定时间去执行 2.windows中的计划任务 打开控制面板》管理工具》任务计划程序》创建基本任务 3.linux中的计划任务 周期性的计划crontab crontab -l :显示当前的计划惹怒我 -e&#…

大健康产业运营模式|大健康行业商业模式|健康管理盈利模式

大家好&#xff01;今天我们来聊聊如何在大健康行业中选择一个适合自己的商业模式&#xff0c;从保健、医疗、健身、美容、养老等方面快速发展并取得成功。 首先&#xff0c;大健康行业涵盖了很多领域&#xff0c;但最核心的是保健和医疗&#xff0c;这两者是保障大家健康的基础…

通过maven基于springboot项目构建脚手架archetype

1、引入脚手架构建的插件依赖 <!--构建脚手架archetype--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-archetype-plugin</artifactId><version>3.2.1</version></plugin><plugin><…

【Visual Studio】Visual Studio使用技巧及报错解决合集

目录 目录 一.概述 二.Visual Studio报错问题及解决方法 三.Visual Studio操作过程中遇到的问题及解决方法 四.Visual Studio编译优化选项 五.Visual Studio快捷键 一.概述 持续更新Visual Studio报错及解决方法&#xff0c;包括Visual Studio报错问题及解决方法、Visua…

土壤品质检测仪:守护大地之母的科技卫士

土壤&#xff0c;作为地球生命之源&#xff0c;承载着万物的生长与繁衍。然而&#xff0c;随着现代农业的快速发展&#xff0c;土壤品质问题日益凸显&#xff0c;对农作物的生长和人们的健康构成了潜在威胁。 随着环保意识的增强和农业可持续发展的需求&#xff0c;土壤品质检测…

实验8 视图创建与管理实验

一、实验目的 理解视图的概念。掌握创建、更改、删除视图的方法。掌握使用视图来访问数据的方法。 二、实验内容 在job数据库中&#xff0c;有聘任人员信息表&#xff1a;Work_lnfo表&#xff0c;其表结构如下表所示&#xff1a; 其中表中练习数据如下&#xff1a; 1.‘张明…

中霖教育:2024年中级经济师备考还来得及吗?

【中霖教育怎么样】【中霖教育口碑】 2024年的中级经济师考试还未开始报名&#xff0c;考试时间在11月16日-11月17日进行&#xff0c;考生目前距离考试还有半年的准备时间。不同的考生人群针对性的复习方法不同&#xff0c;以下内容可以作为大家的参考。 1、零基础考生&#…

Python类与对象02:继承

1、什么是继承 上一节中我们介绍了类与对象的用法。类可以看作是一种程序内的设计图纸&#xff0c;而对象则是基于这个图纸制造出来的实体。这个过程类似于现实中的设计表格和填写表格。 现在假设你是一名设计师&#xff0c;需要迭代一款新产品。你有两个选择&#xff1a; 在…

我的六天C++外出学习记

第一天 7月7日 星期日 早晨&#xff0c;我早早起来了&#xff0c;穿好衣服吃完饭就出发了。 我从家到学校用了1H&#xff0c;迟到了&#xff01;我急急忙忙去报到。 我们中午和晚上的饭菜虽说有点贵&#xff0c;但实在太美味了&#xff0c;和我们原本初中的饭菜相比&#…

手机怎么用代理ip上网

在数字化时代&#xff0c;网络已经成为我们生活中不可或缺的一部分。然而&#xff0c;有时候出于安全、隐私或访问特定网络资源的需要&#xff0c;我们可能需要使用代理IP来上网。那么&#xff0c;什么是代理IP&#xff1f;如何在手机上设置并使用它呢&#xff1f;本文将为您详…

AI绘画,Stable Diffusion姓氏头像副业拆解,操作简单,小白也能轻松上手!

前言 嗨&#xff0c;我是月月。 说时候&#xff0c;现在副业项目层出不穷&#xff0c;但要找到一个操作简单、收益可观且具有长期潜力的项目并不容易。 今天&#xff0c;我为大家推荐一个当下非常火爆的副业项目——AI定制百家姓氏头像。这不仅是一个热门项目&#xff0c;更…

云动态摘要 2024-07-12

给您带来云厂商的最新动态,最新产品资讯和最新优惠更新。 最新优惠与活动 数据库上云优选 阿里云 2024-07-04 RDS、PolarDB、Redis、MongoDB 全系产品新用户低至首年6折起! [免费体验]智能助手ChatBI上线 腾讯云 2024-07-02 基于混元大模型打造,可通过对话方式生成可视化…

Vue3 markRaw的使用

markRaw 作用:将一个对象标记为不可以被转化为代理对象。返回该对象本身。 应用场景: 1.有些值不应被设置成响应式时,例如复杂的第三方类库等 2.当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能 3.在动态渲染组件的时候我们就可以使用 markRaw 包裹。markRaw 的…

Chromium实用技巧篇-如何下载指定版本的Chromium(一)

1. 引言 随着互联网技术的不断发展&#xff0c;网络浏览器已经成为我们日常生活中不可或缺的一部分。作为一款开源浏览器项目&#xff0c;Chromium不仅为Google Chrome提供了坚实的基础&#xff0c;也为其他许多浏览器提供了技术支持。如果您希望体验最前沿的浏览器功能或参与开…

一个很变态但是有用的变现手段:用AI技术搞电商模特图,接单接到手软~

前言 今天带大家拆解一个特别有趣的项目&#xff0c;必须得跟大家分享一下&#xff1a;用AI技术搞电商模特图。 是不是感觉挺科幻的&#xff1f;但这真不是科幻小说里的情节&#xff0c;而是咱们现实生活中已经实现的事情。 想想看&#xff0c;咱们平常在网上看到的那些漂亮…

网络基础知识--网络硬件设备介绍(含eNSP模拟器命令使用)

华为 eNSP 模拟器安装教程可参考&#xff1a;华为 eNSP 模拟器安装教程&#xff08;内含下载地址&#xff09;_ensp下载-CSDN博客 华为eNSP&#xff08;Enterprise Network Simulation Platform&#xff09;模拟器是一款由华为提供的免费网络仿真平台&#xff0c;主要用于模拟和…

虚拟机vmware网络设置

一、网络分类 打开vmware workstation网络编辑器可以知道有三种网络类型&#xff0c;分别是&#xff1a;桥接模式、nat模式、仅主机模式。 1、桥接模式 桥接模式是将主机网卡与虚拟机虚拟的网卡利用虚拟网桥进行通信。在桥接的作用下, 类似于把物理主机虚拟为一个交换机, 所有设…

【Wamp】局域网设备访问WampServer | 使用域名访问Wamp | Wamp配置HTTPS

局域网设备访问WampServer 参考&#xff1a;https://www.jianshu.com/p/d431a845e5cb 修改Apache的httpd.conf文件 D:\Academic\Wamp\program\bin\apache\apache2.4.54.2\conf\httpd.conf 搜索 Require local 和Require all denied&#xff0c;改为Require all granted <…

分布式系统中雪花ID的使用及前后台精度解决

本文介绍了雪花ID的应用场景&#xff0c;以及针对雪花id生成精度过大导致数据缺失的解决方案。 一、概念 雪花 ID是一种分布式 ID 生成策略&#xff0c;保证全局唯一&#xff0c;位数组成中含有时间戳&#xff0c;相比UUID,故也能保证自增。 二、应用场景 分库、分表、分片、…

【windows OBS开启直播】Windows搭建RTMP视频流服务(Nginx服务器版)

如果您想在windows 电脑上设置RTMP服务器&#xff0c;并使用VLC播放器播放OBS的直播流&#xff0c;您可以使用一个本地的RTMP服务器软件&#xff0c;如nginx配合nginx-rtmp-module来搭建。下面 详细介绍下如何搭建此视频流服务。 1、安装和配置本地RTMP服务器 步骤1&#xff…