当前位置: 首页 > news >正文

【Qt学习】04:QDialog

QDialog


OVERVIEW

  • QDialog
      • 一、自定义对话框
        • 1.模态对话框
        • 2.非模态对话框
        • 3.练习代码
      • 二、标准对话框
        • 1.消息对话框
        • 2.文件对话框
        • 3.颜色对话框
        • 4.字体对话框

对话框是 GUI 程序中不可或缺的组成部分,对话框通常会是一个顶层窗口出现在程序最上层,用于实现短期任务或者简单用户交互。

Qt 中使用QDialog类实现对话框,通常会设计一个类继承QDialog。如果QDialog 的 parent 为 NULL,则该对话框会作为一个顶层窗口,否则则作为其父组件的子对话框(此时其默认出现的位置是 parent 的中心),顶层窗口与非顶层窗口的区别在于,顶层窗口在任务栏会有自己的位置,而非顶层窗口则会共享其父组件的位置。

标准对话框是 Qt 内置的一系列对话框用于简化开发,有很多对话框都是通用的,比如打开文件、设置颜色、打印设置等。这些对话框在所有程序中几乎相同,因此没有必要在每一个程序中都自己实现这么一个对话框。

Qt 的内置的标准对话框大致分为以下几类:

  • QColorDialog: 选择颜色;
  • QFileDialog: 选择文件或者目录;
  • QFontDialog: 选择字体;
  • QInputDialog: 允许用户输入一个值,并将其值返回;
  • QMessageBox: 消息对话框,模态对话框,用于显示信息、询问问题等;
  • QPageSetupDialog: 为打印机提供纸张相关的选项;
  • QPrintDialog: 打印机配置;
  • QPrintPreviewDialog:打印预览;
  • QProgressDialog: 显示操作过程。

一、自定义对话框

对话框分为模态对话框和非模态对话框,

  • 模态对话框,会阻塞同一应用程序中其它窗口的输入。模态对话框很常见,比如“打开文件”功能。你可以尝试一下记事本的打开文件,当打开文件对话框出现时,我们是不能对除此对话框之外的窗口部分进行操作的。
  • 非模态对话框相反,例如查找对话框,我们可以在显示着查找对话框的同时,继续对记事本的内容进行编辑。

Qt 支持模态对话框和非模态对话框,模态与非模态的实现:

  • 使用 QDialog::exec() 实现应用程序级别的模态对话框
  • 使用 QDialog::open() 实现窗口级别的模态对话框
  • 使用 QDialog::show() 实现非模态对话框。

1.模态对话框

Qt 有两种级别的模态对话框:

  1. 应用程序级别的模态(默认):

    当该种模态的对话框出现时,用户必须首先对对话框进行交互,直到关闭对话框,然后才能访问程序中其他的窗口。

  2. 窗口级别的模态:

    该模态仅仅阻塞与对话框关联的窗口,但是依然允许用户与程序中其它窗口交互。窗口级别的模态尤其适用于多窗口模式。

调用exec()将对话框显示出来(模态对话框),当对话框出现时用户不能与主窗口进行任何交互,直到关闭了该对话框。

QDialog dialog(this);//对象创建在栈上(匿名函数释放后 dialog对象会释放)
dialog.resize(400, 300);
dialog.setWindowTitle("modal dialog");
dialog.exec();
qDebug() << "modal dialog poped up.";

2.非模态对话框

下面将 exec() 修改为 show() 定义出非模态对话框:

QDialog dialog(this);
dialog->resize(400, 300);
dialog->setWindowTitle("modalless dialog");
dialog->show();
qDebug() << "modalless dialog poped up.";

对话框竟然一闪而过,这是因为 show() 函数不会阻塞当前线程对话框会显示出来,然后函数立即返回代码继续执行。dialog 是建立在栈上的,当show()函数返回MainWindow::open()函数结束,dialog 超出作用域被析构,因此对话框消失了。

将 dialog 改成堆上建立,就不会出现这个问题了:

QDialog *dialog = new QDialog(this);//对象创建在堆区(匿名函数释放后 dialog对象不会释放)
dialog->resize(400, 300);
dialog->setWindowTitle("modalless dialog");
dialog->show();
qDebug() << "modalless dialog poped up.";

上面的代码是有问题的dialog 存在内存泄露,dialog 使用 new 在堆上分配空间却一直没有 delete。解决方案也很简单:将 MainWindow 的指针赋给 dialog 即可,利用对象树自动析构释放内存。

不过这样做存在问题:

  • 若对话框不是在一个界面类中出现,由于QWidget的parent必须是QWidget指针,就不能将普通的 C++ 类指针传给 Qt 对话框。
  • 另外如果对内存占用有严格限制,当将主窗口作为parent时,若主窗口不关闭对话框就不会被销毁,导致会一直占用内存。

在这种情景下可以设置dialog的WindowAttribute解决:函数设置对话框关闭时,自动销毁对话框。

QDialog *dialog = new QDialog(this);//对象创建在堆区(匿名函数释放后 dialog对象不会释放)
dialog->resize(400, 300);
dialog->setWindowTitle("modalless dialog");
dialog->setAttribute(Qt::WA_DeleteOnClose);//防止用户重复操作 多次在堆区开辟内存 导致内存泄露
dialog->show();
qDebug() << "modalless dialog poped up.";

3.练习代码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow) {ui->setupUi(this);//点击按钮 弹出对话框connect(ui->actionnew, &QAction::triggered, this, [=](){QDialog dialog(this);//对象创建在栈上(匿名函数释放后 dialog对象会释放)dialog.resize(400, 300);dialog.setWindowTitle("modal dialog");dialog.exec();qDebug() << "modal dialog poped up.";});connect(ui->actionopen, &QAction::triggered, this, [=](){QDialog *dialog = new QDialog(this);//对象创建在堆区(匿名函数释放后 dialog对象不会释放)dialog->resize(400, 300);dialog->setWindowTitle("modalless dialog");dialog->setAttribute(Qt::WA_DeleteOnClose);//防止用户重复操作 多次在堆区开辟内存 导致内存泄露dialog->show();qDebug() << "modalless dialog poped up.";});
}MainWindow::~MainWindow() {delete ui;
}

二、标准对话框

1.消息对话框

QMessageBox用于显示消息提示。我们一般会使用其提供的几个 static 函数:

  • about:显示关于对话框。
  • aboutQt:显示关于 Qt 对话框。该对话框用于显示有关 Qt 的信息。
  • critical:显示严重错误对话框。
  • information:与QMessageBox::critical()类似,不同之处在于这个对话框提供一个普通信息图标。
  • question:与QMessageBox::critical ()类似,不同之处在于这个对话框提供一个问号图标,并且其显示的按钮是“是”和“否”。
  • warning:与QMessageBox::critical()类似,不同之处在于这个对话框提供一个黄色叹号图标。

使用QMessageBox::question()来询问一个问题,关于函数参数的解释:

  • 这个对话框的父窗口是 this。QMessageBox是QDialog的子类,这意味着它的初始显示位置将会是在 parent 窗口的中央。

  • 第二个参数是对话框的标题。

  • 第三个参数是我们想要显示的内容。

  • 第四个参数是关联的按键类型,我们可以使用或运算符(|)指定对话框应该出现的按钮。比如我们希望是一个 Yes 和一个 No。

  • 最后一个参数指定默认选择的按钮。这个函数有一个返回值,用于确定用户点击的是哪一个按钮。按照我们的写法,应该很容易的看出,这是一个模态对话框,因此我们可以直接获取其返回值。

QMessageBox使用案例:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>
#include <QMessageBox>MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow) {ui->setupUi(this);//点击按钮 弹出对话框connect(ui->actionnew, &QAction::triggered, this, [=](){QDialog dialog(this);//对象创建在栈上(匿名函数释放后 dialog对象会释放)dialog.resize(400, 300);dialog.setWindowTitle("modal dialog");dialog.exec();qDebug() << "modal dialog poped up.";});connect(ui->actionopen, &QAction::triggered, this, [=](){QDialog *dialog = new QDialog(this);//对象创建在堆区(匿名函数释放后 dialog对象不会释放)dialog->resize(400, 300);dialog->setWindowTitle("modalless dialog");dialog->setAttribute(Qt::WA_DeleteOnClose);//防止用户重复操作 多次在堆区开辟内存 导致内存泄露dialog->show();qDebug() << "modalless dialog poped up.";});//点击按钮 弹出消息对话框connect(ui->actionwelcome, &QAction::triggered, this, [=](){QMessageBox::information(this, "welcome", "welcome to this application!~  ");qDebug() << "critical message box poped up.";});connect(ui->actionedit, &QAction::triggered, this, [=](){QMessageBox::critical(this, "sorry", "being developing, looking forward to more content.");qDebug() << "critical message box poped up.";});connect(ui->actionhelp, &QAction::triggered, this, [=](){QMessageBox::StandardButton choose;choose = QMessageBox::question(this, "question?", "Is there any problem when using this product? ");if (choose == QMessageBox::Yes) {qDebug() << "User have question about the use of the software.";} else if (choose == QMessageBox::No) {qDebug() << "User have no question about the use of the software.";}qDebug() << "question message box poped up.";});connect(ui->actionproject, &QAction::triggered, this, [=](){QMessageBox::warning(this, "warning", "project cannot be edit now.");qDebug() << "question message box poped up.";});
}MainWindow::~MainWindow() {delete ui;
}

自定义细节QMessageBox细节

QMessageBox类的 static 函数优点是方便使用,缺点是非常不灵活。只能使用简单的几种形式。为了能够定制QMessageBox细节,必须使用QMessageBox的属性设置 API。如果希望制作一个询问是否保存的对话框,可以使用如下的代码:

MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow) {ui->setupUi(this);//点击save按钮 弹出save对话框(模态对话框)connect(ui->actionsave, &QAction::triggered, this, [=](){QMessageBox msgBox(this);msgBox.setText(tr("The document has been modified."));msgBox.setInformativeText(tr("Do you want to save your changes?"));msgBox.setDetailedText(tr("Differences here..."));msgBox.setStandardButtons(QMessageBox::Save| QMessageBox::Discard| QMessageBox::Cancel);msgBox.setDefaultButton(QMessageBox::Save);int ret = msgBox.exec();switch (ret) {case QMessageBox::Save:qDebug() << "Save document!";break;case QMessageBox::Discard:qDebug() << "Discard changes!";break;case QMessageBox::Cancel:qDebug() << "Close document!";break;}});
}

msgBox 是一个建立在栈上的QMessageBox实例。

设置其主要文本信息为 The document has been modified.,informativeText 则是会在对话框中显示的简单说明文字。使用了detailedText详细信息,当我们点击了详细信息按钮时,对话框可以自动显示更多信息。

自定义的对话框的按钮有三个:保存、丢弃和取消。最后我们使用了exec()是其成为一个模态对话框,根据其返回值进行相应的操作。

2.文件对话框

  1. 首先需要创建一个带有文本编辑功能的窗口

    QAction *openAction = ui->actionopen;
    QAction *saveAction = ui->actionsave;
    //设置按钮图片
    openAction->setIcon(QIcon(":/res/img/ParticleSmoke.png"));
    saveAction->setIcon(QIcon(":/res/img/filetransfer.png"));
    //设置按钮提示tips
    openAction->setStatusTip(tr("Open an existing file"));
    saveAction->setStatusTip(tr("Save a new file"));
    //设置中心组件为textEdit
    QTextEdit *textEdit = new QTextEdit(this);
    
  2. 使用connect()函数,为这两个QAction对象添加响应的动作:

    connect(openAction, &QAction::triggered, this, &MainWindow::openFile);
    connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
    
  3. 编写核心的逻辑处理openFile()saveFile() 函数:

    //打开文件
    void MainWindow::openFile() {QString filepath = QFileDialog::getOpenFileName(this, tr("Open File"), ".", tr("Text Files(*.txt)"));if(!filepath.isEmpty()) {QFile file(filepath);if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {QMessageBox::warning(this, tr("Read File"), tr("Cannot open file:\n%1").arg(filepath));return;}QTextStream in(&file);textEdit->setText(in.readAll());file.close();} else {QMessageBox::warning(this, tr("Path"), tr("You did not select any file."));}
    }//保存文件
    void MainWindow::saveFile() {QString filepath = QFileDialog::getSaveFileName(this, tr("Open File"), ".", tr("Text Files(*.txt)"));if(!filepath.isEmpty()) {QFile file(filepath);if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {QMessageBox::warning(this, tr("Write File"), tr("Cannot open file:\n%1").arg(filepath));return;}QTextStream out(&file);out << textEdit->toPlainText();file.close();} else {QMessageBox::warning(this, tr("Path"), tr("You did not select any file."));}
    }
    
  4. 在openFile()函数中,我们使用QFileDialog::getOpenFileName()来获取需要打开的文件的路径。这个函数原型如下:

    QString getOpenFileName(QWidget * parent = 0,const QString & caption = QString(),const QString & dir = QString(),const QString & filter = QString(),QString * selectedFilter = 0,Options options = 0)
    
    • parent:父窗口,Qt 的标准对话框提供静态函数,用于返回一个模态对话框;

    • caption:对话框标题,

    • dir:对话框打开时的默认目录

      . 代表程序运行目录

      / 代表当前盘符的根目录(特指 Windows 平台;Linux 平台当然就是根目录),这个参数也可以是平台相关的,比如“C:\”等;

    • filter:过滤器,我们使用文件对话框可以浏览很多类型的文件,但是,很多时候我们仅希望打开特定类型的文件。比如,文本编辑器希望打开文本文件,图片浏览器希望打开图片文件。过滤器就是用于过滤特定的后缀名。如果我们使用“Image Files(*.jpg *.png)”,则只能显示后缀名是 jpg 或者 png 的文件。如果需要多个过滤器,使用“;;”分割,比如“JPEG Files(*.jpg);;PNG Files(*.png)”;

    • selectedFilter:默认选择的过滤器;

    • options:对话框的一些参数设定,比如只显示文件夹等等,它的取值是enum QFileDialog::Option,每个选项可以使用 | 运算组合起来。

saveFile()中使用的QFileDialog::getSaveFileName()也是类似的。使用这种静态函数,在 Windows、Mac OS 上面都是直接调用本地对话框,但是 Linux 上则是QFileDialog自己的模拟。这表明如果你不使用这些静态函数,而是直接使用QFileDialog进行设置,那么得到的对话框很可能与系统对话框的外观不一致(需要注意的)。

3.颜色对话框

//颜色对话框
connect(ui->actioncolor, &QAction::triggered, this, [=](){QColor color = QColorDialog::getColor(QColor(255, 0, 0));qDebug() << "red = " << color.red() << "green = " << color.green() << "blue = " << color.blue();
});

4.字体对话框

//字体对话框
connect(ui->actionfont, &QAction::triggered, this, [=](){bool flag;QFont font = QFontDialog::getFont(&flag, QFont("方正喵呜简体", 18));qDebug() << "font-family:" << font.family() << "font-size:" << font.pointSize()<< "isBold:" << font.bold() << "isitalic:" << font.italic();qDebug() << "QFileDialog poped up.";
});

相关文章:

【Qt学习】04:QDialog

QDialog OVERVIEW QDialog一、自定义对话框1.模态对话框2.非模态对话框3.练习代码 二、标准对话框1.消息对话框2.文件对话框3.颜色对话框4.字体对话框 对话框是 GUI 程序中不可或缺的组成部分&#xff0c;对话框通常会是一个顶层窗口出现在程序最上层&#xff0c;用于实现短期任…...

如何更好的进行异常处理

背景 在实际开发中&#xff0c;我们都希望程序可以一直按照期望的流程&#xff0c;无误的走下去。但是由于不可避免的内外部因素&#xff0c;可能导致出现异常的情况&#xff0c;轻则导致报错&#xff0c;重则数据错乱、服务不可用等情况。严重影响系统的稳定性&#xff0c;甚至…...

若依微服务版部署到IDEA

1.进入若依官网&#xff0c;找到我们要下的微服务版框架 2.点击进入gitee,获取源码&#xff0c;下载到本地 3.下载到本地后&#xff0c;用Idea打开&#xff0c;点击若依官网&#xff0c;找到在线文档&#xff0c;找到微服务版本的&#xff0c;当然你不看文档&#xff0c;直接按…...

Elasticsearch 入门安装

1.Elasticsearch 是什么 The Elastic Stack, 包括 Elasticsearch、 Kibana、 Beats 和 Logstash&#xff08;也称为 ELK Stack&#xff09;。能够安全可靠地获取任何来源、任何格式的数据&#xff0c;然后实时地对数据进行搜索、分析和可视化。 Elaticsearch&#xff0c;简称为…...

【80天学习完《深入理解计算机系统》】第十一天 3.5 过程(函数调用)

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…...

LinuxUbuntu安装VMware tools Segmentation fault (core dumped)怎么解决

LinuxUbuntu安装VMware tools Segmentation fault (core dumped)怎么解决 在安装VMware Tools时遇到"Segmentation fault (core dumped)"错误&#xff0c;通常是由于兼容性问题或系统配置不正确导致的。以下是一些可能的解决方法&#xff1a; 检查VMware Tools兼容性…...

002微信小程序云开发API数据库-迁移状态查询/更新索引

文章目录 微信小程序云开发API数据库-迁移状态查询案例代码微信小程序云开发API数据库-更新索引案例代码 微信小程序云开发API数据库-迁移状态查询 在微信小程序中&#xff0c;云开发API数据库是一种方便快捷的数据库解决方案。但是&#xff0c;有时候我们可能需要将云开发数据…...

十几款拿来就能用的炫酷表白代码

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 表白代码 1、坐我女朋友好吗&#xff0c;不同意就关机.vbs2、坐我女朋友好吗&…...

证券低延时环境设置并进行性能测试

BIOS设置BIOS参考信息 关闭 logical Process Virtualization Technology 在System Profiles Settings 中System Profile 选择Performance Workload Profile 选择HPC Profile OS中信息参考在/etc/default/grub文件中添加 intel_idle.max_cstate=0 processor.max_cstate=0 idle=p…...

百度工程师浅析解码策略

作者 | Jane 导读 生成式模型的解码方法主要有2类&#xff1a;确定性方法&#xff08;如贪心搜索和波束搜索&#xff09;和随机方法。确定性方法生成的文本通常会不够自然&#xff0c;可能存在重复或过于简单的表达。而随机方法在解码过程中引入了随机性&#xff0c;以便生成更…...

windows下实现查看软件请求ip地址的方法

一、关于wmic和nestat wmic是Windows Management Instrumentation的缩写&#xff0c;是一款非常常用的用于Windows系统管理的命令行实用程序。wmic可以通过命令行操作&#xff0c;获取系统信息、安装软件、启动服务、管理进程等操作。 netstat命令是一个监控TCP/IP网络的非常有…...

【JAVA】String 类

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈Java &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; String 1. 字符串构造2. String对象的比…...

LoRA继任者ReLoRA登场,通过叠加多个低秩更新矩阵实现更高效大模型训练效果

论文链接&#xff1a; https://arxiv.org/abs/2307.05695 代码仓库&#xff1a; https://github.com/guitaricet/peft_pretraining 一段时间以来&#xff0c;大模型&#xff08;LLMs&#xff09;社区的研究人员开始关注于如何降低训练、微调和推理LLMs所需要的庞大算力&#xf…...

Elasticsearch 8.X reindex 源码剖析及提速指南

1、reindex 源码在线地址 为方便大家验证&#xff0c;这里给出 reindex github 源码地址。 https://github.com/elastic/elasticsearch/blob/001fcfb931454d760dbccff9f4d1b8d113f8708c/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java reindex 常见…...

前端组件库造轮子——Input组件开发教程

前端组件库造轮子——Input组件开发教程 前言 本系列旨在记录前端组件库开发经验&#xff0c;我们的组件库项目目前已在Github开源&#xff0c;下面是项目的部分组件。文章会详细介绍一些造组件库轮子的技巧并且最后会给出完整的演示demo。 文章旨在总结经验&#xff0c;开源…...

Day04-Vue基础-监听器-双向绑定-组件通信

Day04-Vue基础-监听器-双向绑定-组件通信 一 侦听器 语法一 <template><div>{{name}}<br><button @click="update1">修改1</button><...

Java小白基础自学阶段(持续更新...)

引言 Java作为一门广泛应用于企业级开发的编程语言&#xff0c;对初学者来说可能会感到有些复杂。然而&#xff0c;通过适当的学习方法和资源&#xff0c;即使是小白也可以轻松掌握Java的基础知识。本文将提供一些有用的建议和资源&#xff0c;帮助小白自学Java基础。 学习步骤…...

Vue自定义指令- v-loading封装

Vue自定义指令- v-loading封装 文章目录 Vue自定义指令- v-loading封装01-自定义指令自定义指令的两种注册语法&#xff1a; 02自定义指令的值03-自定义指令- v-loading指令封装 01-自定义指令 什么是自定义指令&#xff1f; 自定义指令&#xff1a;自己定义的指令&#xff0c…...

C++中提供的一些关于查找元素的函数

C中提供的所有关于查找的函数 std::find(begin(), end(), key) std::find(begin(), end(), key)&#xff1a;这个函数用于在一个范围内查找一个等于给定值的元素&#xff0c;返回一个指向该元素的迭代器&#xff0c;如果没有找到则返回范围的结束迭代器。 1.1 例如&#xff…...

Wlan——STA上线流程与802.11MAC帧讲解以及报文转发路径

目录 802.11MAC帧基本概念 802.11帧结构 802.11MAC帧的分类 管理帧 控制帧 数据帧 STA接入无线网络流程 信号扫描—管理帧 链路认证—管理帧 用户关联—管理帧 用户上线 不同802.11帧的转发路径 802.11MAC帧基本概念 802.11协议在802家族中的角色位置 其中802.3标…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...