Tag Archives: qt

Qt编程最佳实践21项(一)

C. Probst, Oct 2008

来自ICSNetwork视频,Zhuotong Nan(zhn1@pitt.edu) 整理。原视频地址:http://www.ics.com/learning/icsnetwork_webinar/flash/8

最佳实践1,动手写代码前

实现一个任务前,先翻一下例子程序,Qt solutions(Qt提供的一些解决方案库,有商用也有开源的),Trolltech(Qt的开发商,现在被Nokia收购)及其合作伙伴提供的解决方案,以及开源项目等。

可能有一些与你的需求类似的项目已经存在,另外Qt提供的例子程序值得一看,一般例子程序都演示了比较好的实现方式。在使用这些已有代码前,请检查许可条件,比如是不是GPL,还是商用的,要与你的项目保持一致。

最佳实践2,调查Qt提供的其它模块和框架

除了GUI(图形用户界面)编程支持,Qt还提供了支持一些关键技术的独立于平台的其它API,比如多线程、网络、XML、图形、OpenGL、SQL等。

你需要实现的功能已经可能包括在这些模块里,仔细阅读文档,Qt有很好的文档,从中可以得到你关心的信息。

最佳实践3,了解qmake

qmake可以极大简化编译过程。使用qmake -project也可以产生很多项目文件。它可以生成makefile,nMake makefile等。同时也支持生成visual c++, vs .net, MacOS Xcode项目文件。

但同时也需要认识到qmake在操作大而复杂的项目(比如涉及不同的编译器,相互连接)时可能会有一些限制,这时可以试试比如cmake等。

最佳实践4,用new创建QObject并且指定一个父指针

除非你明确你创建的对像的生命周期只限制在这个生成对像的方法中,否则都用new对创建一个从QObject派生出来的对像,并且指定一个父指针。这样不至于代码在离开这个方法时,就销毁了这个对像,而这往往不是你期望的。

指定一个父对像指针,当这个父对像被销毁时,这个对像也自动被销毁。

保证全部的QObject对像都有一个父对像,这样确保全部的QObject对像最终都可以被销毁。

一个例子,

QLabel aLabel(this);
aLabel.setText(“this is really important”);
aLabel.show(); //当离开这些代码在的函数时,这个Label对像就消失了

QLabel* aLabel =new QLabel(this);
aLabel->setText(“this is really important”);
aLabel->show(); //这个标签对像只有当父对像(this)被销毁时,才会被销毁

最佳实践5,不要多重继承QObject

不要从QObject或其子类上多重继承,Qt不支持这种方式。

最佳实践6,了解QDialog::exec()和QWidget::show()的区别

刚学习Qt时可能会混淆这两者,两者有类似的作用,但也有显著的区别。QWidget::show()将widget(QDialog是QWidget的子类)和它的子对像显示出来;QDialog::exec()是一种有模显示方式,也是将其和子类显示出来,但这时用户除非关闭这个对话框,不能与其它窗体交互。

QWidget类是用户界面类的子类;QDialog也是从QWidget上派生出来的,用于获取用户输入的数据。

最佳实践7,在写定制的图形控件时,确保没有现成的已经存在

Qt里的全部GUI对像,事实上都是定制的控件,与用户自己写的没啥区别。Qt已经提供了很多有用的控件,比如QCalendar、QTooltip、QTabWidgets、QDateEdit、QTimeEdit等。如果已经有现成的,尽量用它们,毕竟它们经过了完整的测试。

写一个定制的控件时,需要重实现QPaintEvent,以及使用QPainter类。

当然,如果你需要的控件是独一无比,除了自已写就别无选择了。不过需要注意写控件是不容易的,需要小心的设计和大量的努力。

(待续)

一个多准则决策的图形程序

我们最近实现了一个多准则决策(Multi-Criteria Approach Decision Making)的一些简单算法,Qt 4实现,代码可以全部主流平台上编译。更多算法以插件的形式添加进来。

image
value function (analysis matrix -> evaluation matrix)

image
indicators简单加权实现及solution ranking

Qt 4.4 + msvc2005 下安装Eric 4, a python IDE

下载了Qt 4.4.0开源,指定msvc2005 spec,编译了大概2小时完成。
*一定要shared DLL
*一定要开源版,如果是商业的Qt 4与开源的PyQt等协议有冲突

下载python 2.5.2 msi安装。下载SIP v4.7.6,根据readme.txt安装,指定-p win32-msvc2005。下载QScintilla-gpl-2.2.zip,根据readme.txt安装,安装for Qt4。

下载PyQt v4.4.2,运行c:python25python configure.py时,提示fromAscii_helper@QString@@CAPAUData@1@PBH@Z could not be loacated in the dynamic link library QtCore4.dll,原因是在path环境变量里,在c:qt-4.4.0bin前还有个路径C:Program FilesMATLABR2007bbin有老版本的QtCore4.dll。将c:qt-4.4.0bin移到MATLAB前解决此问题。

安装QScintilla2 for Python binding(在源文件Python下),见dochtml-Qt4index.html。此步骤须在安装PyQt后,否则提示找不到PyQt v4。

将qscintilla2.dll从%QTDIR%lib拷贝到%QTDIR%bin目录下。

下载eric4-4.1.5,c:python25python install.py,安装之。

涉及到较多的开源包,一般安装步骤都是:

c:python25python configure.py
nmake
nmake install

注:

QScintilla-gpl-2.2的python binding生成的Makefile好像有问题,产生link error,可能原因是没有定义-DQSCINTILLA_DLL。可以打开configure后产生的Makefile,在CPPFLAGS里增加此定义。

可以下载QScintilla-gpl-2.2.1-snapshot-20080610,此问题已经更正。

好一阵折腾呀!

Qt integration for Eclipse

Trolltech finally organized technicals to develop integration with Eclipse, the popular C++ development environment in open source community. A version of 1.0 RC2 has come out and can be found from Trolltech offical FTP server at ftp.trolltech.com. I tried this integration tool to develop a small console tool. It features some interesting things. But it is not very stable yet. Hope 1.0 release version will be more stable and more user friendly.

Qt for VS c++ 2005 EE

Qt 4.3.2 已经支持 Visual Studio C++ 2005 Express Edition了,但不提供Integration,要使用的话,大概使用makefile project再加一点定制,比如使用qmake .pro来生成makefile,通过一些配置,Qt就可以使用VS这个稳定和强大的平台了(比如Intellisense, Debug等都比其它如Eclipse出色,毕竟是商业的)

To install it, download Qt 4.3.2 open source from its ftp at ftp.trolltech.com, configure it using a -platform win32-msvc2005, then compile/link by running nmake.

One thing to be noted is we have to install Windows Core SDK, IE SDK (If no IE SDK, prompting by missing shlwapi.h), and optionally MDAC SDK if you are going to install ODBC, prior to configure Qt. VC++ 2005 Express Edition does not come with SDK. We should install SDK seperately. One way is to install this package by appropriate customing.  

After installation, configure vcvar32.bat under "C:Program FilesMicrosoft Visual Studio 8Common7Tools" by adding "C:Program FilesMicrosoft Platform SDK for Windows Server 2003 R2Bin", "C:Program FilesMicrosoft Platform SDK for Windows Server 2003 R2Include",  and  "C:Program FilesMicrosoft Platform SDK for Windows Server 2003 R2Lib" to #path, #include and #lib respectively. Otherwise the compilation will complain it cannot find necessary header files.

完成了gimms-clip

作为了一个Qt的训练,主要是完成一个GIMMS数据集(ftp://ftp.glcf.umiacs.umd.edu/glcf/GIMMS/)的空间裁剪功能,特色在于:
  • Qt实现跨平台,国际化等功能
  • 调用GDAL完成多种GIS格式的转换
  • 可变线程来处理整个裁剪流程

完成了v1.0,可能暂时到止,以后有兴趣了,可以在此基础上再增加一些小功能,比如引进xml,将用户的配置记住等等(当然可以用QSettings,但锻炼一下学生的xml也是不错的)

放一个截图吧,已经本地化

 

——

前面有朋友问为什么在windows下不用mfc,我最早应该是mfc出身的,但接触的科研项目大多对操作平台有要求,国外很多学者仍是用linux/unix环境来进行科学研究,于是开始寻找一种可以跨平台的而且对于我来讲比较易学的工具(c/c++/c#背景),Qt当然是个不错的选择,只是Qt/win稍贵了一些

[原创]QTextCodec::codecForName()的问题

问题:
如下代码片断,
int main(…)
{
QTextCodec* gbkCodec=QTextCodec::codecForName("GBK");
Q_CHECK_PTR(gbkCodec);
 
QCoreApplication a(…);
 
 
return a.exec();
 
}
 
gbkCodec返回null。换成 除cn, jp, ko之外的编码,如 windows-1258,可以成功返回 codec! 如果不用codecForName,换成codecForLocale(),也将返回指向 System的codec,没有问题。检查codec plugins,确认有 qcncodecs.dll。
 
解决方案:
将 codecForName()一句移到 QCoreApplication a(…)一句之后。
 
原因不详。发现是内置的codec 这样是可以返回的,但plugin codec不能放在这个位置。
 
Environment: Qt 4.1.1

一个Qt Excel的文档翻译

使用Qt调用Excel

Eugene Eremin

翻译:tong # cngis.org

原文Urlhttp://www.qtlib.ru/index.php?option=com_content&task=view&id=42&Itemid=28

 

Qt 3.1及以上版本的一个新特性是为Windows操作系统提供了ActiveX支持。开发者如果关心如何使用Qt操作COM组件,比如在Excel里插入新数据,这个新增功能就很重要了。

然而不幸的是,在Internet上没有太多这方面的主题可以借鉴。我在这里演示一个例子,可能会对大家有所帮助。

首先我们来看一下Qt自带的例子。通常Qt自带的例子可以告诉大家一些常用的知识点。我不记得在哪里看过,说一个好的文档应当是用户看过后不再存在不解的地方。但Qt只提供了一个与MS Outlook Express交互的例子。不过这就是我开始Excel交互研究的起点了。

ActiveXCOM的区别不是很大,我不是这方面的专家,但我在这里推荐大家看一本Adam Denninga的书“ActiveX for professionals”。这本书会帮助大家很好地理解这些概念。第一步,我们来引入Excel,并创建一个对象。

#include <qaxobject.h>

QAxObject* excel = new QAxObject( "Excel.Application", this ); //获取一个Excel对象

excel->dynamicCall( "SetVisible(bool)", TRUE ); //设置为可见

这里我们通过代码构建了一个对象,并通过对象打开了Excel。第二步,我们计划插入新数据。为了做到这一步,必须了解一点Excel文档的结构。Excel应用程序包括一系列的workbooks,每个workbook又由多个sheets组成。Microsoft公司并没有给出太多这方面的结构信息,我在Google上寻找了不短的时间,也没有太多的结果。

QAxObject *workbooks = excel->querySubObject( "Workbooks" ); //得到Workbooks集合的指针

QAxObject *workbook = workbooks->querySubObject( "Open(const QString&)", "C:dataA.xls" ); //打开硬盘上的一个Excel文档

QAxObject *sheets = workbook->querySubObject( "Sheets" ); //得到Sheets对象的指针

QAxObject *StatSheet = sheets->querySubObject( "Item(const QVariant&)", QVariant("stat") );     //得到名为stat的一个sheet的指针

StatSheet->dynamicCall( "Select()" ); //选择名为statsheet使之可见 

QAxObject *range = StatSheet->querySubObject( "Range(const QVariant&)", QVariant( Qstring("A1:A1")));  //选择A1:A1这个range对象

range->dynamicCall( "Clear()" ); // 清除range对象

range->dynamicCall( "SetValue(const QVariant&)", QVariant(5) ); //将该range对象的值设为5

接下去用户可以保存和关闭这个Excel文档了。

最后说一句,这些对象的接口可以通过generateDocumentation () 产生。比如,我们可以这样做:

QFile outfile("excel.html");

QTextStream out( &outfile );

outfile.open( IO_WriteOnly | IO_Translate );

QString docu = excel->generateDocumentation();

out << docu;

outfile.close();

这些信息被保存在名为“excel.html”的文件里。如果插入的数据很大,会花费很多的时间。MFC使用了专门的class,但我没能在Qt里实现这个class。如果有意见,请反馈至http://prog.org.ru/forum/ptopic_141.html

译者注:本文由在线语言工具从俄语翻译至英语,然后人工翻译成中文,因此中文与俄文可能有一些出入,欢迎指正。

Qt 4里已经有很多的有关ActiveQt的文档,大家应当以那个为主要的学习的材料。

 

上周五早讨论时遇到的几个问题

1. olb?

*.olb可被认为是*.tlb的前身,它也是表述com对象的信息,现在已经被定义更完整的
*.tlb代替掉了,使用*.olb的ocs/activeX一般是较为早期的产品。

2. axWidgetTOC->dynamicCall("SetBuddyControl(IDispatch*)",
(axWidgetPageLayout->querySubObject("Object"))->asVariant());

Object是PageLayout的一个属性。querySubObject输入方法名或属性名。
HRESULT IPageLayoutControl2::get_Object(
IDispatch** ppDispatch
);

3. catalog open file dialog

GxDialog在ArcEngine里不能用。这里有个帖子讨论这个问题:
http://forums.esri.com/Thread.asp?c=159&f=1705&t=163159&mc=5
这里有个例子,也可以参考
http://edndoc.esri.com/arcobjects/9.0/default.asp?URL=/arcobjects/9.0/Sample
s/Geodatabase/Accessing_Data/Browse_for_data_using_name_objects/Browse_for_d
ata_using_name_objects.htm

4. Q_Declare_private / d_func()
目的是为了在类里隐藏界面冗长的代码,将界面代码放置到专设的 QxxxPrivate类里
去。相关的定义如下:
#define Q_DECLARE_PRIVATE(Class)
inline Class##Private* d_func() { return reinterpret_cast<Class##Private
*>(d_ptr); }
inline const Class##Private* d_func() const { return
reinterpret_cast<const Class##Private *>(d_ptr); }
friend class Class##Private;

#define Q_DECLARE_PUBLIC(Class)
inline Class* q_func() { return static_cast<Class *>(q_ptr); }
inline const Class* q_func() const { return static_cast<const Class
*>(q_ptr); }
friend class Class;

#define Q_D(Class) Class##Private * const d = d_func()
#define Q_Q(Class) Class * const q = q_func()

在使用时,
//////////////////////
class QDialogPrivate;

class Q_GUI_EXPORT QDialog : public QWidget
{
Q_OBJECT
Q_DECLARE_PRIVATE(QDialog)
///////////////////////
class QDialogPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QDialog)
public:
///////////////////////
d_ptr是在QObject里定义的,protected,为指向 QObjectData的指针
p_ptr是在QObjectData里定义,public,指向QObject的指针
在使用时,定义Q_D(class)和Q_Q(Class),直接使用 d和q两个指针

QHttp post的一个问题

有一些网站必需要求 cookies,这些在使用QHttp request前,必须在
QHttpRequestHeader里设置 正确的cookies,否则可能不正常工作,in the
citationSearch case,会提示被禁止访问。具体作法可参考 citationSearch源代码。

1. 可以在程序里 实例化多个 QHttp

2. 最好用 requestFinished(int, bool)来截获请求的完成情况,而不是done(bool);在进行abort()或delete QHttp时,都要emit done

3. …