06-4_Qt 5.9 C++开发指南_MDI应用程序设计

文章目录

  • 1. MDI简介
  • 2. 文档窗口类 QFormDoc 的设计
  • 3. MDI主窗口设计与子窗口的使用
    • 3.1 主窗口界面设计
    • 3.2 MDI子窗口的创建与加入
    • 3.3 QMdiArea 常用功能函数
    • 3.4 MDI的信号
  • 4. 源码
    • 4.1 qwmainwindow.h
    • 4.2 qwmainwindow.cpp

1. MDI简介

传统的应用程序设计中有多文档界面(Multi-document Interface,MDI) 应用程序,Qt为设计MDI应用程序提供了支持。

本节的实例 samp6_4 是一个MDI应用程序,程序运行效果如图 6-14 所示。MDI应用程序就是在主窗口里创建多个同类型的 MDI 子窗口,这些 MDI 子窗口在主窗口里显示,并共享主窗口上的工具栏和菜单等操作功能,主窗口上的操作都针对当前活动的 MDI子窗口进行。

在这里插入图片描述

设计 MDI 应用程序需要在主窗口工作区放置一个QMdiArea 作为子窗体的容器。实例 samp6_4主窗口的工作区使用一个QMdiArea 组件,实例的子窗口类是QFormDoc,是一个使用QPlainTextEdit进行简单文本显示和编辑的窗体。

创建的 QFormDoc 窗体对象作为一个子窗口加入到 mdiArea 组件中。QMdiArea 组件类似于实例 samp6_3 中主窗口上的 tabWidget 组件,只是QMdiArea 提供更加完备的功能。更改MDI的显示模式,可以得到与实例 samp6_3 相似的以多页组件管理的MDI界面效果。

2. 文档窗口类 QFormDoc 的设计

以可视化方式创建一个基于 QWidget 的类 QFormDoc,设计可视化界面时,只放置一个QPlainTextEdit 组件,并以水平布局填充满整个窗口。这里不再用可视化的方式设计 Action,因为QFormDoc 窗口不需要创建自己的工具栏,而是使用主窗口上的工具栏按钮对 QFormDoc 窗体上的QPlainTextEdit 组件进行操作。其可视化UI设计框架如下:

在这里插入图片描述

为QFormDoc 添加一些用于文件打开和编辑操作的接口函数,QFormDoc 类的完整定义如下:

#ifndef QFORMDOC_H
#define QFORMDOC_H#include <QWidget>namespace Ui {
class QFormDoc;
}class QFormDoc : public QWidget
{Q_OBJECTprivate:QString mCurrentFile; //当前文件bool    mFileOpened=false; //文件已打开public:explicit QFormDoc(QWidget *parent = 0);~QFormDoc();void    loadFromFile(QString& aFileName); //打开文件QString currentFileName();//返回当前文件名bool    isFileOpened();//文件已经打开void    setEditFont();//设置字体void    textCut(); //cutvoid    textCopy(); //copyvoid    textPaste(); //pasteprivate:Ui::QFormDoc *ui;};#endif // QFORMDOC_H

这些接口函数是为了在主窗口里调用,实现对 MDI子窗口的操作。实现代码如下:

#include "qformdoc.h"
#include "ui_qformdoc.h"#include    <QVBoxLayout>
#include    <QFile>
#include    <QTextStream>
#include    <QFontDialog>
#include    <QFileInfo>
#include    <QMessageBox>QFormDoc::QFormDoc(QWidget *parent) :QWidget(parent),ui(new Ui::QFormDoc)
{ui->setupUi(this);this->setWindowTitle("New Doc"); //窗口标题this->setAttribute(Qt::WA_DeleteOnClose); //关闭时自动删除
}QFormDoc::~QFormDoc()
{
//    QMessageBox::information(this,"信息","文档窗口被释放");delete ui;
}void QFormDoc::loadFromFile(QString &aFileName)
{//打开文件QFile aFile(aFileName);  //以文件方式读出if (aFile.open(QIODevice::ReadOnly | QIODevice::Text)) //以只读文本方式打开文件{QTextStream aStream(&aFile); //用文本流读取文件ui->plainTextEdit->clear();//清空ui->plainTextEdit->setPlainText(aStream.readAll()); //读取文本文件aFile.close();//关闭文件mCurrentFile=aFileName;//保存当前文件名QFileInfo   fileInfo(aFileName); //文件信息QString str=fileInfo.fileName(); //去除路径后的文件名this->setWindowTitle(str);mFileOpened=true;}
}QString QFormDoc::currentFileName()
{return  mCurrentFile;
}bool QFormDoc::isFileOpened()
{ //文件是否已打开return mFileOpened;
}void QFormDoc::setEditFont()
{QFont   font;font=ui->plainTextEdit->font();bool    ok;font=QFontDialog::getFont(&ok,font);ui->plainTextEdit->setFont(font);
}void QFormDoc::textCut()
{ui->plainTextEdit->cut();
}void QFormDoc::textCopy()
{ui->plainTextEdit->copy();
}void QFormDoc::textPaste()
{ui->plainTextEdit->paste();
}

注意:作为 MDI子窗口,不管其是否设置为关闭时删除,在主窗口里关闭一个MDI子窗口时,都会删除子
窗口对象。

3. MDI主窗口设计与子窗口的使用

3.1 主窗口界面设计

要在主窗口实现 MDI功能,只需在主窗口的工作区放置一个 QMdiArea 组件。图6-15 是设计好的主窗口界面。

在这里插入图片描述

在 UI 设计器里创建 Action,并应用 Action 设计主工具栏。在主窗口的工作区放置一个QMdiArea 组件,然后在主窗口的构造函数里设置mdiArea 填充满工作区。

QWMainWindow::QWMainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::QWMainWindow)
{ui->setupUi(this);this->setCentralWidget(ui->mdiArea);this->setWindowState(Qt::WindowMaximized); //窗口最大化显示ui->mainToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
//    this->setAutoFillBackground(true);
}

3.2 MDI子窗口的创建与加入

下面是主窗口上“新建文档”按钮的响应代码:

void QWMainWindow::on_actDoc_New_triggered()
{ //新建文件QFormDoc *formDoc = new QFormDoc(this); //ui->mdiArea->addSubWindow(formDoc); //文档窗口添加到MDIformDoc->show(); //在单独的窗口中显示ui->actCut->setEnabled(true);ui->actCopy->setEnabled(true);ui->actPaste->setEnabled(true);ui->actFont->setEnabled(true);
}

代码功能是新建一个 QFormDoc 类的窗口 formDoc,构造函数中传入了主窗口指针,所以主窗口是 formDoc 的父窗口,然后使用QMdiArea 的addSubWindow()函数将 formDoc 加入到 mdiArea。

下面是主窗口上“打开文档”按钮的响应代码:

void QWMainWindow::on_actDoc_Open_triggered()
{//打开文件
//必须先获取当前MDI子窗口,再使用打开文件对话框,否则无法获得活动的子窗口bool needNew=false;// 是否需要新建子窗口QFormDoc    *formDoc;if (ui->mdiArea->subWindowList().count()>0) //如果有打开的主窗口,获取活动窗口{formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();needNew=formDoc->isFileOpened();//文件已经打开,需要新建窗口}elseneedNew=true;QString curPath=QDir::currentPath();QString aFileName=QFileDialog::getOpenFileName(this,tr("打开一个文件"),curPath,"C程序文件(*.h *cpp);;文本文件(*.txt);;所有文件(*.*)");if (aFileName.isEmpty())return; //如果未选择文件,退出if (needNew) //需要新建子窗口{formDoc = new QFormDoc(this);//指定父窗口,必须在父窗口为Widget窗口提供一个显示区域ui->mdiArea->addSubWindow(formDoc);}formDoc->loadFromFile(aFileName); //打开文件formDoc->show();ui->actCut->setEnabled(true);ui->actCopy->setEnabled(true);ui->actPaste->setEnabled(true);ui->actFont->setEnabled(true);
}

通过QMdiArea::subWindowList()可以获得子窗口对象列表,从而可以判断子窗口的个数。如果没有一个 MDI子窗口,就创建一个新的窗口并打开文件。

如果有MDI子窗口,则总有一个活动窗口,通过QMdiArea::activeSubWindow()可以获得此活动的子窗口,通过子窗口的 isFileOpened()函数判断是否打开了文件,如果没有打开过文件,就在这个活动窗口里打开文件,否则新建窗口打开文件。

注意:一定要先获取 MDI子窗口,再使用 QFileDialog 选择需要打开的文件,如果顺序更换了,则无法获得正确的 MDI活动子窗口。

3.3 QMdiArea 常用功能函数

QMdiArea 提供了一些成员函数,可以进行一些操作,工具栏上的“关闭全部”“MDI模式”“级联展开”“平铺展开”等按钮都是调用 QMdiArea 类的成员函数实现的。下面是这几个按钮功能的实现代码:

void QWMainWindow::on_actCascade_triggered()
{ //窗口级联展开ui->mdiArea->cascadeSubWindows();
}void QWMainWindow::on_actTile_triggered()
{//平铺展开ui->mdiArea->tileSubWindows();
}void QWMainWindow::on_actCloseALL_triggered()
{//关闭全部子窗口ui->mdiArea->closeAllSubWindows();
}void QWMainWindow::on_actViewMode_triggered(bool checked)
{//MDI 显示模式if (checked) //Tab多页显示模式{ui->mdiArea->setViewMode(QMdiArea::TabbedView); //Tab多页显示模式ui->mdiArea->setTabsClosable(true); //页面可关闭ui->actCascade->setEnabled(false);ui->actTile->setEnabled(false);}else 子窗口模式{ui->mdiArea->setViewMode(QMdiArea::SubWindowView); //子窗口模式ui->actCascade->setEnabled(true); //ui->actTile->setEnabled(true); //}
}

其中,设置MDI视图模式用 setViewMode()函数,有两种模式可以选择。

  • QMdiArea::SubWindowView 是传统的子窗口模式,显示效果如图 6-14 所示。

  • QMdiArea::TabbedView 是多页的显示模式,显示效果如图6-16 所示。
    在这里插入图片描述

3.4 MDI的信号

QMdiArea 有一个信号subWindowActivated(QMdiSubWindow *argl),在当前活动窗口切换时发射,利用此信号可以在活动窗口切换时进行一些处理,例如,在状态栏里显示活动 MDI子窗口的文件名,在没有 MDI子窗口时,将工具栏上的编辑功能按钮设置为禁用。下面是该信号的槽函数代码:

void QWMainWindow::on_mdiArea_subWindowActivated(QMdiSubWindow *arg1)
{//当前活动子窗口切换时Q_UNUSED(arg1);if (ui->mdiArea->subWindowList().count()==0){ //若子窗口个数为零ui->actCut->setEnabled(false);ui->actCopy->setEnabled(false);ui->actPaste->setEnabled(false);ui->actFont->setEnabled(false);ui->statusBar->clearMessage();}else{QFormDoc *formDoc=static_cast<QFormDoc*>(ui->mdiArea->activeSubWindow()->widget());ui->statusBar->showMessage(formDoc->currentFileName()); //显示主窗口的文件名}
}

主窗口工具栏上的“剪切”“复制”“粘贴”“字体设置”等按钮都是调用当前子窗口的相应函数,关键是获取当前 MDI子窗体对象,例如,“剪切”和“字体设置”按钮的代码如下:

void QWMainWindow::on_actCut_triggered()
{ //cutQFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();formDoc->textCut();
}void QWMainWindow::on_actFont_triggered()
{//设置字体QFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();formDoc->setEditFont();
}void QWMainWindow::on_actCopy_triggered()
{//copyQFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();formDoc->textCopy();
}void QWMainWindow::on_actPaste_triggered()
{//pasteQFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();formDoc->textPaste();
}

4. 源码

4.1 qwmainwindow.h

#ifndef QWMAINWINDOW_H
#define QWMAINWINDOW_H#include    <QMainWindow>#include    "qformdoc.h"#include    <QMdiSubWindow>namespace Ui {
class QWMainWindow;
}class QWMainWindow : public QMainWindow
{Q_OBJECT
private:void closeEvent(QCloseEvent *event); //主窗口关闭时关闭所有子窗口
public:explicit QWMainWindow(QWidget *parent = 0);~QWMainWindow();private slots:void on_actDoc_Open_triggered(); //打开文件void on_actDoc_New_triggered(); //新建文件void on_actCut_triggered(); //cutvoid on_actFont_triggered();  //设置字体void on_actCopy_triggered();  //copyvoid on_actPaste_triggered(); //pastevoid on_mdiArea_subWindowActivated(QMdiSubWindow *arg1); //子窗口被激活void on_actViewMode_triggered(bool checked); //MDI 模式设置void on_actCascade_triggered(); //级联形式显示子窗口void on_actTile_triggered(); //平铺形式显示子窗口void on_actCloseALL_triggered(); //关闭全部子窗口private:Ui::QWMainWindow *ui;
};#endif // QWMAINWINDOW_H

4.2 qwmainwindow.cpp

#include "qwmainwindow.h"
#include "ui_qwmainwindow.h"#include    <QPainter>
#include    <QFileDialog>
#include    <QCloseEvent>void QWMainWindow::closeEvent(QCloseEvent *event)
{ui->mdiArea->closeAllSubWindows(); //关闭所有子窗口event->accept();
}QWMainWindow::QWMainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::QWMainWindow)
{ui->setupUi(this);this->setCentralWidget(ui->mdiArea);this->setWindowState(Qt::WindowMaximized); //窗口最大化显示ui->mainToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
//    this->setAutoFillBackground(true);
}QWMainWindow::~QWMainWindow()
{delete ui;
}void QWMainWindow::on_actDoc_Open_triggered()
{//打开文件
//必须先获取当前MDI子窗口,再使用打开文件对话框,否则无法获得活动的子窗口bool needNew=false;// 是否需要新建子窗口QFormDoc    *formDoc;if (ui->mdiArea->subWindowList().count()>0) //如果有打开的主窗口,获取活动窗口{formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();needNew=formDoc->isFileOpened();//文件已经打开,需要新建窗口}elseneedNew=true;QString curPath=QDir::currentPath();QString aFileName=QFileDialog::getOpenFileName(this,tr("打开一个文件"),curPath,"C程序文件(*.h *cpp);;文本文件(*.txt);;所有文件(*.*)");if (aFileName.isEmpty())return; //如果未选择文件,退出if (needNew) //需要新建子窗口{formDoc = new QFormDoc(this);//指定父窗口,必须在父窗口为Widget窗口提供一个显示区域ui->mdiArea->addSubWindow(formDoc);}formDoc->loadFromFile(aFileName); //打开文件formDoc->show();ui->actCut->setEnabled(true);ui->actCopy->setEnabled(true);ui->actPaste->setEnabled(true);ui->actFont->setEnabled(true);
}void QWMainWindow::on_actDoc_New_triggered()
{ //新建文件QFormDoc *formDoc = new QFormDoc(this); //ui->mdiArea->addSubWindow(formDoc); //文档窗口添加到MDIformDoc->show(); //在单独的窗口中显示ui->actCut->setEnabled(true);ui->actCopy->setEnabled(true);ui->actPaste->setEnabled(true);ui->actFont->setEnabled(true);
}void QWMainWindow::on_actCut_triggered()
{ //cutQFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();formDoc->textCut();
}void QWMainWindow::on_actFont_triggered()
{//设置字体QFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();formDoc->setEditFont();
}void QWMainWindow::on_actCopy_triggered()
{//copyQFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();formDoc->textCopy();
}void QWMainWindow::on_actPaste_triggered()
{//pasteQFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();formDoc->textPaste();
}void QWMainWindow::on_mdiArea_subWindowActivated(QMdiSubWindow *arg1)
{//当前活动子窗口切换时Q_UNUSED(arg1);if (ui->mdiArea->subWindowList().count()==0){ //若子窗口个数为零ui->actCut->setEnabled(false);ui->actCopy->setEnabled(false);ui->actPaste->setEnabled(false);ui->actFont->setEnabled(false);ui->statusBar->clearMessage();}else{QFormDoc *formDoc=static_cast<QFormDoc*>(ui->mdiArea->activeSubWindow()->widget());ui->statusBar->showMessage(formDoc->currentFileName()); //显示主窗口的文件名}
}void QWMainWindow::on_actViewMode_triggered(bool checked)
{//MDI 显示模式if (checked) //Tab多页显示模式{ui->mdiArea->setViewMode(QMdiArea::TabbedView); //Tab多页显示模式ui->mdiArea->setTabsClosable(true); //页面可关闭ui->actCascade->setEnabled(false);ui->actTile->setEnabled(false);}else 子窗口模式{ui->mdiArea->setViewMode(QMdiArea::SubWindowView); //子窗口模式ui->actCascade->setEnabled(true); //ui->actTile->setEnabled(true); //}
}void QWMainWindow::on_actCascade_triggered()
{ //窗口级联展开ui->mdiArea->cascadeSubWindows();
}void QWMainWindow::on_actTile_triggered()
{//平铺展开ui->mdiArea->tileSubWindows();
}void QWMainWindow::on_actCloseALL_triggered()
{//关闭全部子窗口ui->mdiArea->closeAllSubWindows();
}

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

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

相关文章

企业权限管理(六)-订单详情

订单详情查询 跳转到订单详情页面orders-show.jsp <button type"button" class"btn bg-olive btn-xs" onclick"location.href${pageContext.request.contextPath}/orders/findById.do?id${orders.id}">详情</button>OrdersControl…

北美跨境购物商城多语言多货币系统快捷搭建(java开源)

我了解到您想搭建一个北美跨境购物商城&#xff0c;拥有多语言和多货币系统&#xff0c;并且希望使用Java开源技术进行快速搭建。以下是一个基本的搭建步骤&#xff1a; 1.确定需求&#xff1a;首先确定您的商城需求&#xff0c;包括功能、设计和用户体验等方面。确保您清楚地…

进入现代云技术的世界-APIGateway、ServiceMesh、OpenStack、异步化框架、云原生框架、命令式API与声明式API

目录 APIGateway Service Mesh OpenStack 异步化框架 云原生框架 命令式API与声明式API APIGateway API网关&#xff08;API Gateway&#xff09;是一个服务器——充当了客户端和内部服务之间的中间层。API网关负责处理API请求&#xff0c;将客户端的请求路由到相应的后端…

数据挖掘全流程解析

数据挖掘全流程解析 数据指标选择 在这一阶段&#xff0c;使用直方图和柱状图的方式对数据进行分析&#xff0c;观察什么数据属性对于因变量会产生更加明显的结果。 如何绘制直方图和条形统计图 数据清洗 观察数据是否存在数据缺失或者离群点的情况。 数据异常的两种情况…

webpack基础知识八:说说如何借助webpack来优化前端性能?

一、背景 随着前端的项目逐渐扩大&#xff0c;必然会带来的一个问题就是性能 尤其在大型复杂的项目中&#xff0c;前端业务可能因为一个小小的数据依赖&#xff0c;导致整个页面卡顿甚至奔溃 一般项目在完成后&#xff0c;会通过webpack进行打包&#xff0c;利用webpack对前…

leetcode 33.搜索旋转排序数组

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;搜索旋转排序数组 ps&#xff1a; 本题是二分查找的变形&#xff0c;旋转排序数组之后其实会形成两个有序的区间。算出平均下标先判断是否与 target 相等&#xff0c;因为这样可以减少代码的冗余。如果前者不成立则使用平…

Godot 4 源码分析 - 文件读入编码处理

今天需要读入xml文件进行处理&#xff0c;结果读入一个带中文的文件时&#xff0c;出错了。当然程序还能运行&#xff0c;但编译器一直报错&#xff0c;而且XML解析也不正确 单步调试发现读入的内容出现乱码&#xff0c;具体逻辑&#xff1a; String FileAccess::get_as_text…

【肌电图信号分析】通道肌电图并查找收缩周期的数量、振幅、最大值和持续时间(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

React源码解析18(2)------ FilberNode,FilberRootNode结构关系

摘要 在上一篇&#xff0c;我们实现了通过JSX转换为ReactElement的方法&#xff0c;也看到了转换后React元素的结构。但是这个React元素&#xff0c;并不能很清楚的表达组件之间的关系&#xff0c;以及属性的处理。 所以在React内部&#xff0c;会将所有的React元素转换为Fil…

【Linux】详解进程状态之僵尸进程——孤儿进程

目录 &#x1f31e;专栏导读 &#x1f31b;什么是进程 ⭐什么是PCB&#xff1f; &#x1f31b;查看进程 &#x1f31b;如何通过系统调用查看进程PID &#x1f31b;fork &#x1f31e;认识进程状态 &#x1f31b;查看进程状态 &#x1f31b;R状态 ⭐例如&#xff1a…

VMware Workstation及CentOS-7虚机安装

创建新的虚机&#xff1a; 选择安装软件&#xff08;这里选的是桌面版&#xff0c;也可以根据实际情况进行选择&#xff09; 等待检查软件依赖关系 选择安装位置&#xff0c;自主配置分区 ​​​​​​​ 创建一个普通用户 安装完成后重启 点击完成配置&#xff0c;进入登陆界面…

怎么进行流程图制作?用这个工具制作很方便

怎么进行流程图制作&#xff1f;流程图是一种非常有用的工具&#xff0c;可以帮助我们更好地理解和展示各种复杂的业务流程和工作流程。它可以将复杂的过程简化为易于理解的图形和文本&#xff0c;使得人们更容易理解和跟踪整个流程。因此&#xff0c;制作流程图是在日常工作中…

拆解与重构:慕云游首页组件化设计

目录 前言1 项目准备1.1 创建项目目录1.2 搭建项目开发环境 2 项目组件化2.1 在当前环境启动原有项目2.2 顶部组件2.3 幻灯片组件2.3.1 功能实现2.3.2 加载中组件2.3.3 结构和样式2.3.4 使用Ajax获取数据 2.4 机酒自由行组件2.5 拆分余下的css文件 3 项目完善4 源码 前言 在现代…

如何使Python Docker镜像安全、快速、小巧

一、说明 在微服务领域&#xff0c;拥有安全、高效和紧凑的 Docker 映像对于成功部署至关重要。本博客将探讨有助于构建此类映像的关键因素&#xff0c;包括不以 root 用户身份运行映像的重要性、在构建映像时更新和升级包、在编写 Dockerfile 指令时考虑 Docker 的层架构&…

岩土工程仪器多通道振弦传感器信号转换器应用于桥梁安全监测

岩土工程仪器多通道振弦传感器信号转换器应用于桥梁安全监测 桥梁作为交通运输的重要节点&#xff0c;其安全性一直备受关注。不同于其他建筑物&#xff0c;桥梁所处的环境复杂多变&#xff0c;同时&#xff0c;其所需承受的负荷也相对较大&#xff0c;这就需要对桥梁的安全进…

Windows 安装 pandoc 将 jupyter 导出 pdf 文件

Windows 安装 pandoc 将 jupyter 导出 pdf 文件 1. 下载 pandoc 安装文件2. 安装 pandoc3. 安装 nbconvert4. 使用 pandoc 1. 下载 pandoc 安装文件 访问 https://github.com/jgm/pandoc/releases&#xff0c;下载最新版安装文件&#xff0c;例如&#xff0c;3.1.6.1 版&#…

常见分布式ID解决方案总结:数据库、算法、开源组件

常见分布式ID解决方案总结 分布式ID分布式ID方案之数据库数据库主键自增数据库号段模式Redis自增MongoDB 分布式ID方案之算法UUIDSnowflake(雪花算法) 雪花算法的使用IdWorker工具类配置分布式ID生成器 分布式ID方案之开源组件uid- generator(百度)Tinyid&#xff08;滴滴&…

基于Java的体育网站的设计与实现(论文+源码)_kaic

基于Java的体育网站的设计与实现 摘 要&#xff1a;在网络应用的迅速发展与科技的不断进步的现代环境下&#xff0c;人们生活节奏越来越快&#xff0c;娱乐方式也多种多样&#xff0c;各种软件应用&#xff0c;各种娱乐&#xff0c;购物网站已经成为必不可少的伴随品&#xff…

《24海南大学835软件工程考研经验贴》

1.经验之谈 首先&#xff0c;我是一个二战的考生&#xff0c;一战给我带来的经验有几点。第一&#xff0c;数学、专业课这两门越早复习越好&#xff0c;越拖到后面你就会发现来不及了&#xff0c;这学不完&#xff0c;那学不完的。第二、我认为是比较关键的一点&#xff0c;一定…

Idea创建maven管理的web项目

如果你想在项目中添加一个传统的 src 目录来存放源代码&#xff0c;可以按照以下步骤操作&#xff1a; 1. 在项目视图中&#xff0c;右键单击项目名称&#xff0c;选择 “New” -> “Directory”。 2. 在弹出的对话框中&#xff0c;输入目录名称为 “src”&#xff0c;然后…