Qt与VS2005/2008的完美配合
介绍
用过Linux的人想必都知道Qt(不是QuickTime,呵呵)这个名称,KDE就是用Qt写的,我也是接触Linux后才认识它的。
Qt原先是奇趣科技TM(Trolltech)的产品,由Haavard Nord(Trolltech的CEO)和Eirik Chambe-Eng(Trolltech的董事长)于1991年开始它的历史,三年后他们创建了Quasar Technologies公司,后改名为Trolltech,其发展与KDE的发展紧密关联,可以说早期时每个KDE版本的发布都是Qt的一个里程碑事件。之所以叫Qt,据说是因为字母“Q”在Haavard的Emacs所用的字体中很PP -_-!,而字母“t”是toolkit的意思。
Haavard和Eirik要开发Qt的起因是当时他们正在做一个项目(1991),必需在Unix、Macintosh和Windows环境下运行。那个夏季的一天,Haavard和Eirik出去散步,当他们坐在一个公园长凳上时,Haavard说,“我们需要一个面向对象的显示系统。”。这次讨论的结果为他们即将创建的跨平台GUI框架埋下了伏笔。
1991年,在设计上与Eirik合作,Haavard开始写了一些类,它们后来成为Qt。在这年的接下来时间里,Eirik提出了“signals and slots”的想法,这也是Qt的一个重要特征。在这年末,在Haavard的提议下,两人一起下网开发“世界上最好的C++ GUI 框架”。
1994对这两个年轻的程序员来说是不幸的,没有一个客户,手头还是一个未完成的项目,没有钱。幸运的是,他们的妻子都有工作,可以支持他们(感动啊!!)。之后感谢与Haavard的一个大学时候的教授的联系,一家公司给了他们用Qt开发运行在Unix和Windows上的软件的机会。终于在1995年5月20号,Qt 0.90发布了,这是Qt的第一个公开发行版。
之后还有很多故事,如Qct KDE组织的成立,KDE和Gnome的PK,Qt协议的变更,及Qt的几个重要发行版,Nokia收购Qt,Qt支持LGPL协议等,就不介绍了。已经有点跑题了,介绍就到这…
为什么用Qt
如果就写跨平台的程序,Qt是一个很好的选择,当然还有很好其它的GUI库,如wxWidgets、gtk等。我选择Qt主要是因为程序简单,可拓展性强,代码思路清晰,文档强悍!一般写GUI,如果用到新的class都是再查文档、看例程的,而这点用起来比MFC方便、灵活。用MFC写程序不舒服的地方时,很好时候代码是用向导生成的,MSDN中对于GUI的class的例程不够多。例程充足,这样代码完全可以自己写,这样条理就清楚了。
安装与编译
1. Commercial Edition
如果你用的是商业版本,那只要选择好对应开发平台的就可以了,如vs2005sp1的,安装下就可以了,连带Visual Studio Addon,连编译都省了。
2. Open-Source Edition
官方有提供MinGW下的安装版本,可以选择连带的Qt Creator。这个IDE比较赞的,支持一些简单的自动代码补全,可以方便的查看Doc。还提供了git、svn等版本控制工具的集成支持,当然还有Qt Designer、Qt Linguist的集成。
如果用在VS2005/2008中使用,就只是自己动手编译了。编译过程很简单,下面假设IDE是VS2005,操作如下:
简单编译
- a. 下载Qt原代码包,如qt_4.5.1_opensource.zip,解压到一个剩余空间大于3.5G的分区。
- b. 设置系统环境变量:
QTDIR —— 刚刚解压的Qt根目录,
添加%QTDIR%\bin到Path,
QMAKESPEC —— win32-msvc2005
- c. 打开VS的Command Prompt,输入:
>configure>nmake
编译大约要2-4小时,编译结果占3.5G左右。
自定义编译
从上面的c步骤开始:
- c. 打开VS的Command Prompt,输入:
>configure --help
查看configure的可以使用的选项,我自己可能会用的:
-release 编译release版本
-debug 编译debug版本
-debug-and-release 两个版本都编译
-shared 编译dll版本
-static 编译静态链接库版本
-fast configure时只生成目录级的Makefile
-no-qt3support 不支持Qt3
-qt-libjpeg 用Qt的jpeg解码,用system-jpeg时,软件发布到其它电脑上时jpg解码出问题了
-vcproj 生成vs2005的vcproj工程文件,方便以后,一般不用,占地方
-phonon 视频播放支持,需要DirectShow(DShow)
-direct3d direct3d支持,需要D3D SDK
注意:
用-phonon和-direct3d选项时,需要在之前设置环境变量,参与Qt的Readme。
DShow安装比较麻烦,因为MS已经停止DShow的支持了,取而代之的是Media Foundation,在Vista和Win7中开始应用。DShow的最后版本环境是D3D2005 SDK和Direct Show包,好像还要Windows SDK 2003云云,配置过,记不清楚了。
- d. 修改Qt如果不想编译的部分
如不想编译examples目录下的文件,打开$(QTDIR)\examples\Makefile,修改为(添加skip-all和skip-qmake两行)
all:
skip-all:
D:\Qt\4.5.2-vs2008sp1\bin\qmake D:/Qt/4.5.2-vs2008sp1/examples\examples.pro -o Makefile -spec win32-msvc2008
nmake -f Makefile
first: all
qmake:
skip-qmake:
D:\Qt\4.5.2-vs2008sp1\bin\qmake D:/Qt/4.5.2-vs2008sp1/examples\examples.pro -o Makefile -spec win32-msvc2008
这样编译都这里时就直接跳过了,注意设置时要慎重,一些目录下的代码可能是编译基本库文件所需要的,特别是src目录下的。如果你不想生成qdemo.exe可以相仿地修改$(QTDIR)\demos\Makefile文件。
- e. 编译后的清理
如果你打算以后动不再修改编译选项的话,又对Qt临时文件占地方不舒服的话,可以清理一些临时文件,最终可以减小到800M左右。
- 清理bin下除.pdb和.dll外的临时文件,注意临时文件指的是编译生成的文件,如.obj、.ilk之类的文件
- 清理lib下除.prl和.lib外的临时文件,*.prl不知道有什么用,反正小,就留着吧。
- 清理src下除vc[n].pdb外的临时文件,如vs2005是vc80.pdb而vs2008是vc90.pdb。
- tools、plugin和qmake目录类似
配置VS2005
1. Qt Visual Studio Add-in
Qt官方下载: http://qt.nokia.com/downloads/visual-studio-add-in
主要提供VS2005/2008的集成,如调用Designer、Linguist和一些帮助,还有修改Debug信息显示方式,使Debug时数据显示更直观。
2. 好像没有了。。。
使用Qt写程序
1. 唯美主义 - 不使用Designer
我个人常用的方法,这样怎么开始Qt工程呢?
新建个目录,如hi_qt,再新建个文件main.cpp,生成工程文件hi_qt.pro
qmake -project
生成VS工程文件hi_qt.vcproj:
qmake -tp vc
打开hi_qt.vcproj,菜单Qt- Convert project to Qt Add-in project,这样就可以用Qt VS Add-in的功能新建Qt class了。
2. 一般方法
就是直接用Qt VS Add-in 的导向了,不爽的是一定要生成ui文件和qrc文件,当然你也可以事后删除它们,这个就不多说了。
3. 让Designer做大部分工作
主要是结合Qt VS Add-in和Designer完成大部分界面工作,如在界面中插入自己定义的Widget,写Style Sheet等。这个说起来比较复杂,不多说了,一般用得不多,以后有时间再慢慢整理。
参考
- C++ GUI Programming with Qt 4, 2006, A Brief History of Qt
- Qt Assistant 4.5.2 Qt Home 1.
static_cast、dynamic_cast、reinterpret_cast、和const_cast
最近温习的一些C++基础知识,记性不好,看了忘,忘了看,来个简要小记好了。
static_cast *
dynamic_cast *
reinpreter_cast *
const_cast *
参考 *
这是标准C++中的四个类型转换符,是C风格的强制类型转换的推荐替代物,如(T) expression 或 T (expression)。
static_cast
用法 :static_cast type-id ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的(这也是引出dynamic_cast * 的原因)。
- 用于基本数据类型之间的转换,如把int转换成double,把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
- 把空指针转换成目标类型的空指针。
- 把任何类型的表达式转换成void类型。 把non-const转换成const,相反的操作由const_cast * 完成。 注意 : static_cast 不能转换掉expression的const、volitale、或者__unaligned属性。
例子 :
class CBaseX
{
int x;
}
class CBaseY
{
int y;
int* py;
}
class CDerived : public CBaseX, public CBaseY
{
}
CDerived的内存布局(Memory Layout)
如图所示,CDerived的内存布局包括两个对象,CBaseX 和 CBaseY,编译器也知道这一点。因此:
当你将CDerived 用static_cast* 转换到 CBaseY时,它给指针添加4个字节,同时当你将CBaseY用static_cast * 转换到CDerived时,它给指针减去4。 *然而,甚至它即便不是一个CDerived你也可以这样做,此时static_cast * 将是不安全的。当然,这个问题只在如果你做了多继承时发生。 在你将CDerived转换 到 CBaseX时static_cast 和reinterpret_cast * 是没有区别的。 因为基类不是“虚”类,所以不能使用dynamic_cast * ;如果是“虚”类,则情况与 static_cast 同,且下行转换时有安全检查,转换失败返回NULL。
dynamic_cast
用法 * gt( expression )该运算符把expression转换成type-id类型的对象。type-id必须是类的指针、类的引用或者void *;
- 如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。
- 通过RTTI来判断类型转换的合法性,需要类成为多态,即包括“虚”函数,因此不能用于转换void*。
- 主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换(不相关的类相互转换,试验过,直接返回NULL)。
- 由于要动态判别,实现相当慢,尽量避免使用。
在类层次间进行上行转换时, dynamic_cast 和 static_cast 的效果是一样的;在进行下行转换时, dynamic_cast 具有类型检查的功能,比 static_cast 更安全。深入讨论RTTI,请参见 [4]
reinpreter_cast
用法
type-id 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。 该运算符的用法比较多。
const_cast
用法
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。 常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。
参考
gtis actually doing 1.
gt揭密 1.
C++箴言:将强制转型减到最少 1.
如何在运行时确定对象类型(RTTI) 1.
Ogre::ParticleSystem的Abstract Factory模式
最近在看Ogre的粒子系统的绘制方式,这里小记下。
从上面的类图可以看出,Ogre::ParticleSystem是一个MovableObject,也就是说Ogre把它看成就一个可移动的场景物体。所以不可以直接创建,而是应该通过SceneManager来创建,并且只有attached到SceneNode后,才会显示。
为了便于ScenManager统一管理各种MovableObject,所有MovableObject使用了 Abstract Factory 模式,并且每个子类的Factory要在Ogre::Root的mMovableObjectFactoryMap中注册,而mMovableObjectCollectionMap中存放的是各种MovableObject类的实例集合。下面就粒子系统的创建函数,常规的Abstract Factory
ParticleSystem* SceneManager::createParticleSystem(const String&name,
const String&templateName)
{
NameValuePairList params;
params["templateName"] = templateName;
return static_cast<ParticleSystem*>(
createMovableObject(name, ParticleSystemFactory::FACTORY_TYPE_NAME,¶ms));
}
MovableObject* SceneManager::createMovableObject(const String&name,
const String&typeName, const NameValuePairList* params)
{
// Nasty hack to make generalised Camera functions work without breaking add-on SMs
if (typeName =="Camera")
{
return createCamera(name);
}
MovableObjectFactory* factory =
Root::getSingleton().getMovableObjectFactory(typeName);
// Check for duplicate names
MovableObjectCollection* objectMap = getMovableObjectCollection(typeName);
{
OGRE_LOCK_MUTEX(objectMap->mutex)
if (objectMap->map.find(name) != objectMap->map.end())
{
OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,"An object of type '"+ typeName +"' with name '"+ name
+"' already exists.","SceneManager::createMovableObject");
}
MovableObject* newObj = factory->createInstance(name, this, params);
objectMap->map[name] = newObj;
return newObj;
}
}
Setup Ruby on Rails quickly on Windows XP
最近无聊,又开始看网站制作相关的东西了,有点急性子,然后盯上了Ruby On Rails(据说与Java相比更适合个人开发)。我分别在Arch和XP上安装配置了环境,都很简单。前者直接通过源的包,后者下几个安装包。下面简单记录下xp下的安装过程和几个小问题。
所需安装包
下载点: http://rubyonrails.org/download
下载包:Ruby,RubyGems(Optional),Rails(Optional)
也就是只要下个Ruby Windows installer就可以了,其中包含了Gems,而Rails可以通过Gem来在线安装。
安装步骤
- 安装Ruby
- 命令行下 #gem update
- #gem rails
注意
- 如果网络不好,想安装rails-...gem,可以用命令 #gem ins rails-...gem –local 不过这样gem(也就是包管理器)就不会帮你安装rails的依赖包了,你得自己手动安装activerecord、actionpack、activesupport…等几个包了。
- gt,也可以直接加到环境变量中(我的电脑-》属性)
小问题
用命令 #rake db:migrate 建立表时,出现mysql错误提示
Mysql::Error: query: not connected: SELECT version FROM schema_migrations
原因可以看 这里 ,也就是说新版本的mysql的一些相关接口变化了,ruby的mysql接口还没跟上,解决方法就是下个旧版本的 libmySQL.dll 到 ruby_dir \bin目录下,也就是保持了mysql旧的调用接口。我的测试环境是:mysql 5.1.39-community, ruby 1.8.6, rake 0.8.7
Orge Intermediat Tutorial 1
问题
在实现 Orge Intermediat Tutorial 1 附加的 Difficult Questions 时,发现启动 die animation state后
// set Die animation
mAnimationState = mEntity->getAnimationState("Die");
mAnimationState->setLoop(false);
mAnimationState->setEnabled(true);
// Set walking animation
mAnimationState = mEntity->getAnimationState("Walk");
mAnimationState->setLoop(true);
mAnimationState->setEnabled(true);
再恢复为”Walk“ animation state后,robot虽然是在”Walk“但依然就倾斜的。
发现
跟踪程序发现mNode(Robot attatched)的mOrientation在Y轴上并没有变化,猜想应该是在mEntity(Robot)中改变的,但Debug中并没有发现变化。继续Debug,发现从 Walk state到 Die state再到 Walk state后, Die state的状态依然是启动的,而不会因为启动了”Walk state而停止。这可能就是问题所在吧。
解决
再切换到 Walk state之前,关闭 Die state。
// Set walking animation
mAnimationState->setEnabled(false);
mAnimationState = mEntity->getAnimationState("Walk");
mAnimationState->setLoop(true);
mAnimationState->setEnabled(true);
PS: 居然问题解决了,但如果是前后连续的启动这两个state, Die state并不会影响到 Walk state。这个问题以后有空再到源码中找吧。
vs2008 always rebuilds the whole project
问题
每次 build project 都有重新编译整个工程(Ogre project),也就是不能 minimal rebuild(/Gm) 了,折腾了昨天一个晚上,郁。。。
提示
Why is Visual Studio 2008 always rebuilding my whole project?
分析与解决
想到安装好 Win7 后调整了下系统时间,所以用 total commander 调整了整个 Orge SDK 的时间。
Win7下添加网络打印机
问题:
通过Win7的打印机添加向导添加打印机时,会自己停止Print Spooler系统服务,导致添加失败,屡次尝试不成功。
提示:
Windows 7 beta – Print spooler app not working
解决方法:
暂时关闭系统防火墙,启动Print Spooler服务,按向导提示添加打印机。
使firefox的组件FEBE使用boxcn.net
原本FEBE插件使用的可选存储空间是box.net,可使主页一直打不开, 原来box.net已经被封了 。但它的新域名boxcn.net可以访问,于是就想hack下FEBE插件,如果运气好说不定可以噢: )。
-
首先进入FEBE插件安装目录:%APPDATA%\Mozilla\Firefox\Profiles[user]\extensions{4BBDD651-70CF-4821-84F8-2B918CF89CA3}
-
( )用winrar或7z解压出chrome\febe.jar中的content\boxnet.js,替换所有的 box.net 为“boxcn.net”
-
把boxnet.js重新压缩到febe.jar,OK了~ quot ===============================================
插件主页:http://customsoftwareconsult.com/extensions/febe/febe.html
简介:FEBE