Qt君


  • 首页

  • 关于

  • 归档

  • 搜索

Qt官方示例-Http

发表于 2019-11-03

通过get接口对url资源下载,并显示下载进度。

main_page

0x00 Http请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void HttpWindow::startRequest(const QUrl &requestedUrl)
{
...
reply = qnam.get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &HttpWindow::httpFinished);
connect(reply, &QIODevice::readyRead, this, &HttpWindow::httpReadyRead);

ProgressDialog *progressDialog = new ProgressDialog(url, this);
progressDialog->setAttribute(Qt::WA_DeleteOnClose);
connect(progressDialog, &QProgressDialog::canceled, this, &HttpWindow::cancelDownload);
connect(reply, &QNetworkReply::downloadProgress, progressDialog, &ProgressDialog::networkReplyProgress);
connect(reply, &QNetworkReply::finished, progressDialog, &ProgressDialog::hide);
...
}

0x01 下载进度

  使用以下接口获取下载进度。

1
2
void QNetworkReply::downloadProgress(qint64 bytesReceived, 
qint64 bytesTotal);

main_page

0x02 网络验证(如有需要)

  绑定authenticationRequired信号:

1
2
connect(&qnam, &QNetworkAccessManager::authenticationRequired,
this, &HttpWindow::slotAuthenticationRequired);

  验证动作:

1
2
3
4
5
6
7
8
9
10
11
12
13
oid HttpWindow::slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator)
{
...
// Did the URL have information? Fill the UI
// This is only relevant if the URL-supplied credentials were wrong
ui.userEdit->setText(url.userName());
ui.passwordEdit->setText(url.password());

if (authenticationDialog.exec() == QDialog::Accepted) {
authenticator->setUser(ui.userEdit->text());
authenticator->setPassword(ui.passwordEdit->text());
}
}

0x03 关于更多

  • 在QtCreator软件可以找到:

what_find

  • 或在以下Qt安装目录找到

    1
    C:\Qt\{你的Qt版本}\Examples\{你的Qt版本}\network\http
  • 相关链接

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

QString较少用到的接口

发表于 2019-11-02

介绍QString较少使用却很有用的接口。

0x00 移除行首行尾的空白字符

  空白字符包含:’\t’, ‘\n’, ‘\v’, ‘\f’, ‘\r’和’ ‘。
  接口:

1
QString QString::trimmed() const

  示例:

1
2
3
QString str = "  lots\t of\nwhitespace\r\n ";
str = str.trimmed();
// str == "lots\t of\nwhitespace"

0x01 移除行首行尾空白字符并将每个内部空白序列替换为一个空格。

1
2
3
QString str = "  lots\t of\nwhitespace\r\n ";
str = str.simplified();
// str == "lots of whitespace";

0x02 QString转QStringList

1
2
3
QStringList QString::split(const QString &sep, 
QString::SplitBehavior behavior = KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const
1
2
3
4
5
6
7
QString str = "a,,b,c";

QStringList list1 = str.split(',');
// list1: [ "a", "", "b", "c" ]

QStringList list2 = str.split(',', QString::SkipEmptyParts);
// list2: [ "a", "b", "c" ]

  另外QStringList转QString可以使用以下接口:

1
QString QStringList::join(const QString &separator) const

0x03 截取指定位置内容

1
void QString::truncate(int position)

  示例:

1
2
3
QString str = "Hello world";
str.truncate(5);
// str == "Hello"

0x04 计算字符串的某个字符个数

1
2
int QString::count(QChar ch, 
Qt::CaseSensitivity cs = Qt::CaseSensitive) const

qmake实用函数

发表于 2019-11-01

介绍些qmake使用频率较高的函数。

0x00 判断某个类型是否存在:

  • 原型:
    1
    defined(name[, type])
type 含义
test 检查测试函数
replace 检查代替函数
var 检查变量
  • 示例(判断变量是否存在):
    1
    2
    3
    defined(COPY_TARGET, var) {
    ...
    }

0x01 变量列表是否包含某个变量

  • 原型:

    1
    contains(variablename, value)
  • 示例:

    1
    2
    3
    contains(QT, core) {
    ...
    }

0x02 判断变量值是否相等

  • 原型:

    1
    equals(variablename, value)
  • 示例:

    1
    2
    3
    4
    TARGET = Test
    equals(TARGET, "Test") {
    ...
    }

0x03 打印输出

  • 原型:
    1
    2
    3
    4
    message(string)
    log(string)
    warning(string)
    error(string)

0x04 测试变量是否大于某个值

  • 原型:

    1
    greaterThan(variablename, value)
  • 示例(判断Qt版本):

    1
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

0x05 系统调用

  • 原型:
    1
    system(command)

解决QWindowsContext OleInitialize错误

发表于 2019-10-31

使用Qt应用程序使用webrtc库运行时错误的解决笔记。

0x00 错误重现

  • 伪代码:

    1
    2
    3
    4
    5
    6
    int main(...) 
    {
    QApplication app(argc, argv);
    webrtc *w = createOneWebrtc();
    return app.exec();
    }
  • 使用QApplication创建应用程序的事件循环后报以下错误。

    1
    QWindowsContext: OleInitialize() failed:  "COM error 0xffffffff80010106 RPC_E_CHANGED_MODE (Unknown error 0x080010106)"

  OleInitialize是一个Windows API函数。它的作用是在当前单元(apartment)初始化组件对象模型(COM)库,应用程序必须在调用COM库函数之前初始化COM库。每个线程不能初始化多次。

0x01 分析问题

  • 由于QApplication会在主线程初始化COM组件(OleInitialize),而webrtc库也会在主线程初始化COM组件(OleInitialize)导致后者报错。

0x02 解决方法

  • 使用独立线程操作webrtc库。
  • 如:
    1
    2
    3
    4
    5
    6
    7
    int main(...) 
    {
    QApplication app(argc, argv);
    QFuture<webrtc *> future = QtConcurrent::run(createOneWebrtc);
    webrtc *w = future.result();
    return app.exec();
    }

使用boost库实现的CRC64示例

发表于 2019-10-30

网上比较多的CRC16,CRC32校验实现,但CRC64却很难找,最近也有用到,所以特意地写一个CRC64示例分享给大家。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
 #include <boost/crc.hpp>
string CRC64(const string &inputStr)
{
boost::crc_optimal<64, 0x42F0E1EBA9EA3693,
0xffffffffffffffff, 0xffffffffffffffff,
false, false> crc;

crc.process_bytes(str.c_str(), str.size());

char crcStr[128] = {0};
sprintf_s(crcStr, 128, "%016llx", crc.checksum());
return crcStr;
}

检验

  • 位数: 64bits
  • 系数(除数多项式的最小系数): 0x42F0E1EBA9EA3693
  • xor_in(多项式余数的初始状态): 0xffffffffffffffff
  • xor_out(多项式余数的输出掩码): 0xffffffffffffffff
  • reflected_in(反射输入状态): false
  • reflected_out(反射输出状态): false
  • 输入值(“123456789”) -> 输出值”62ec59e3f1a4f00a”

参考

https://www.boost.org/doc/libs/1_71_0/boost/crc.hpp
https://stackoverflow.com/questions/50765230/use-boost-to-compute-ecma-128-64bit-crc

cmd命令笔记

发表于 2019-10-29

介绍一些开发中常用到的cmd命令。

命令 作用
dir 列出文件和目录
cd 目录 进入目录
del 文件名 删除文件
rd 目录 删除目录
cls 清屏
time /t 显示当前时间
date /t 显示当前日期
start 目录路径 打开所在路径的文件资源管理器
如start .在当前路径打开文件资源管理器
mshta vbscript:msgbox(“内容”,64,”标题”)(window.close) 创建一个消息窗口

Qt官方示例-Markdown编辑器

发表于 2019-10-27

基于QWebEngineView与QWebChannel实现的Markdown编辑器。

main_page

0x00 原理

  Markdown编辑器演示了如何使用QWebChannel和JavaScript库为自定义标记语言提供富文本预览工具。

  Markdown是一种轻量级的标记语言,具有纯文本格式语法。可以在浏览器中查看时将内容呈现为富文本格式。

  Markdown编辑器主窗口分为编辑区域和预览区域。

  • 编辑区域(左栏):
    该编辑器区域使用QPlainTextEdit实现。

  • 预览区域(右栏):
    预览区域使用QWebEngineView实现的。为了呈现文本,借助Web引擎内部的JavaScript库,将Markdown文本转换为HTML格式。预览是通过QWebChannel发送编辑区域的文本内容到QWebEngineView渲染(支持边编辑边渲染更新)。

0x01 实现

  • 为编辑区域加载markdown格式文件。

    1
    2
    3
    QFile defaultTextFile(":/default.md");
    defaultTextFile.open(QIODevice::ReadOnly);
    ui->editor->setPlainText(defaultTextFile.readAll());
  • 使用QWebChannel绑定page(QWebEngineView)对文本进行更新。

    1
    2
    3
    4
    5
    6
    connect(ui->editor, &QPlainTextEdit::textChanged,
    [this]() { m_content.setText(ui->editor->toPlainText()); });

    QWebChannel *channel = new QWebChannel(this);
    channel->registerObject(QStringLiteral("content"), &m_content);
    page->setWebChannel(channel);
  • 加载网页文件用于接收ui->editor(QPlainTextEdit)的内容。

    1
    ui->preview->setUrl(QUrl("qrc:/index.html"));
  • 在index.html中,我们加载一个自定义样式表和两个JavaScript库。markdown.css是由Kevin Burke创建的markdown友好样式表。marked.js是Markdown解析器和编译器,由Christopher Jeffrey编写,旨在提高速度,而qwebchannel.js是QWebChannel模块的一部分(用于数据交互)。

    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
    <!doctype html>
    <html lang="en">
    <meta charset="utf-8">
    <head>
    <link rel="stylesheet" type="text/css" href="3rdparty/markdown.css">
    <script src="3rdparty/marked.js"></script>
    <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
    </head>
    <body>
    <div id="placeholder"></div>
    <script>
    'use strict';

    var placeholder = document.getElementById('placeholder');

    var updateText = function(text) {
    placeholder.innerHTML = marked(text);
    }

    new QWebChannel(qt.webChannelTransport,
    function(channel) {
    var content = channel.objects.content;
    updateText(content.text);
    content.textChanged.connect(updateText);
    }
    );
    </script>
    </body>
    </html>
  • uml简图
    uml

0x02 关于更多

  • 在QtCreator软件可以找到:
    what_find

  • 或在以下Qt安装目录找到

    1
    C:\Qt\{你的Qt版本}\Examples\{你的Qt版本}\webenginewidgets\markdowneditor
  • 相关链接

    1
    https://doc.qt.io/qt-5/qtwebengine-webenginewidgets-markdowneditor-example.html
  • Qt君公众号回复『Qt示例』获取更多内容。

Qt 5.12部分版本网络模块重大缺陷(建议升级)

发表于 2019-10-26

使用Qt 5.12.0或Qt 5.12.1网络模块进行网络请求操作时报错,导致的后果是请求无法进行。强烈建议升级Qt版本到5.12.2及其以上。

  • 错误描述:使用了QNetworkAccessManager的get,post网络请求接口。报下列错误:

    1
    QNetworkReplyHttpImplPrivate::_q_startOperation was called more than once QUrl
  • 涉及版本:Qt 5.12.0,Qt 5.12.1

  • 修复版本:Qt 5.12.2

插图

插图


  • 更多精彩内容请关注公众号『Qt君』。

Linux QQ 2.0 Beta版初体验

发表于 2019-10-25

Linux QQ最新版悄悄上架了,Linux版的QQ可谓是”十年磨一剑”啊!那就让我们看看最新版QQ都有哪些功能?

下载安装

  • 地址:
    1
    https://im.qq.com/linuxqq/download.html

download

  • Qt君使用的是Ubuntu 16.04系统,所以选择x64的shell下载安装。

install

登录界面

  • 运行起来了,看登录界面怎么有点熟悉的感觉像是以前的web版本的QQ。

login

主界面

  • 主界面是最近联系人,联系人,群组,看起来实在太简洁了。QQ签名不显示就算了,但Qt君最近才充的会员居然不显示出来,功能有待完善。

info

设置功能

  • 点击个人头像显示的基本资料,还可以换肤设置。

my_info

  • 设置快捷键。

setting

聊天功能

  • 惊呆了打开一看,十几年前的QQ风格。咋认真一看,感觉像是初学者练手的聊天界面。

chat2

  • 可以发表情,图片,截屏,文件(不可用)。

emoji

使用感受

  • 界面存在较多的bugs(卡顿,闪退,换肤界面关不掉);
  • 界面相对简陋,但满足基本的聊天功能;
  • 与旧版本相比差太多了,有待优化。

不报错调用空指针类的成员函数

发表于 2019-10-23

究竟什么原因使得空指针实例调用成员函数也能正常运行?

  猜猜下列例子运行会有什么结果?

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
class A
{
public:
static void print()
{
printf(">>>>>\n");
}

void print2()
{
printf("+++++\n");
}

void print3()
{
printf("====%d\n", value);
}

private:
int value;
};

int main(int argc, char *argv[])
{
A *a = NULL;
a->print();
a->print2();
a->print3();
return 0;
}

  运行结果:

1
2
3
a->print()  输出:>>>>>
a->print2() 输出:+++++
a->print3() 程序段错误

  前两个应该都会段错误才对的呀,怎么都运行正常了。其实上述的行为都由this指针左右结果。

0x00 静态函数没有this指针

  静态方法随着类的加载而加载,静态方法不需要实例化。不会引用到this指针里面的数据,所以static void print()不会报错。

0x01 成员函数不使用this指针不报错

  a->print();可以近似看作void print(A *a)调用,展开是这样:

1
2
3
4
void print(A *a)
{
printf("+++++\n");
}

  由此A的实例a指针没有被使用,不会访问到错误的地址而出现异常。

0x02 空指针引用实例成员才会异常

  void print3()中使用了实例a的value成员,由于a为空,没有指向具体的内存,导致引用value内存出错。

0x03 总结

  上述行为引起段错误的原因是空指针实例引用了成员变量导致的。


更多精彩文章请关注微信公众号:「Qt君」

1234…32
Qt君

Qt君

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