Qt君


  • 首页

  • 关于

  • 归档

  • 搜索

string与char *小知识

发表于 2019-10-01

在C++中,使用字符串相对于char *,我更倾向于使用string。其优点更安全,更多的易用接口。

  简化的string类似于下列实现,除了比char 多几个字节的占用空间外几乎一样,但比char 省心很多,这也是C++的”++”表现之一。

1
2
3
4
struct string {
char* data;;
size_t length;
};

不继承QObject也可以使用tr函数

发表于 2019-09-29

一个类如果不继承QObject是不能直接使用tr函数,有什么方法可以在不继承QObject的情况下又能直接使用tr函数呢?答案是使用Q_DECLARE_TR_FUNCTIONS宏。

使用

  • 在类中用Q_DECLARE_TR_FUNCTIONS宏定义该类。
  • 可以直接使用tr与trUtf8静态方法。
    1
    2
    3
    4
    static inline QString tr(const char *sourceText,
    const char *comment = 0);
    static inline QString trUtf8(const char *sourceText,
    const char *comment = 0);

示例

1
2
3
4
5
6
7
8
9
10
class Test
{
Q_DECLARE_TR_FUNCTIONS(Test)
public:
Test()
{
qDebug() << tr("text");
qDebug() << trUtf8("utf8-text");
}
};

前瞻Qt5.14支持markdown语法

发表于 2019-09-29

在2019/09/25的Qt5.14评估版本中看到QTextEdit和QTextBrowser支持markdown格式。编写文本(笔记,文章等)上markdown相对于html语法,其简洁,方便,高效。

支持markdown的类

  • QTextDocument
  • QTextEdit和QTextBrowser
  • Qml的Text和TextEdit

插图

  • QTextDocument支持标准markdown语法和CommonMark,GitHub规范允许的范围内保留格式(包括标题,表格,列表,引用块和代码块)。
  • 默认情况下它们还支持markdown与html混合语法编写。
  • QTextBrowse::setSource()基于文件扩展名识别Markdown语法。

效果

显示效果

附录markdown文本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 1.标题
# 标题1
## 标题2
### 标题3
#### 标题4
##### 标题5
###### 标题6
---

# 2. 列表
* list1
* list2
* list3
---

# 3. 嵌套列表
1. 第一项:
- 第一项嵌套的第一个元素
- 第一项嵌套的第二个元素
2. 第二项:
- 第二项嵌套的第一个元素
- 第二项嵌套的第二个元素
---

# 4. 任务列表
- [ ] task1
- [x] task2
- [x] task3
---

# 5. 文字格式
**粗体文本**
_斜体文本_
_**粗斜体文本**_
~~删除线文本~~
<u>带下划线文本</u>
<font face="微软雅黑" >微软雅黑字体</font>
<font size=1 >1号字</font>
<font size=2 >2号字</font>
<font color=#FF0000 >红色</font>
<font color=#008000 >绿色</font>
<font color=#0000FF >蓝色</font>

---

# 6. 分隔线
---

# 7. 表格
| 表头1 | 表头2 |
| ---- | ---- |
| 单元格1 | 单元格2 |
| 单元格3 | 单元格4 |

ref:https://wiki.qt.io/New_Features_in_Qt_5.14

程序打包问题及解决方法汇总

发表于 2019-09-28

一直来被问得最多的是关于windows系统上程序打包上问题,不能运行,在我的机器能运行,别的机器不能运行的情况。经过一段时间的整理,将一些问题和解决方法都列出来供大家参考。

0x00

  小白:怎么我编译好的程序在QtCreator能运行,但我在文件夹下打开却不行了呢?
  Qt君:因为QtCreator运行下的程序附带了运行环境,而离开了QtCreator软件没有运行环境会报以下的一些错误(库找不到)。

插图
插图
插图
插图

0x01

  小白:那我该怎么找这些库呢?
  Qt君:你可以根据你的编译配置(Qt版本,编译器,32/64位,release/debug)来选用不同的windeployqt.exe工具帮你生成Qt依赖的运行库。

windeployqt

  • 一般程序生成方法:

    1
    windeployqt xxx.exe
  • 如果是使用QML组件需要这样操作:

    1
    windeployqt xxx.exe --qmldir qmlPath
  • 注意: 请使用Qt提供的控制台操作。

  • 可以参考Qt快捷打包程序方法获取更多信息。

0x02

  小白:怎么会出现PTLib.dll找不到的问题?
  Qt君:由于windeploqt.exe工具并不能找到第三方库,这时候需要自己对应将库复制到程序的运行目录下。

0x03

  小白:0xc000007b错误代码这个又怎么了?

错误示例
  Qt君:可能是你打包时候使用了版本不对应的windeploqt.exe工具,你当时使用的是什么版本的windeploqt.exe?
  小白:Qt5.12.2 (MSVC 2017 64-bit)

qt5.12.2_msvc_2017_64
  Qt君:你的程序版本是Qt5.12.2 (MSVC 2017 32-bit),而windeploqt.exe版本是生成64位的库不对咯,你修改为对应的windeploqt.exe就可以了。

0x04

  小白:”无法找到入口”?

无法找到入口问题示例

  小白:哦,我明白了。我使用了mingw版本的windeploqt.exe与程序使用MSVC编译器不一样导致生成的程序库找不到入口。
  Qt君:不错,学会举一反三了。

0x05

  小白:现在才举一反二,还差一例就举一反三了。在使用windeploqt.exe过程中,看到有一个--release参数,在msvc的windeploqt.exe下似乎默认为release参数,但我使用mingw时候却生成的是debug版本的程序库(例:Qt5Cored.dll带d标识)。我还是每次生成之前都输入--release或--debug参数了,以防万一。

0x06

  小白:这个问题很诡异,它又不提示库找不到,就显示了这信息,该怎么解决呢?

错误示例

  Qt君:造成这一问题有很多,但最有可能的是没有生成platforms/qwindows.dll插件。你可以尝试删除目录下的库再重新生成试一试,或者在对应的Qt安装目录下复制platforms/qwindows.dll插件到自己程序的运行目录下。注意要带上platforms目录。

0x07

  小白:我用本机能运行,但在其他机器不能运行?
  Qt君:主要是缺windows相关库。
复制以下路径的库文件到运行目录下:

1
2
C:\Windows\System32 (注意:32位编译程序复制)
C:\Windows\SysWOW64 (注意:64位编译程序复制)

插图

0x08

  小白:这次太糟了,双击程序完全没反应,只是一个简单的QML应用,怎么回事呀?
  Qt君:由于QML应用大量使用了插件形式的缘故吧。比如import QtQuick.Shapes 1.12则会在程序运行时加载Shapes模块插件。你可以这样,在程序的项目文件添加CONFIG += console然后在命令行执行,看调试输出。因为qml没有断言输出,导致不能弹框警告错误。
  小白:运行后看调试输出貌似是缺少Shapes模块。

1
2
3
C:\Users\Strong\Documents\Deploy>Test.exe
QQmlApplicationEngine failed to load component
qrc:/main.qml:3 module "QtQuick.Shapes" is not installed

  Qt君:由于windeploqt.exe工具并不能解析到程序加载的插件,这就导致某些插件没有被复制到,需要手动复制添加Shapes插件。

  解决方法:

  • 将Shapes目录

    1
    C:\Qt\Qt5.12.2\5.12.2\msvc2017\qml\QtQuick\Shapes
  • 复制到运行目录(C:\Users\Strong\Documents\Deploy)的QtQuick目录下

    1
    C:\Users\Strong\Documents\Deploy\QtQuick

  如出现以下问题还需要将Qt5QuickShapes.dll复制到程序运行目录下

1
2
3
C:\Users\Strong\Documents\Deploy>Test.exe
QQmlApplicationEngine failed to load component
qrc:/main.qml:3 plugin cannot be loaded for module "QtQuick.Shapes": Cannot load library C:\Users\Strong\Documents\Deploy\QtQuick\Shapes\qmlshapesplugin.dll

  • 将Qt5QuickShapes.dll文件

    1
    C:\Qt\Qt5.12.2\5.12.2\msvc2017\bin\Qt5QuickShapes.dll
  • 复制到运行目录下

    1
    C:\Users\Strong\Documents\Deploy\

0x09

  • 复制文件到其他机器过程中导致文件损坏运行不了。
  • 版本不一致的程序库会知道各种奇怪问题。如:5.12.1的程序放在5.12.2库中。
  • 找缺库的工具还可以使用​depends.exe。

0x0a

  • Qt君公众号后台回复『打包问题』获取更多相关信息。

Qt使用protobuf笔记

发表于 2019-09-27

解决使用protobuf库过程中出现的编译问题。protobuf和XML,json一样的数据结构。

插图

问题1

  • 缺protobuf库,可以定义PROTOBUF_USE_DLLS来链接protobuf库。

    1
    无法解析的外部符号 "class google::protobuf::internal::ExplicitlyConstructed<class std::basic_string<char,struct std::char_traits,class std::allocator > >
  • 解决方法:

    1
    DEFINES += PROTOBUF_USE_DLLS

问题2

  • std::min,std::max与windows.h的min,max冲突了。

    1
    2
    3
    4
    5
    .pb.h:189: warning: C4003: 类函数宏的调用“min”参数不足
    .pb.h:189: warning: C4003: 类函数宏的调用“max”参数不足
    .pb.h:189: error: C2589: “(”:“::”右边的非法标记
    UserInfo_STATE_UserInfo_STATE_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
    UserInfo_STATE_UserInfo_STATE_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
  • 解决方法:
    屏蔽windows.h的min, max方法

    1
    DEFINES += NOMINMAX

Qt官方示例-速度仪表盘

发表于 2019-09-26

该刻度盘控件为一个速度仪表盘。

预览

插图

运行演示

演示

分析

  • 采用Qml语言实现;
  • 使用到了图片素材(刻度盘,指示器,指示器阴影,覆盖层);
    插图

  • 它结合了Image元素,Rotation变换和SpringAnimation行为,用来组合生成交互式的速度仪表盘。

  • 核心代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    Item {
    id: root
    property real value : 0

    width: 210; height: 210

    Image { source: "background.png" }

    //! [needle_shadow]
    Image {
    x: 96
    y: 35
    source: "needle_shadow.png"
    transform: Rotation {
    origin.x: 9; origin.y: 67
    angle: needleRotation.angle
    }
    }
    //! [needle_shadow]
    //! [needle]
    Image {
    id: needle
    x: 98; y: 33
    antialiasing: true
    source: "needle.png"
    transform: Rotation {
    id: needleRotation
    origin.x: 5; origin.y: 65
    //! [needle angle]
    angle: Math.min(Math.max(-130, root.value*2.6 - 130), 133)
    Behavior on angle {
    SpringAnimation {
    spring: 1.4
    damping: .15
    }
    }
    //! [needle angle]
    }
    }
    //! [needle]
    //! [overlay]
    Image { x: 21; y: 18; source: "overlay.png" }
    //! [overlay]
    }

关于更多

  • 在QtCreator软件可以找到:
    插图

  • 或在你的Qt安装目录C:\Qt\{你的Qt版本}\Examples\{你的Qt版本}\quick\customitems\dialcontrol找到。

  • 相关链接

    1
    https://doc.qt.io/qt-5/qtquick-customitems-dialcontrol-example.html
  • Qt君公众号后台回复『Qt示例』获取更多内容。

使用png图像常见的一个警告

发表于 2019-09-25

libpng warning: iCCP: known incorrect sRGB profile

原因

  新版本(libpng-1.6)在检查ICC配置文件(主要用于色彩校正)方面更加严格。您可以忽略该警告,但有些应用程序会将该警告处理为错误。

解决方法

  删除PNG图像中iCCP块。为大家提供以下两种方法。

  1. Unix系统下可以使用convert工具转换

    1
    convert in.png out.png
  2. 可以使用Qt库实现来转换

    1
    2
    3
    QPixmap pixmap;
    pixmap.load("in.png");
    pixmap.save("out.png", "PNG");

关于更多

  • ICCP:iCCP嵌入式ICC配置文件。
    • 在PLTE和IDAT之前。如果存在iCCP块,则不应该存在sRGB块。
    • 另外,PNG数据流最多应包含一个嵌入式配置文件,无论是使用iCCP块显式指定还是使用sRGB块隐式指定。
  • ICC配置文件:颜色空间的描述(以国际颜色联盟(ICC)的形式)。
  • sRGB:标准RGB颜色空间(一个图像样本符合这个颜色空间的指示)。
  • ref:https://www.w3.org/TR/2003/PR-PNG-20030520/#11iCCP

关于Qt翻译功能的一些小想法

发表于 2019-09-24

Qt翻译功能最近用得好好的,却是一份新需求导致对这一功能的思考。

  最近接到一个新需求就是为公司的某个软件添加多语言翻译功能,由于之前已经做过类似的了。直接移植就可以了。可是实际上并不是那么简单,多语言共有9种。可是翻译人员不会用Qt的语言家软件。除了中英文自己翻译外,其余的7种语言都需要发给专门的翻译人员翻译。7种语言翻译都统一弄成excel文本给他们翻译,当他们翻译完成后又一个一个对应的填在语言家软件里,这操作做了两份语言后,实在是受不了了。心里碎碎念:这到底是什么翻译操作啊,太繁琐了。

  于是我不发excel文档给他们翻译了,和他们说你翻译到Qt的语言家软件吧。教他们安装Qt语言家,并教他们如何使用。说多是泪,我一顿操作猛如虎,一问他们会不会,都说太难了!只好放弃这一想法。顿时陷入沉思中,究竟是谁走漏了风声说:Qt翻译很简单的!!!

  还有就是,语言家提供提取Qt项目文件的翻译到文件,我想说的是这操作挺好的。但每次翻译字段更改的时候又要重新刷新一下翻译文件,这设计太难用了。我们常用的思维应该是修改翻译文本,再通过翻译文本去修改Qt项目的翻译字段。

  常常我们不论翻译和不翻译的文本都使用tr()包含一下,但这是用错了,或许有人会说:可以解决乱码问题呀。只能说有些系统能解决乱码问题。在没有翻译功能的前提下使用tr()会造成额外性能负担。还有就是tr()会根据类名标记翻译字段,这一点很想不明白。作者可能是使用类似命名空间的做法来实现翻译字段的命名空间限制,实际使用上只会增加额外的使用负担和学习成本。

  回到最初问题(重复工作多),没办法只能写一个小工具(csv转qm),csv格式文件可以被excel打开,而工具可以直接将csv文件转换为翻译二进制(qm后缀文件),这样就可以避免一个一个复制到语言家再翻译了。而对翻译人员也相对友好。


Qt君公众号回复『工具』获取该工具

为什么QtCreator保存文件即多一个换行符?

发表于 2019-09-23

看似不经意的行为,找找原因也挺有意思的。

  • 当光标移到文件末尾时可以更容易看到光标;
  • 在Unix中换行符是文本文件结束标志之一;
  • C标准文件中源文件必须是文本文件,这就导致了每行必须以换行符结尾,不然会导致编译错误的问题;
  • 某些工具也不喜欢没有以换行符结尾的文件。

如何取消自动添加换行符?

插图

轻量级Qt键盘-中文输入

发表于 2019-09-22

在原有的键盘基础上新增中文输入功能。

插图

中文候选栏

  中文输入候选栏ChineseWidget使用QListWidget和样式表实现:

setText输入对应拼音字母,即会加载符合的拼音中文。
pressedChanged信号函数即为当按键按下,传递对应的中文。

1
2
3
4
5
6
7
8
9
10
class ChineseWidget : public QListWidget {
Q_OBJECT
public:
ChineseWidget(QWidget *parent = NULL);
void setText(const QString &text);

signals:
void pressedChanged(const int &code, const QString &text);
...
};

  设置QListWidget:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
setFocusPolicy(Qt::NoFocus);
/* 设置为列表显示模式 */
setViewMode(QListView::ListMode);

/* 从左往右排列 */
setFlow(QListView::LeftToRight);

/* 屏蔽水平滑动条 */
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

/* 屏蔽垂直滑动条 */
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

/* 设置为像素滚动 */
setHorizontalScrollMode(QListWidget::ScrollPerPixel);

/* 设置鼠标左键拖动 */
QScroller::grabGesture(this, QScroller::LeftMouseButtonGesture);

/* 设置样式 */
setStyleSheet(R"(
QListWidget { outline: none; border:1px solid #00000000; color: black; }
QListWidget::Item { width: 50px; height: 50px; }
QListWidget::Item:hover { background: #4395ff; color: white; }
QListWidget::item:selected { background: #4395ff; color: black; }
QListWidget::item:selected:!active { background: #00000000; color: black; }
)");

加载中文字库

  字库加载在QMap<QString, QList<QPair<QString, QString>> >容器中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
QFile pinyin(":/ChineseLib/PinYin");
if (! pinyin.open(QIODevice::ReadOnly)) {
qDebug() << "Open pinyin file failed!";
return;
}

while (! pinyin.atEnd()) {
QString buf = QString::fromUtf8(pinyin.readLine()).trimmed();
QRegExp regExp("^[\u4E00-\u9FA5]+");

int index = regExp.indexIn(buf);
if (index == -1)
continue;

QString first = buf.right(buf.size() - regExp.matchedLength()); // 分离拼音字母
QString second = buf.mid(index, regExp.matchedLength()); // 分离中文

QList<QPair<QString, QString>> &tmp = m_data[first.left(1)]; // 取首字母做索引
tmp.append(qMakePair(first, second));
}

  部分字库内容预览:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
安a
按a
爱a
阿a
暗a
啊a
埃a
碍a
凹a
奥a
岸a
矮a
案a
俺a

匹配符合拼音的中文

  取拼音首字母索引,再匹配中文。

1
2
3
4
5
6
7
const QList<QPair<QString, QString>> &tmp = m_data[text.left(1)];
for (const QPair<QString, QString> &each : tmp) {
if (each.first != text) // 匹配是否符合的在容器里面拼音
continue;

addOneItem(each.second);
}

关于更多

  1. 轻量级Qt键盘-介绍篇
  2. 通过索引优化查找性能
  3. 公众号Qt君后台回复『Qt键盘』获取往期推送文章。
1…567…32
Qt君

Qt君

313 日志
41 标签
© 2019 Qt君
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4
粤ICP备 - 16070052号