分类目录归档:Qt开发

Qt的相关开发

使用匿名函数,简易地把同步转异步

使用匿名函数,简易地把同步转异步。
大概思路,已经省去了线程池的相关说明。

#define MYASSERT(x)
 
typedef std::function<QVariant(void)> FunAsyncTask;
typedef std::function<void(QVariant)> FunSuccessCallBack;
typedef std::function<void(QVariant)> FunErrorCallBack;
 
//从KAsyncTask派生
class AsyncTask     
{
private:
	const FunAsyncTask task;
	const FunSuccessCallBack ok_cb;
	const FunErrorCallBack err_cb;
        const QPointer<QObject> callerThiz; //外部调用者的This指针,目的利用它来检验当前匿名函数所捕获的参数是否仍有效。
	QVariant result;
	QVariant err;
        //ToDo保存调用线程,调用线程与成功及错误的处理是同一个线程,也即是调用成功及错误之前先检查线程是否相同。
	int threadCallId; //任务请求的线程。
	int threadDoTaskId; //任务处理的线程
public:
	static void post_aync_task(QObject *thiz, FunAsyncTask t, FunSuccessCallBack ok, FunErrorCallBack err)
	{
		AsyncTask *task = new AsyncTask(thiz, t, ok, err);
		//ToDo推送至多线程任务队列。
	}
private:
	AsyncTask(QObject *thiz, FunAsyncTask t, FunSuccessCallBack ok, FunErrorCallBack err)
		: callerThiz(thiz), task(t), ok_cb(ok), err_cb(err)
	{
		threadCallId = GetCurrentThreadId();
	}
 
	void run()
	{
		// AnyncThread do the job.
		threadDoTaskId = GetCurrentThreadId();
		try
		{
			result = task();
			//ToDo Save Ok
		}
		catch (...)
		{
			//TODO Save Error;
		}
	}
 
	void handleResult()
	{
		//ToDo MainThread to do the job.
                MYASSERT(callerThiz);
		MYASSERT(threadCallId == GetCurrentThreadId());
		ok_cb(result);
	}
 
	void handleError()
	{
		//ToDo MainThread to do the Error
                MYASSERT(callerThiz);
		MYASSERT(threadCallId == GetCurrentThreadId());
		err_cb(err);
	}
};
 
void assertValidTaskLambda(char* txt)
{
	//ToDo提取lamda表达式的中括号的参数进行检查,不允许使用"=&"的特殊字符,有该字符则输出错误及抛出异常。
        //提取括号外及大括号前的字符串,不允许"mutable"参数使用。
	printf("\r\n%s", txt);
}
 
void assertValidCallBackLambda(char* ok, char* err)
{
        //ToDo提取lamda表达式的中括号的参数进行检查,不允许使用"&"的特殊字符,有该字符则输出错误及抛出异常。
        //提取括号外及大括号前的字符串,不允许"mutable"参数使用。
	printf("\r\n%s-%s", ok, err);
}
 
#define POST_AYNC_TASK(task, ok_cb, err_cb) \
{\
        assertValidQObject(this);  \
	assertValidTaskLambda(#task); \
        assertValidCallBackLambda(#ok_cb, #err_cb) \
	AsyncTask::post_aync_task(this, task, ok_cb, err_cb); \
}
 
int MyClass::execute()
{
	int x = 1;
	int y = 2;
	int z = 3;
	int m = 4;
 
 	FunAsyncTask task = [x, y, z]()->int{
		return QVariant(123);
	};
 
 	FunSuccessCallBack ok = [x, m](QVariant r){
		printf("ok...ok...%d", r);
	};
 
	FunErrorCallBack err = [z, m](QVariant err){
		printf("failed...failed...%d", err);
	}; 
 
	POST_AYNC_TASK(task, ok, err); //这种使用,报错。
 
	// 推荐以下方式使用,目的是语法检查,减少多线程出错。
        // POST_AYNC_TASK((task_exp),(ok_exp),(err_exp))
        // 如果表达式不用括号包裹起来的话,可能会导致编译出错。
	POST_AYNC_TASK(([x, y, z]()->QVariant{
		int v1 = x;
		int v2 = v1*2;
		Sleep(1000);
		return QVariant(v2 + z);
	}), ([=](QVariant r){
		printf("ok...ok...%d", r);
	}), ([=](QVariant err){
		printf("failed...failed...%d", err);
	}));
 
	getchar();
}

cef的Qt的封装库及webrtc的测试

1.webrtc已经在cef3.x中支持。
2.由于cef的编译复杂性,有一些第三方机构专门编译一些全功能的二进制库,并提供了相应的例子,很方便地直接引入到第三方应用中。
3.在window中,简述其编译测试如下:
A-首先下载cef的库文件。下载地址如下:
http://opensource.spotify.com/cefbuilds/index.html【记住要下载32位的版本,不要下载64位的】
下载完成,先阅读其CMakeLists.txt文件,它说明了在各个平台该如何二次编译,如window的编译截图如下:

注:————–一定要用cmake -G “Visual Studio 14″【也即是vs2015,社区版就可以了编译了】的命令,令其生成工程vc的工程文件。———
注:————–不要用cmake的gui方式生成工程,因为可能会失败,而产生困扰——————————-
4.用vs2015打开工程,选择全编译。
5.调试cefclient工程,在调试器中添加–enable-media-stream选项。

6.打开webrtc的测试页面如下:
https://webrtc.github.io/samples/
7.截图如下:经验检,摄像头及声音都正常。


8.

—————————–
有人针对这场景写了一个QT的封装库,可以方便直接被Qt使用,在github随便搜索的结果有如下,可以逐个测试。
https://tishion.github.io/QCefView/
—————————
https://github.com/GreatTux/CefMinGWQt,这个是mingw版本。
———————————–
https://github.com/Dax89/QtCEF
——————-

Android后台运行

在播放音乐或定时器的情况,需要程序在后台运行,则此时可以打开以下开关。

<meta-data android:name=”android.app.background_running” android:value=”true”/>

QML的多语言支持

1.Pro工程文件配置

TRANSLATIONS
+=
muyu.ts

lupdate_only{


SOURCES
+=
\


kxmob/*.qml
\


listmgr/*.qml

}

2.导入语言包

QTranslator
translator;


if(translator.load(“:/muyu.qm”)){


app.installTranslator(&translator);

}

3.
工具->外部->Qt语言家->更新翻译lupdate,lrelease

QML控件风格与应用配置的读与写

QML quickcontrol已经具备设置风格,故需要如下设置(可参考Qt5.6.0\Examples\Qt-5.6\qtquickcontrols2\controls例子)

在QML中导入风格库

import
Qt.labs.controls
1.0

import
Qt.labs.controls.material
1.0

import
Qt.labs.controls.universal
1.0



 

 

 

    

Qt闪屏

Qt的闪屏,使用QtCreator向导创建的Android应用,在应用启动时,首先看到黑色的背景及标题,非常丑,一直想修改它。偶然看到一个大作的应用,非常优雅的实现一个闪屏,完美的解决了原有默认的启动效果,于是学习他制作了一个例子。

例子仓库:https://github.com/kxtry/AndroidSplash

  1. 首先是创建AndroidManifest.xml文件

  2. 修改该文件里的几项如下图:

    文件目录结构如下:

    Apptheme.xml文件内容:

    <?xml version=”1.0″ encoding=”utf-8″?>

    <resources>

    <style name=”AppTheme” parent=”@android:style/Theme.DeviceDefault.Light.NoActionBar”>

    <item name=”android:windowBackground”>@drawable/splash</item>

    </style>

    </resources>

    Splash.xml文件内容如下:

    <?xml version=”1.0″ encoding=”utf-8″?>

    <layer-list xmlns:android=”http://schemas.android.com/apk/res/android”>

    <item>

    <shape android:shape=”rectangle” >

    <solid android:color=”#FFFFFFFF”/>

    </shape>

    </item>

    <item>

    <bitmap android:src=”@drawable/icon” android:gravity=”center” />

    </item>

    </layer-list>

  3. 编译程序,即可。

QTDesigner的QVBoxLayout自动随窗口拉伸

在MainWindow的构造函数中添加如下代码:
//设置Ui
ui.setupUi(this);

//使Ui可自适应父窗口大小
QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->addWidget(ui.verticalLayoutWidget);
setLayout(mainLayout);

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->addWidget(ui->verticalLayoutWidget);
ui->centralWidget->setLayout(mainLayout);
}

KXFW界面库

开源UI库的前因后果。

从2011年后半年就开始写这个UI库了,初衷是为了延续我的第二版UI库。第一版UI库给了酷狗七,该UI库是在负责酷狗七产品开发的过程中仓促完成的,因为项目只有4个月时间开发,然后就要进行产品演示。最后事实也证明赶项目赶出来的架构真的存在太多问题了,而这些问题一直支持着我去开发第二版的UI库。命运之神的按排,让我进入了YY公司,有机缘接触YY的UI库,那时一边学习Qt,一边学习YY的业务开发,曾暗暗自喜:其实我酷狗七的UI库也不算很差嘛。在进行YY的娱乐业务开发的同时,也发现YY的UI架构也有很多问题,而这些问题也被考虑到我的第二版UI库中,当然也会参考它的一些优点。后来因为创业的需要,我离开了YY,那时我的第二版UI库已经完成了,命名为MagicFw库。恰好创业时可以派上用场,可以锤炼我的UI库。我提前与老板商量且承诺:将来这个UI库要开源,要回馈这个互联网,以表达我这么多年只索取没有贡献的愧疚。老板人品很好,也认同我的建议,但要求开源时要”减料”,去除一些关键的模块,且承诺产品赚钱后花30万买下这UI库。就这样创业持续了一年,UI库也修改了好几个版本,日趋完善。

命运之神再次与我开了一个玩笑:创业失败了,团队解散时,老板还欠一个月的工资没给呢。

不久我又上班了,”金山公司”我曾经梦寐以求的公司,而且还是做服务器开发,这是老天爷赐给我的一个学习机会,感恩老天爷的厚爱了。

但我开源计划还没有完成,7月初,我的个人博客域名kxtry.com备案成功了,是阿里云代理备案的,这还要感谢我的一位同事呢,从此网站不用再在海外承受风吹雨打了。

我的UI库也因域名而更名为KXFW界面库,希望有缘者使用得”开心”就好了。

以后我的工作重点会在Linux服务器端,希望将来能再开源一套服务器端的业务架构,计划是基于GO语言。

以下是我的UI描述:

基于Qt的GraphicsView而写的XML-UI界面架构。

1.基本的UI组件,如Label,ComboBox,ProgressBar等常见组件。

2.增加了基于MVC模式的高扩展性的List和Tree控件,已经通过2万多条的记录测试。

3.所有组件都支持XML描述,并依XML控件树结构,生成各种各样的UI界面。

4.可参考kxfw-example的例子开发产品。

 

KXFW仓库:https://github.com/kxtry/kxfw

example仓库:https://github.com/kxtry/kxfw-example

开发环境的安装配置参考:善学记事本,http://www.kxtry.com/?page_id=89

 

一些界面截图:

XML文件描述:

example

 

 

善学记事本

善学记事本

这是一个很普通的树型记事本,是本人编写的第三个记事本程序。

第一个记事本是基于Win32的RichEdit控件,编写到最后困难重重,原因是RichEdit控件对图片和自绘控件受限制很大,很难实现一些高级功能,例如在图片上显示各种各样的按钮或编辑事件。

第二个记事本是基于Win32的自绘控件,实现文档的排版布局控制,包括不同字体不同字号的像素计算,插图的定位运算,段落的重排等,笨重的架构,数不清的已经解决和未解决的BUG,匹夫之力不能持久,最后坚持了大半年,也不了了之。

第三个记事本,也是现在这个记事本, Qt的TextEdit控件本身就已经非常强大,可实现各种各样难以想像的功能,这是深深吸引我的一个原因,此外好像本人天生有一种写”属于自已的记事本情结”。

如今把这个记事本开源,原因也是希望能获得有缘人的认同和鼓励,从而产生持续编写这记事本的动力。

 

本记事本实现的功能如下:

1.树型结构文件节点。

2.每个节点对应一份文件。

3.支持桌面停靠。

4.随系统自启动。

5.托盘菜单

截图如下:

 

开源仓库为: https://github.com/kxtry/sxnote

其依赖的kxfw库的仓库地址:https://github.com/kxtry/kxfw

 

本项目依赖kxfw的框架,其相关目录结构如下
ProjectRoot
..|—>kxfw
..|……|—>kxfw.sln
..|……|—>kxfw.vcproj
..|……|—-…..
..|—>sxnote
………|—>sxnote.sln
………|—>sxnote.vcproj
………|—-…..

编译项目前,请确保是否已经安装:
1.VS2008+VS2008SP1
补丁


http://pan.baidu.com/s/1qWK3UUS

VS2008win7系统或Win8系统上,建议是解压VS2008.iso到非中文路径下的目录内,然后点击autorun进行安装。原因为使用虚拟光驱安装,容易安全失败,本人也是经历了虚拟光驱安装失败后才选择解压方式安装的。

VS2010版,则不要尝试,原因是VS2010对自定义编译命令支持较弱,虽然也能编译成功,但阅读这些自定义编译命令,总是觉得怪怪的,没有VS2008爽,而Qt-vs-addin则依赖自定义编译命令实现IDE的集成编译。


2.qt-win-opensource-4.7.1-vs2008.exe


http://download.qt-project.org/archive/qt/4.7/qt-win-opensource-4.7.1-vs2008.exe

3.qt-vs-addin-1.1.11-opensource.exe


http://download.qt-project.org/official_releases/vsaddin/qt-vs-addin-1.1.11-opensource.exe