目录

一,Label

1.1 主要属性

1.2 文本格式

1.3 设置图片

1.4 其它常用属性

1.5 设置伙伴

二,LCD Number

2.1 主要属性

2.2 实现倒计时

​2.3 两个问题

三,ProgressBar

3.1 主要属性

3.2 进度条按时间增长

3.3 改变样式

3.4 一个问题

四,Calendar Widget

4.1 主要属性

4.2 获取选中的日期 

一,Label

1.1 主要属性

QLabel 可以用来显示文本或图片,主要属性如下:

属性说明
textQLabel 中的文本
textFormat

文本的格式:

  • Qt::PlainText:纯文本
  • Qt::RichText:富文本(⽀持html标签)
  • Qt::MarkdownText:markdown格式
  • Qt::AutoText:根据文本内容自动决定文本格式
pixmapQlabel 内部包含的图片
scaledContents设为 true表示图片自动拉伸填充满 QLabel,false就不会
alignment对齐方式,可设置水平和垂直方向如何对齐
wordWrap

设为 true 内部文本会自动换行,false 则不会

QLabel 不会提供滚动条,别的控件才有,比如 QtextEdit(多行编辑框)

indent设置文本缩进,水平和垂直方向都生效
margin内部文本和边框之间的边距
openExternalLinks是否允许打开一个外部的链接(QLabel 文本内容包含 URL 时涉及)
buddy

给 QLabel 关联⼀个"伙伴",这样点击QLabel时就能激活对应的伙伴

例如伙伴如果是⼀个QCheckBox,那么该QCheckBox就会被选中

 下面我们来搞几个具体的例子,演示下上表格的部分属性

1.2 文本格式

先创建三个label用于展示不同的格式,然后可以在构造函数里设置不同文本格式:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->label->setTextFormat(Qt::PlainText);ui->label->setText("这是一段纯⽂本");ui->label_2->setTextFormat(Qt::RichText);ui->label_2->setText("<b> 这是一段富⽂本 </b>"); //b标签表示加粗ui->label_3->setTextFormat(Qt::MarkdownText);ui->label_3->setText("## 这是一段 markdown ⽂本"); // ##表示二级标题
}

 

1.3 设置图片

首先用 qrc 准备一张图片,然后就可以对 Label 设置图片:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//先把整个 Label 铺满窗口,然后让 Label 的左上角设置到窗口的左上角ui->label->setGeometry(0, 0, this->width(), this->height());QPixmap pixmap(":/deepseek.png");ui->label->setPixmap(pixmap);ui->label->setScaledContents(true); //有时候图片尺寸会小于窗口,那么这个就可以让图片拉伸
}

但是上面我们对 Label 尺寸的设置是“一次性”的,就上面的程序而言,只要我们扩大或缩小窗口大小,里面的 Label控件大小是不会变的,所以下面我们让 Label 的大小随着窗口大小实时发生改变

原理

  • 用户的绝大部分操作,会对应一些事件
  • 但 Qt 中,除了信号,还有一个“事件”也用来表示用户的操作
  • 鼠标拖拽窗口大小时,会让 Qt 触发一个 resize 事件(resizeEvent),而且我们改变窗口尺寸的过程中,会触发一系列的 resize事件
  • 此时就可以借助 resizeEvent 来完成功能,重写父类 QWidget 的 resizeEvent虚函数,而且在鼠标拖动窗口尺寸过程中,会持续调用这个虚函数进而调用子类的函数

先在头文件里声明函数:

然后实现该函数即可:

//此处的形参 event 包含了触发 resize 事件时,窗口尺寸的数值
void Widget::resizeEvent(QResizeEvent *event)
{//qDebug() << event->size();ui->label->setGeometry(0, 0, event->size().width(), event->size().height());
}

 效果如下:

1.4 其它常用属性

先创建几个带边框的 Label,如下图:

 然后在构造函数中,给这几个 label 设置不同的属性:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{//①设置对齐方式ui->setupUi(this);ui->label->setText("这是一段文本");ui->label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //设置文本对齐方式,参数也是枚举,这两个表示垂直和水平居中,就是显示在框框中间//水平方向有靠左、中、右三种,垂直方向有靠上、中、下三种,一般用两个组合使用//②设置自动换行ui->label_2->setText("Tcp全称“传输控制协议(Transmission Control Protocol)”,是当今互联网使用最广泛的传输层协议,因为它基于通信时保证可靠性,并且对于高效传输也有一定策略,是目前应用层底层使用的非常常见的网络协议");ui->label_2->setWordWrap(true); //表示开启自动换行//③设置缩进ui->label_3->setText("这是另一段文本");ui->label_3->setIndent(50); //表示在显示在程序上时给字体前面加上多少像素的空白//如果是label_2那样的长文本的话,会给所有的行都添加缩进//④设置边距ui->label_4->setText("Tcp的三次握手是验证双方通信信道的最小次数,能够快速建立连接;并且奇数次握手,可以确保一般情况下握手失败的连接成本是嫁接在客户端的,能保证服务器本身的稳定性");ui->label_4->setWordWrap(true); //开启自动换行ui->label_4->setMargin(50); //设置边距,表示文本内容的上下左右四个方向都要留出部分像素的空白
}

效果如下:

1.5 设置伙伴

这个和 HTML 前端中一样的,有时候按钮旁边会有一些字,但是为了方便用户点击,一般用户直接点击按钮的旁边的文字也可以选中按钮,所以这个设置伙伴就是将文本和按钮“绑定”

先创建两个单选框和两个文本框:

关于 QLabel 快捷键:

  • Qt 中 Label 的快捷键是在文本中使用符号 ‘ & ’ 跟上一个字符来表示快捷键
  • 比如 &A ,然后需要通过键盘上的 Alt + a 才能触发快捷键
  • 绑定了伙伴关系之后,就可以通过快捷键选中对应的单选或复选按钮了
  • 但是这个快捷键没有我们前面QPushButton的功能那么强大,所以了解即可

然后就是通过代码将下面的文本框添加“伙伴”,如下代码:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//设置 label 和 radioButton 的伙伴关系ui->label->setBuddy(ui->radioButton);ui->label_2->setBuddy(ui->radioButton_2);
}

然后我们就可以通过 Alt + A 或 Alt + B 的快捷键方式来选中按钮了:

二,LCD Number

2.1 主要属性

QLCDNumber 是一个专门用来显示数字的控件,类似于“老式计算器”的效果,主要属性如下:

属性说明
intValue显示的数字值(int)
value

显示的数字值(double)

  • 和 intValue 是联动的,例如 value 设为1.5,那么intValue 的值就是2
  • 另外,设置 value 和 intValue 的方法名字为 display,而不是 setValue 或 setIntValue
digitCount显示几位数字
mode

数字显示形式

  • QLCDNumber::Dec:十进制模式,显示常规的十进制数字
  • QLCDNumber::Hex:十六进制模式,以十六进制格式显示数字
  • QLCDNumber::Bin:二进制模式,以二进制格式显示数字
  • QLCDNumber::Oct:八进制模式,以八进制格式显示数字

只有十进制才能显示小数点后的内容

segmentStyle

设置显示风格

  • QLCDNumber::Flat:平面的显示风格,数字呈现在一个平坦的表面上
  • QLCDNumber::Outline:轮廓显示风格,数字具有清晰的轮廓哦和阴影效果
  • QLCDNumber::Filled:填充显示风格,数字被填充颜色并与背景区分开
smallDecimalPoint设置比正常大小还小的小数点

下面通过例子来演示上述效果:

2.2 实现倒计时

我们先使用 QLCDNumber 显示一个初始的数值,比如4,然后程序启动后,每过一秒数字就 -1,直到 0 就结束

先创建一个LCD,如下:

然后我们现在的关键点就是要实现“每秒钟 -1” 这个效果,也就是周期性的执行某个逻辑

关于“定时器”功能

  • C++ 标准库里没有提供定时器的相关接口(Boost库里面有)
  • 但是Qt 中是封装了对应的定时器的,涉及到的类叫做 QTimer,创建出来的对象会产生 timeout 这样的信号
  • 我们可以通过 start 方法来开启定时器,并在参数中设定触发 timeout 信号的周期 
  • 然后结合 connect ,把这个 timeout 信号绑定到需要的槽函数中,就可以执行逻辑,修改 LCDNumber 中的数字了

我们先在头文件添加 定时器对象和槽函数的声明:

然后就是倒计时的逻辑了:

#include "widget.h"
#include "ui_widget.h"
#include<QTimer>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->lcdNumber->display(4); //设置一个初始值timer = new  QTimer(this);connect(timer, &QTimer::timeout, this, &Widget::handle);//将 QTimer 的 timeout 信号和我们自己创建的槽函数进行关联timer->start(1000); //启动定时器,单位ms,1000表示每隔一秒触发一次信号
}Widget::~Widget()
{delete ui;
}void Widget::handle()
{int value = ui->lcdNumber->intValue();if(value <= 0){timer->stop();return;}ui->lcdNumber->display(value - 1);
}

效果如下:

2.3 两个问题

问题一:如果我不用计时器,直接在 Widget 的构造函数里,通过 “循环 + sleep(1)” 的方式是否可以呢

例如下列代码:

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{ui->setupUi(this);int value = ui->lcdNumber->intValue();while (true) {std::this_thread::sleep_for(std::chrono::seconds(1));if (value <= 0) break;ui->lcdNumber->display(value - 1);}
}

这个方法直接叉掉,在构造函数里搞循环,会导致构造函数无法退出,此时界面就无法显示任何控件

问题二:那么我是否可以另外创建一个线程,在新线程里完成 循环 + sleep(1) 可以吗?

如下代码:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//创建线程t,并添加lamdba线程函数std::thread t([this]() {int value = this->ui->lcdNumber->intValue();while (true) {std::this_thread::sleep_for(std::chrono::seconds(1));if (value <= 0) break;this->ui->lcdNumber->display(value - 1);}});
}

这个也是不行的,原因如下:

  • Qt 的界面只能由主线程去负责维护和更新的,并且 Qt 为了保证修改页面过程中不受影响,禁止了其他线程直接修改页面
  • 因为这种情况如果不加锁,不维护好线程安全,就可能有多个线程同时在修改页面,很容易导致页面显示混乱,这是无法容忍的
  • 所以Qt 为了主界面线程安全,直接要求所有对界面的修改操作,必须在主线程中完成
  • 槽函数就是由主线程调用的,所以可以修改

简单来说,界面就相当于共享资源,每个线程访问签都必须先加锁,但是 Qt 规定只能由主线程一个线程去修改 

解决办法也有,就是创建线程后,线程只负责每秒发 timeout 信号给槽函数再去修改,但这属于多此一举, 所以暂时不考虑 

三,ProgressBar

3.1 主要属性

QProgressBar 控件表示一个进度条,就是我们安装程序时界面显示的那个条,主要属性如下:

属性说明
minimum进度条最小值
maximum进度条最大值
value京都条当前值
alignment

文本在进度条中的对齐方式

  • Qt::AlignLeft:左对齐
  • Qt::AlignRight:右对齐
  • Qt::AlignCenter:居中对齐
  • Qt::AlignJustify:两端对齐
textVisible进度条数字是否可见
orientation进度条的方向是水平还是垂直
invertAppearance是否朝反方向增长进度
textDirection文本的朝向
format

展示的数字格式

  • %p:表示进度的百分比(0 - 100)
  • %v:表示进度的数值(0-100)
  • %m:表示剩余时间(单位ms)
  • %t:表示总时间(单位ms)

3.2 进度条按时间增长

我们之前是写过一个命令行版本的进度条的,可以参考:Linux实现简单进度条-CSDN博客

先创建一个进度条,如下图:

我们的期望是每隔100毫秒进度条就增加1,所以我们仍然可以通过定时器来实现周期行为

代码如下:

#include "widget.h"
#include "ui_widget.h"
#include<QTimer>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);timer = new QTimer(this);connect(timer, &QTimer::timeout, this, &Widget::handle);timer->start(20); //启动计时器
}Widget::~Widget()
{delete ui;
}void Widget::handle()
{int value = ui->progressBar->value(); //获取进度条当前数值if(value >= 100){timer->stop();return;}ui->progressBar->setValue(value + 1);
}

步骤和前面的倒计时很像,都是计时器发信号然后触发槽函数然后修改,效果如下:

 在实际开发中,进度条的取值,往往是根据当前任务的实际进度来进行设置的

3.3 改变样式

QProGressBar 也是继承自 QWidget 的,所以也可以使用 styleSheet等方式来改变进度条的颜色等外表

假如我们要把上面的进度条颜色改为“红色”,如下:

 可以添加下列样式:

QProgressBar::chunk { background-color: red; }

上面两个冒号是“选择器”,对于什么是选择器,可以参考:前端学习(2)—— CSS详解与使用-CSDN博客 

 效果如下:

但是我们发现,我们的 100% 的数字跑到了左上角,这个忙猜是 Qt 的bug,毕竟我们没有改变其他的任何地方,所以我们只能先使用 alignment 来手动调整下,如下图:

效果如下:

3.4 一个问题

问题:我们上面的 Widget.h 头文件,添加QTimer* timer; 声明时,明明没有包含 对应头文件,为什么不会提示“QTimer 找不到定义”之类的呢?

如下图:

原因如下:

  • 在 Qt 中,有一个特殊的头文件,这个头文件里包含了 Qt 中所有类的“前置声明”,这个头文件一般不会直接接触到,但是包含其他的 Qt 的头文件,都会间接包含到这个文件
  • 比如上面的 Widget 类的前面已经提供了 QTimer 类的声明的话,此时就可以直接在 Widget 中使用 QTimer 的指针/引用类型的成员(这个是 C++ 中的特殊技巧,Qt 就把它充分发挥了)

追加问题:Qt 为什么要使用上面的技巧呢?

解答

  • C/C++ 的代码,编译速度在其他语言的横向对比中,其实是非常慢的,这个 #include 头文件有很大关系
  • 因为C/C++代码在编译期间,是直接把头文件展开,然后替换掉原来包含头文件的位置,相当于复制拷贝,而一个头文件会间接包含其他头文件,然后其他头文件也会包含其他头文件,这样一下来,就会造成很多不必要的头文件展开
  • 因此,尽可能减少 include 头文件的个数,就可以有效减少编译事件,Qt 就使用 class 前置声明的方式,尽量减少头文件的包含
  • 但是实际开发中,该包含就该包含,也可以引入更好的硬件资源来更高效的编译,一些互联网大肠,都有专门的“编译集群”(分布式编译),专门用来编译

四,Calendar Widget

4.1 主要属性

QCalendarWidget 表示一个“日历”,主要属性如下:

属性说明
selectDate当前选中的日期
minimumDate最小日期
maximumDate最大日期
firstDayOfWeek每周的第一天是周几(日历的第一列)
gridVisible是否显示表格的边框
selectionMode是否允许选择日期
navigationBarVisible日历上方标题是否显示
horizontalHeaderFormat日历上方标题显示的日期格式
verticalHeaderFormat日历第一列显示的内容格式
dateEditEnabled是否允许日期被编辑

也提供了一些信号,如下:

信号说明
selectionChanged(const QDate&)当选中的日期发生改变时发出
activated(const QDate&)当双击一个有效的日期或按下回车键时发出,形参是一个QDate类型,保存了选中的日期
currentPageChanged(int, int)当年份月份改变时发出,形参表示改变后的新年份个月份

4.2 获取选中的日期

先创建一个 label 和一个日历,然后右键转到槽,选择 selectionChange():

编写如下槽函数:

void Widget::on_calendarWidget_selectionChanged()
{QDate date = ui->calendarWidget->selectedDate();QString ret = "选择的日期是:";ret += date.toString();ui->label->setText(ret);
}

效果如下:

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

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

相关文章

LINUX文件系统权限,命令解释器alias,文件查看和查找

1、文件査看:查看/etc/passwd文件的第5行[rootserver ~]# head -5 /etc/passwd | tail -1 #先找到前5行&#xff0c;用管道符过滤&#xff0c;显示倒数第一行2、文件查找(1)在当前目录及子目录中&#xff0c;查找大写字母开头的txt文件[rootserver ~]# find / -name "[…

AI图像修复工具CodeFormer实测:马赛克去除与画质增强效果评测

大家好&#xff01;平时看图片或视频&#xff0c;是不是特别烦人脸被马赛克遮住的地方&#xff1f;比如老照片模糊、视频关键部分被打码&#xff0c;看着很不舒服。今天给大家分享一款超好用的去马赛克神器——CodeFormer&#xff0c;完全免费&#xff0c;新手也能轻松搞定&…

知识宇宙-思考篇:AI大模型如何重塑软件开发流程?

名人说&#xff1a;博观而约取&#xff0c;厚积而薄发。——苏轼《稼说送张琥》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录AI大模型重塑软件开发&#xff1a;从码农到AI编程伙伴的华丽转身一、AI大模型的编程&…

Rocky Linux上使用NVM安装Node.js 18

问题描述 Rocky Linux 9 默认 yum 安装的 Node.js 版本是16&#xff0c;vite启动报错&#xff1a;TypeError: crypto$2.getRandomValues is not a function &#xff0c;需安装更高版本的 Node.js 使用nvm安装Node.js的好处 多版本管理&#xff0c;NVM 允许你安装多个不同版本的…

JVM 中“对象存活判定方法”全面解析

1. 前言 在 Java 开发过程中&#xff0c;我们常常听到“垃圾回收”&#xff08;Garbage Collection, GC&#xff09;这一术语。JVM 通过垃圾回收机制自动管理内存&#xff0c;极大地简化了程序员的内存控制负担。然而&#xff0c;GC 究竟是如何判断哪些对象该回收、哪些应保留…

苹果公司高ROE分析

公司通过增加负债提升净资产收益率&#xff08;ROE&#xff09;的核心机制在于财务杠杆效应和资本结构优化&#xff0c;以下从原理、操作路径、风险边界及苹果案例四维度展开分析&#xff1a;名称解释&#xff1a; ROIC(投入资本回报率)&#xff1a;ROICNOPATInvested Capital …

【Linux系统】进程概念

1. 进程概念1.1 进程的本质核心定义用户视角&#xff1a;程序的动态执行实例&#xff08;如同时运行多个Chrome窗口即多个进程&#xff09;。内核视角&#xff1a;资源分配的最小实体单位&#xff0c;独享CPU时间片、内存空间和文件资源。现代定义&#xff1a;进程 内核数据结…

从LLM到VLM:视觉语言模型的核心技术与Python实现

本教程的完整代码可以在GitHub上找到&#xff0c;如果你有任何问题或建议&#xff0c;欢迎交流讨论。 引言&#xff1a;为什么需要VLM&#xff1f; 当我们与ChatGPT对话时&#xff0c;它能够理解复杂的文字描述&#xff0c;生成流畅的回答。但如果我们给它一张图片&#xff0c…

老系统改造增加初始化,自动化数据源配置(tomcat+jsp+springmvc)

老系统改造增加初始化&#xff0c;自动化数据源配置一、前言二、改造描述1、环境说明2、实现步骤简要思考三、开始改造1、准备sql初始化文件2、启动时自动读取jdbc文件&#xff0c;创建数据源&#xff0c;如未配置&#xff0c;需要一个默认的临时数据源2.1去掉sping mvc原本配置…

卫星通信终端天线的5种对星模式之二:DVB跟踪

要实现稳定可靠的卫星通信&#xff0c;地面终端天线必须精准地对准远方的卫星。对星的过程是一个不断搜索、不断逼近的过程&#xff0c;其目标是让天线波束中心精确指向卫星&#xff0c;从而获得最大信号接收与发射效率。 卫星通信终端天线的对星技术是保障卫星通信链路稳定的…

重构下一代智能电池“神经中枢”:GCKontrol定义高性能BMS系统级设计标杆

概述BMS&#xff08;电池管理系统&#xff09;作为新能源汽车动力电池与整车的核心纽带&#xff0c;通过实时监控电压、电流、温度及SOC等参数&#xff0c;控制电池充放电过程&#xff0c;保障电池安全性与使用寿命。随着电动汽车智能化发展&#xff0c;对BMS的响应速度、精度和…

面试150 对称二叉树

思路 联想递归三部曲&#xff1a;传入参数、遍历方式、返回什么。本题联想到先序遍历的方式,需要遍历整颗二叉树,最后返回的是一个布尔值。然后我们需要传入的是左子树和左子树的节点,然后分别进行比较。 # Definition for a binary tree node. # class TreeNode: # def __…

多线程的区别和联系

进程和线程的区别和联系1.一个进程可以包含多个线程&#xff0c;不能够没有线程2.进程是系统资源分配的基本单位&#xff0c;线程是系统调度执行的基本单位3.同一个进程里的线程之间&#xff0c;共用同一份系统资源4.线程是当下实现并发编程的主流方式&#xff0c;通过多线程&a…

两个文件夹自动同步

两个文件夹自动同步&#xff0c;非常简单&#xff0c;利用一些工具就可以轻松做到&#xff0c;设置完源和目标文件夹&#xff0c;点击启动就马上可以两个文件夹自动同步&#xff0c;对于一些有文件同步、文件灾备需求的老登&#xff0c;用起来会非常顺手&#xff0c;比如PanguF…

虚拟商品交易维权指南:数字经济时代的消费者权益保护

首席数据官高鹏律师数字经济团队创作AI辅助在元宇宙、NFT、虚拟情绪产品等新兴领域蓬勃发展的今天&#xff0c;虚拟商品交易已成为数字经济的重要组成部分。从游戏皮肤、在线课程到数字藏品&#xff0c;消费者在享受虚拟商品便捷性的同时&#xff0c;也面临着诸多法律风险。作为…

mysql 一条语句的执行流程

文章目录一条查询语句的执行流程连接器管理连接权限校验分析器优化器采样统计优化器选错索引改正执行器查询缓存存储引擎一条update语句的执行流程redo logredo log buffer结构redo log日志类型写入时机配置innodb_flush_log_at_trx_commitbinlogredo log和binlog 对比配置两阶…

【视频观看系统】- 需求分析

&#x1f3af; 一、项目目标 构建一个功能完备的视频观看网站&#xff0c;用户可以上传、浏览、观看视频&#xff0c;并在观看过程中实时发送/接收弹幕。系统具备良好的性能、可扩展性与用户体验&#xff0c;未来可逐步扩展为多媒体平台。&#x1f464; 二、用户角色分析用户类…

模型驱动的架构MDA的案例

在一个企业资源规划&#xff08;ERP&#xff09;系统开发项目中&#xff0c;目标是为一家中型制造企业打造一套高效且可扩展的管理系统&#xff0c;涵盖订单处理、库存管理等多个业务模块。项目团队采用了 MDA 的设计思想进行开发。​首先是业务需求分析与计算独立模型&#xf…

第一次搭建数据库

本文详细介绍第一次搭建数据库安装和配置过程, 包括卸载旧版本、下载安装、配置服务、环境变量等等 第一步下载mysql 在下载之前需要检查电脑上有没有安装mysql, 如果有再安装, 80%就会有问题 检查方法: 电脑-右键找到管理-服务-在服务中找有没有mysql服务若有请先 1.停止服务 …

洛谷题解 | UVA1485 Permutation Counting

目录题目描述题目思路AC 代码题目描述 https://onlinejudge.org/external/14/p1485.pdf 题目思路 dp。 定义 dpi,jdp_{i,j}dpi,j​ 为前 iii 个数的排列中恰好有 jjj 个小于号的排列总数。 考虑将数字 iii 插入到前 i−1i-1i−1 个数的排列中不同的位置&#xff1a; 如果…