Qt msvc2013 问题解决方案

编写 Remote-Control 的客户端代码,界面用Qt绘制,记录出现的问题及解决方案。

MSVC的Release问题

  • 使用Qt版本5.6.0, msvc2013。Release后缺少动态链接库。
  • msvc2013bin 目录下没有 mingwm10.dlllibgcc_s_dw2-1.dll等。
  • main() 函数顶部添加 QCoreApplication::addLibraryPath("./");
  • 将release出的 app.exe 拷贝到部署文件夹,path_to_msvc2013\bin\windeployqt.exe app.exe
  • 可能仍出现 无法定位动态链接库 Qt5Widgets.dll。环境变量中有 MikTex 的路径,该路径下包含 Qt5Widgets.dll, 将 msvc2013 在环境变量中的位置调整高于 MikTex
  • 或在部署文件夹下新建 qt.conf,指定 Library 加载目录。

部署程序图标

  • 程序图标 icon.ico
  • 在工程目录下 (与project.pro同目录)新建 icon.rc,添加 IDI_ICON1 ICON DISCARDABLE "icon.ico"
  • project.pro 中添加 RC_FILE = icon.rc
  • release可执行文件

宽字符转换

  • 执行 ShellExecute() 函数时,参数 3 需要宽字符。
  • ShellExecute(NULL, L"open", open_file_path, NULL , NULL, SW_SHOWNORMAL);
  • 编写函数 string2LPCWSTRstd::string 转为 LPCWSTR
1
2
3
4
5
6
7
inline LPCWSTR stringToLPCWSTR(std::string src){
size_t srcsize = src.length() + 1;
size_t convertedChars = 0;
wchar_t *wcstring = (wchar_t *)malloc(sizeof(wchar_t)*(src.length()-1));
mbstowcs_s(&convertedChars, wcstring, srcsize, src.c_str(), _TRUNCATE);
return wcstring;
}

Qt下UTF8和GBK的转换

  • UTF82GBK
1
2
3
4
5
6
inline QString UTF82GBK(const QString &inStr)
{

QTextCodec *gbk = QTextCodec::codecForName("GB18030");
QString u2g = gbk->toUnicode(inStr.toLocal8Bit());
return u2g;
}
  • GBK2UTF8
1
2
3
4
5
6
inline QString GBK2UTF8(const QString &inStr)
{

QTextCodec *gbk = QTextCodec::codecForName("GB18030");
QString g2u = gbk->toUnicode(gbk->fromUnicode(inStr));
return g2u;
}

Qt下线程和ui组件处理

  • 编写线程子函数 unsigned int __stdcall refreshThread(void* pM),试图在子线程中修改ui组件
  • handle = (HANDLE)_beginthreadex(NULL, 0, refreshThread, (void *)(&actives[i]), 0,NULL ); 参数 3 不能是非静态成员函数
  • Qt中只有 QApplication.exec() 主线程能对界面元素进行控制
  • 利用 signal/slot,在线程中创建一个 signal,在主线程中创建一个 slot。当线程修改界面时,发送 signal 通知主线程响应。

Qt的Sql操作

  • QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); 添加 sqlite,可添加第二个参数指定当前连接名称,未指定该参数则为默认连接
  • db.setDatabaseName("data.db"); 指定数据库文件
  • query = QSqlQuery(db); 创建查询
  • query.exec(""); 执行sql语句
  • 添加多个数据库时,addDatabase必须指定不同的连接名称,否则会覆盖默认连接或重名连接引发错误。

Socket通信频率问题

  • 使用同一个 buf 作为发送方的缓冲,当 buf长度过大,超过 Socket默认缓冲长度时,如果发送频率过快,socket的拆分发送将使 buf 同时读写,接收方将收到垃圾数据。
  • send 返回实际写入的字节数,检查发送的数目并移动缓冲窗口,结尾判断可以用字节填充。
  • 或缩小 buf 长度,但网络情况差的时候仍会写入垃圾数据,只是垃圾数据较少。传输二进制文件将因为垃圾数据的存在而无效。

一些组件的tips

  • 添加 QTableWidget 右键菜单
1
2
3
4
5
6
7
8
9
ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
popMenu = new QMenu(ui->tableWidget);
action = new QAction("connect",this);
void MainWindow::on_tableWidget_customContextMenuRequested(const QPoint &pos)
{
popMenu->clear(); // popMenu for QTableWidget
popMenu->addAction(action); // action for connect
popMenu->exec(QCursor::pos());
}
  • 滚动条位置设置
1
2
3
QTextEdit *edit = ui->textEdit;        // example for QTextEdit
QScrollBar *sb = edit->verticalScrollBar();
sb->setValue(sb->maximumHeight());
  • Qt正则
1
2
3
4
5
QString IPv4pattern("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b");
QRegExp IPv4rx(IPv4pattern);
if (IPv4rx.exactMatch("8.8.8.8")){
// example for IPv4 address check
}

参考文献:

原创作品,允许转载,转载时无需告知,但请务必以超链接形式标明文章原始出处(https://forec.github.io/2016/09/14/tips-for-qt/) 、作者信息(Forec)和本声明。

分享到