介绍一个可以自由调整 CSDN Markdown 表格的列宽的好方法,可以有效防止表头或列名自动换行,适用性很强。先看一下问题:下表摘自我的一篇文章《QWebChannel 前端交互(Js/C++ 互操作性):原则、示例与逐步解释》,未使用本文介绍的技巧处理前,它是这样的:
| 编号 | C++ 对象 | Js 对象 | 使用方式 | 交互形式 |
|---|---|---|---|---|
| (1) | 所有 Q_PROPERTY 声明的属性 | 有对等属性 | ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致^[1](#编号 C++ 对象 Js 对象 使用方式 交互形式 (1) 所有 Q_PROPERTY 声明的属性 有对等属性 ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致1; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新2 前端读写直接作用到后端,后端更新自动同步到前端 (2) 所有 singal 方法 有对等方法 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) 后端“跨语言”通知前端 (3) 所有 slot 方法 有对等方法 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) 前端“跨语言”调用后端)^; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新^[2](#编号 C++ 对象 Js 对象 使用方式 交互形式 (1) 所有 Q_PROPERTY 声明的属性 有对等属性 ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致1; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新2 前端读写直接作用到后端,后端更新自动同步到前端 (2) 所有 singal 方法 有对等方法 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) 后端“跨语言”通知前端 (3) 所有 slot 方法 有对等方法 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) 前端“跨语言”调用后端)^ | 前端读写直接作用到后端,后端更新自动同步到前端 |
| (2) | 所有 singal 方法 | 有对等方法 | 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) | 后端"跨语言"通知前端 |
| (3) | 所有 slot 方法 | 有对等方法 | 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) | 前端"跨语言"调用后端 |
这张表格最糟糕的地方是 [ Js 对象 ] 一栏,我希望它能宽一点。过去,遇到难以调整的 markdwon 表格时,我通常会转换成 Excel 然后截图,但这次的表格中有两个脚标引用,如果改成图片就无效了,所以我决定在 markdown 模式下调整一下试试看。起初,我尝试在列名上添加一些空格,这确实起到了作用,列被"撑"宽了,但列名 [ Js 对象 ] 总是会自动换行,无论加多少空格都不起作用:
| 编号 | C++ 对象 | Js 对象 | 使用方式 | 交互形式 |
|---|---|---|---|---|
| (1) | 所有 Q_PROPERTY 声明的属性 | 有对等属性 | ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致^[1](#编号 C++ 对象 Js 对象 使用方式 交互形式 (1) 所有 Q_PROPERTY 声明的属性 有对等属性 ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致1; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新2 前端读写直接作用到后端,后端更新自动同步到前端 (2) 所有 singal 方法 有对等方法 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) 后端“跨语言”通知前端 (3) 所有 slot 方法 有对等方法 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) 前端“跨语言”调用后端)^; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新^[2](#编号 C++ 对象 Js 对象 使用方式 交互形式 (1) 所有 Q_PROPERTY 声明的属性 有对等属性 ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致1; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新2 前端读写直接作用到后端,后端更新自动同步到前端 (2) 所有 singal 方法 有对等方法 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) 后端“跨语言”通知前端 (3) 所有 slot 方法 有对等方法 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) 前端“跨语言”调用后端)^ | 前端读写直接作用到后端,后端更新自动同步到前端 |
| (2) | 所有 singal 方法 | 有对等方法 | 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) | 后端"跨语言"通知前端 |
| (3) | 所有 slot 方法 | 有对等方法 | 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) | 前端"跨语言"调用后端 |
虽然这不是个大问题,但真是会"逼死强迫症",而且这个问题不应该这么"弱智",应该有解决办法才对,所以我尝试着在单元格里加空格来"撑起"列宽,然后得到了第二个版本:
| 编号 | C++ 对象 | Js 对象 | 使用方式 | 交互形式 |
|---|---|---|---|---|
| (1) | 所有 Q_PROPERTY 声明的属性 | 有对等属性 | ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致^[1](#编号 C++ 对象 Js 对象 使用方式 交互形式 (1) 所有 Q_PROPERTY 声明的属性 有对等属性 ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致1; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新2 前端读写直接作用到后端,后端更新自动同步到前端 (2) 所有 singal 方法 有对等方法 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) 后端“跨语言”通知前端 (3) 所有 slot 方法 有对等方法 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) 前端“跨语言”调用后端)^; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新^[2](#编号 C++ 对象 Js 对象 使用方式 交互形式 (1) 所有 Q_PROPERTY 声明的属性 有对等属性 ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致1; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新2 前端读写直接作用到后端,后端更新自动同步到前端 (2) 所有 singal 方法 有对等方法 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) 后端“跨语言”通知前端 (3) 所有 slot 方法 有对等方法 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) 前端“跨语言”调用后端)^ | 前端读写直接作用到后端,后端更新自动同步到前端 |
| (2) | 所有 singal 方法 | 有对等方法 | 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) | 后端"跨语言"通知前端 |
| (3) | 所有 slot 方法 | 有对等方法 | 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) | 前端"跨语言"调用后端 |
这一改进解决了列名自动换行的问题,但"有对等属性"这一单元格却出现了无法控制的自动行换行,我尝试给列名和其他单元格都添加空格,但都无效。然后我仔细想了想一下,这里换行的原因是单元格中的文本已经是文字内容[空格][空格][空格]...了,所以文本的换行应该是以其包含空格的总长度计算的,这让我们想起了在 PPT 中给形状输入设置文本时,如果是五个字的内容,为了美观,我们会在第二个字后回车变成两行,上一行两个字,下一行三个字,宽度由下方长的一行决定,受这一点启发,我在文字内容和空格中间添加了一个 <br/>,变成: 文字内容<br/> ...,然后问题问题就奇迹般解决了。我顺道也处理了 [ 编号 ] 一栏,最终得到了一张"非常舒适"的表格:
| 编号 | C++ 对象 | Js 对象 | 使用方式 | 交互形式 |
|---|---|---|---|---|
| (1) | 所有 Q_PROPERTY 声明的属性 | 有对等属性 | ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致^[1](#编号 C++ 对象 Js 对象 使用方式 交互形式 (1) 所有 Q_PROPERTY 声明的属性 有对等属性 ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致1; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新2 前端读写直接作用到后端,后端更新自动同步到前端 (2) 所有 singal 方法 有对等方法 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) 后端“跨语言”通知前端 (3) 所有 slot 方法 有对等方法 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) 前端“跨语言”调用后端)^; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新^[2](#编号 C++ 对象 Js 对象 使用方式 交互形式 (1) 所有 Q_PROPERTY 声明的属性 有对等属性 ① 向 Js 对象写入属性值就是向 C++ 对象写入属性值(存在一次 前端 🠚 后端 的远程交互); ② 从 Js 对象读取属性值时,并不会发起远程交互去取后端 C++ 对象的属性值,但 Qt 有透明的自动更新机制保证前端属性值与后端 C++ 对象始终一致1; ③ 后端 C++ 对象更新属性时,前端 Js 对象能自动同步更新2 前端读写直接作用到后端,后端更新自动同步到前端 (2) 所有 singal 方法 有对等方法 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) 后端“跨语言”通知前端 (3) 所有 slot 方法 有对等方法 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) 前端“跨语言”调用后端)^ | 前端读写直接作用到后端,后端更新自动同步到前端 |
| (2) | 所有 singal 方法 | 有对等方法 | 在 Js 端会被 connect 到 Js 的事件响应函数上,用于在前端响应/处理后端发来的信号(存在一次 后端 🠚 前端 的远程交互) | 后端"跨语言"通知前端 |
| (3) | 所有 slot 方法 | 有对等方法 | 通常是在 Js 的事件响应函数内调用,用于将前端事件/数据传回到后端处理(存在一次 前端 🠚 后端 的远程交互) | 前端"跨语言"调用后端 |
简单总结一下这个小技巧:
如果需要增加列宽且不想让表头/列名自动换行,只需要选择列中的一个单元格的文字内容后添加一个 <br/> 和若干个 形成
文字内容<br/> ...
这种格式就可以解决问题了。这个方法的适用性很好,因为你可以靠插入的空格数量自用调整列宽,同时又能避免列名或单元格内容自动换行。
-
这个透明的自动更新机制是:属性在声明时必须设置 NOTIFY,且当后端 C++ 对象中变更时要发射 NOTIFY 指定的属性值变更信号,当 QWebChanel 接收到这个信号时,发现与属性 NOTIFY 指定的信号一致,则说明:这个值发生了变更, QWebChanel 需要立即更新前端 Js 对象的属性值。这个过程是透明的,但如果没有 NOTIFY 声明或没有发出对应的信号,自动更新就不会发生。 ↩︎ ↩︎ ↩︎ ↩︎
-
是有条件的,属性必须设置了 NOTIFY 且在后端 C++ 对象中变更时要发射 NOTIFY 指定的属性值变更信号(就是 [1] 中描述的属性更新机制) ↩︎ ↩︎ ↩︎ ↩︎