Qt5的中文亂碼問題如何解決

Qt5的中文亂碼問題如何解決

Qt5的中文亂碼問題如何解決

如果使用msvc2005/2008/2010,那麼需要將包含中文的源文件保存為帶BOM的UTF8格式,並且使用QStringLiteral;如果要處理本地文件路徑,那麼需要使用QFile::encodeName和QFile::decodeName

參考:http://blog.csdn.net/dbzhang800/article/details/7325698

其它相關文章推薦
[Qt] 讀檔,讀取 txt 文字檔
[Qt] 寫檔,寫入 txt 文字檔
安裝 Qt 在 Windows 7 (使用MSVC)
Qt產生的exe發布方式
Qt 新增多國語言.ts翻譯檔案

Qt產生的exe發布方式

本篇將介紹如何在 Windows 下使用 Qt 提供的工具來佈署 exe,
你可能會問,我不是已經編譯出 exe 了嗎?為什麼還需要佈署呢?
佈署就是將這個 exe 執行時所需要的依賴檔全部都複製到指定目錄內,
最後這個目錄內的東西拿到任一台電腦上都可以執行了!

那接下來就來介紹怎麼使用吧!

使用 windeployqt 工具

假設編譯出來的執行檔名為 hello.exe, 使用 windeployqt 來佈署(會自動找出相依的dll複製到此目錄下)

1
windeployqt hello.exe

設定 VCINSTALLDIR 環境變數

使用 windeployqt 可能出現下列訊息

1
Warning: Cannot find Visual Studio installation directory, VCINSTALLDIR is not set.

設置環境變量 VCINSTALLDIR 的值為 VS 目錄,
比如我的 C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC

加完以後 windeployqt 會多複製一個 vcredist_x86.exe / vcredist_x64.exe 到資料夾下

參考
Qt官方開發環境生成的exe發布方式–使用windeployqt
如何將QT 5.5.1程式佈署在Windows
Tutorial Qt Creator - Installer Framework (Instalar aplicaciones de Qt en Windows) - 如何打包成安裝檔教學
QT編譯好的檔案無法執行的一種解決方案

其它相關文章推薦
[Qt] 讀檔,讀取 txt 文字檔
[Qt] 寫檔,寫入 txt 文字檔
安裝 Qt 在 Windows 7 (使用MSVC)
Qt產生的exe發布方式
Qt 新增多國語言.ts翻譯檔案
Qt5的中文亂碼問題如何解決

旋轉矩陣 轉 尤拉角 (Conversion Euler To Matrix)

我寫出了屬於我自己的兩種版本, 如下

版本一

參考來源

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
/** this conversion uses conventions as described on page:
* https://www.euclideanspace.com/maths/geometry/rotations/euler/index.htm
* Coordinate System: right hand
* Positive angle: right hand
* Order of euler angles: heading first, then attitude, then bank
* matrix row column ordering:
* [m00 m01 m02]
* [m10 m11 m12]
* [m20 m21 m22]*/
public final void rotate(matrix m) {
// Assuming the angles are in radians.
if (m.m10 > 0.998) { // singularity at north pole
heading = Math.atan2(m.m02,m.m22);
attitude = Math.PI/2;
bank = 0;
return;
}
if (m.m10 < -0.998) { // singularity at south pole
heading = Math.atan2(m.m02,m.m22);
attitude = -Math.PI/2;
bank = 0;
return;
}
heading = Math.atan2(-m.m20,m.m00);
bank = Math.atan2(-m.m12,m.m11);
attitude = Math.asin(m.m10);
}

轉成 opencv 的版本, 且對應到我的座標系 (x, z 對調), 最後 x y 軸還加上負號.
bank(x) -> attitude(x)
heading(y) -> heading(y)
attitude(z) -> bank(z)
euclideanspace -> 我的座標系(OpennGL)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Vec3f matrix2Euler(const Mat &R) {
// Assuming the angles are in radians.
float heading, attitude, bank;
if (R.at<double>(1,0) > 0.998) { // singularity at north pole
heading = atan2(R.at<double>(0,2),R.at<double>(2,2));
attitude = M_PI/2;
bank = 0;
return Vec3f(bank, heading, attitude);
}
if (R.at<double>(1,0) < -0.998) { // singularity at south pole
heading = atan2(R.at<double>(0,2),R.at<double>(2,2));
attitude = -M_PI/2;
bank = 0;
return Vec3f(bank, heading, attitude);
}
heading = atan2(-R.at<double>(2,0),R.at<double>(0,0));
bank = atan2(-R.at<double>(1,2),R.at<double>(1,1));
attitude = asin(R.at<double>(1,0));

return Vec3f(-bank, -heading, attitude);
}

版本二

參考來源

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
// Checks if a matrix is a valid rotation matrix.
static bool isRotationMatrix(const Mat &R)
{
Mat Rt;
transpose(R, Rt);
Mat shouldBeIdentity = Rt * R;
Mat I = Mat::eye(3,3, shouldBeIdentity.type());

return norm(I, shouldBeIdentity) < 1e-6;
}

/** rotation matrix to euler angles
* Coordinate System: right hand
* Positive angle: right hand
* Order of euler angles: heading first, then attitude, then bank
* matrix row column ordering:
* [m00 m01 m02]
* [m10 m11 m12]
* [m20 m21 m22]*/
Vec3f matrix2Euler(const Mat &R)
{
assert(isRotationMatrix(R));
float sy = sqrt(R.at<double>(0,0) * R.at<double>(0,0) + R.at<double>(1,0) * R.at<double>(1,0) );
bool singular = sy < 1e-6; // If

float x, y, z;
if (!singular)
{
x = atan2(R.at<double>(2,1) , R.at<double>(2,2));
y = atan2(-R.at<double>(2,0), sy);
z = atan2(R.at<double>(1,0), R.at<double>(0,0));
}
else
{
x = atan2(-R.at<double>(1,2), R.at<double>(1,1));
y = atan2(-R.at<double>(2,0), sy);
z = 0;
}
return Vec3f(x, y, z);
}

轉成 我的座標系 (z 軸加上負號).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Vec3f matrix2Euler(const Mat &R)
{
assert(isRotationMatrix(R));
float sy = sqrt(R.at<double>(0,0) * R.at<double>(0,0) + R.at<double>(1,0) * R.at<double>(1,0) );
bool singular = sy < 1e-6; // If

float x, y, z;
if (!singular)
{
x = atan2(R.at<double>(2,1) , R.at<double>(2,2));
y = atan2(-R.at<double>(2,0), sy);
z = atan2(R.at<double>(1,0), R.at<double>(0,0));
}
else
{
x = atan2(-R.at<double>(1,2), R.at<double>(1,1));
y = atan2(-R.at<double>(2,0), sy);
z = 0;
}
return Vec3f(x, y, -z);
}

Git submodule 子模組

本篇將介紹怎麼使用 Git 的 submodule 的功能,
通常在開發時有使用到外部第三方的函式庫時(例如:sub.git),
就可以使用 Git submodule 這個功能,
將外部的 Git (sub.git)加入進來,
此時我們自己的 Git (mainrepo.git) 會去記住目前是使用 sub.git 的哪一筆 commit,
而不是去追蹤紀錄整包 sub.git 的程式碼。
這樣 mainrepo.git 就會省很多硬碟空間。

新增 submodule

1
2
cd mainrepo
git submodule add git@github.com:aaa/sub.git sub

再推上 server

抓子模組 submodule

方法1. 一次抓下來

1
git clone --recursive git@github.com:aaa/mainrepo.git

方法二. 先抓完, 再抓submodule

1
2
3
4
git clone git@github.com:aaa/mainrepo.git
cd mainrepo
git submodule init
git submodule update --recursive

移除抓下來的 submodule (清空而已)

1
git submodule deinit .

Git tag 標籤使用

新增 tag

1
2
git tag -a v0.9.0 -m '0.9.0'
git tag -a v1.0.0 -m '1.0.0'

針對很久以前 commit 的進行 tag

1
git tag -a v0.9.0 -m '0.9.0' a1b2c3456

上傳指定的 tag 到遠端

1
git push origin v0.9.0

一次上傳多個 tag 到遠端

1
git push origin --tags

刪除遠端 tag

1
git push origin :refs/tags/v1.1.0

刪除本地 tag

1
git tag -d v1.0.0

C語言跨平台寫法

C 語言跨平台是門專業的學問,為什麼這麼說呢?
因為平常一般開發者要開發跨平台程式的話,一開始就可以選擇跨平台的應用程式框架,例如:Qt
就很少遇到跨平台改寫的問題了。

但是將現有的產品程式碼移植或改成跨平台,
就會遇到跨平台改寫的問題,
不過畢竟是少數人才會遇到的經驗,
所以以下將我遇到的經驗紀錄一下,

通常有幾個api最容易遇到,例如:sleep,開 thread 執行緒,tmux 鎖,
以下將逐一介紹:

sleep

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#if defined(_WIN32)
#include <Windows.h>
#else
#include <unistd.h>
#endif

inline void sleep(int milliseconds)
{
#if defined(_WIN32)
Sleep(milliseconds);
#else
usleep(milliseconds * 1000);
#endif
}

參考
https://github.com/libimobiledevice/libusbmuxd/blob/c724e70fb52ba45291dc73a2e369c0c5bae0ec2e/src/libusbmuxd.c#L57
https://github.com/vurtun/mmx/blob/f0ef47edc2077bc498880f7d3032c37e68f79219/tests/web_test.c#L52

其它相關文章推薦
C/C++ 新手入門教學懶人包

開源專案TinyTcp-輕巧的網路程式框架

介紹

This is a C++ socket wrapper designed to fast development of network related functionality.

動機

有鑑於以前寫太多 socket 程式,這次寫一套,但之後又沒拿出來用,又在寫一套,這樣太浪費時間,
這次決定寫一個輕巧的網路框架,讓以後需要時在拿出來使用,即使是需要重構。
重點是以後有需要網路功能的程式直接套用,這樣開發上能夠更快速些,
對於軟體開發前期,能夠快速驗證,是件很種要的事情。

當然我這輕巧的網路框架還需要能夠跨平台,因為平時的我都會在 Windows、Ubuntu、MacOS 上切換來換去,
跨平台是必不可免的!

目的

  • thread-base (不用event-base, 那樣寫太累, 要寫更久),直接用 C++11 的 thread 來搞定!
  • 跨平台 (當然是先在一個平台下搞定後, 再用跨到其他平台)
  • onRecv,onDisconnect,onConnect 這些 api 訂出來, 這是重要的窗口!
  • 既然是 tiny,檔案數就不能太多,最多兩個 class

Github 連結:https://github.com/shengyu7697/TinyTcp


其他類似專案

sokkit - A lightweight C++ socket wrapper.
學習怎麼寫 TEST_CASE

cppsocket - C++ socket wrapper
平台定義

1
2
3
4
5
6
#ifdef _WIN32
typedef SOCKET socket_t;
#else
typedef int socket_t;
#define INVALID_SOCKET -1
#endif

libting - ting was started as a simple cross platform C++ wrapper for threading (thread, mutex, semaphore, message queue and message). But now ting is not only a threading library, now it is a utility framework containing also Network Sockets API library and some other useful stuff, e.g. reference counted pointers etc. See WiKi page for what is there.
https://code.google.com/archive/p/ting/

clsocket - SimpleSockets is a lightweight set of classes that allow developers to implement IP based network programs.
libsocket - The ultimate socket library for C and C++, supporting TCP, UDP and Unix sockets (DGRAM and STREAM) on Linux, FreeBSD, Solaris. Only ZMQ is better.
Practical C++ Sockets

其它相關文章推薦
開源專案ScreenCapture-螢幕截圖自動存檔小工具
開源專案CursorJail-滑鼠鎖定工具
開源專案-2048
開源專案-tetris俄羅斯方塊
開源專案-數獨sudoku
開源專案-金庸群俠傳
開源專案-仙劍奇俠傳

慣C除錯

本篇介紹在 C/C++ 下使用 printf 來 debug 的一些技巧,

Gist

https://stackoverflow.com/questions/1941307/c-debug-print-macros

最簡單的

1
#define DEBUG_PRINT(fmt, ...)  printf("[DEBUG] %s, %s(), line:%d, msg:" fmt, __FILE__, __func__, __LINE__, ##__VA_ARGS__)

Tom Kuschel 的版本

1
2
3
4
5
6
7
8
#define DEBUG 3

#if defined(DEBUG) && DEBUG > 0
#define DEBUG_PRINT(fmt, ...) fprintf(stderr, "[DEBUG] %s:%d:%s(): " fmt, \
__FILE__, __LINE__, __func__, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...) // Don't do anything in release builds
#endif

以下為我的版本, DEBUG 可以定義不同數字等級, 決定輸出的訊息種類.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define DEBUG 4
#if defined(DEBUG)
#if DEBUG >= 4 // filename:function:line
#define DEBUG_PRINT(fmt, ...) fprintf(stderr, "[DEBUG] %s:%s():%d " fmt, \
__FILE__, __func__, __LINE__, ##__VA_ARGS__)
#elif DEBUG >= 3 // filename:function
#define DEBUG_PRINT(fmt, ...) fprintf(stderr, "[DEBUG] %s:%s() " fmt, \
__FILE__, __func__, ##__VA_ARGS__)
#elif DEBUG >= 2 // filename:line
#define DEBUG_PRINT(fmt, ...) fprintf(stderr, "[DEBUG] %s:%d " fmt, \
__FILE__, __LINE__, __func__, ##__VA_ARGS__)
#elif DEBUG >= 1 // function:line
#define DEBUG_PRINT(fmt, ...) fprintf(stderr, "[DEBUG] %s():%d " fmt, \
__func__, __LINE__, ##__VA_ARGS__)
#endif
#else
#define DEBUG_PRINT(fmt, ...) // Don't do anything in release builds
#endif

使用

1
2
DEBUG_PRINT("Debugging is enabled.\n");
DEBUG_PRINT("Debug level: %d", (int) DEBUG);


20180220 updated: libusbmuxd 另一種用法


20190409 updated: 新增顯示檔名

1
2
3
4
5
#include <string.h>
// 提醒:For Windows use '\\' instead of '/'.
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
// function() filename:line
#define DRBUG_PRINT(fmt, ...) do { fprintf(stderr, "[DEBUG] %s() %s:%d " fmt, __FUNCTION__, __FILENAME__, __LINE__, ##__VA_ARGS__); } while(0)

其它相關文章推薦
C/C++ 新手入門教學懶人包