Daily Archives: August 23, 2005

Qt 4.0.1 signal的模板参数问题

描述如下:singal带2个参数,第一个是模板类型的参数,第二个是一个类,在4.01下
面编译通不过,即便第二个参数是int这样的简单类型,也不行。但如果只有一个参数
(即模板参数),可以正常通过。Qt 4.0.0没有这个问题。
解决方案:通过typedef将模板参数定义成一个别名。编译通过。

Qt里的属性(property)

Qt里的属性(property)
giscn[at]msn[dot]com


1.属性有什么用?
由于c++类具备封装特性,不推荐对类成员变量(class
variables)进行直接存取。现代编译器引用属性(property)的概念,对成员变量进行安全的存取。比如在win平台下
vc7有类似于__property或[property]的支持。Qt由于要实现其跨平台(cross
platform),引入一套独特的属性系统。其底层是由meta compiling进行支持。

2.格式
    Q_PROPERTY(type name
               READ getFunction
               [WRITE setFunction]
               [RESET resetFunction]
               [DESIGNABLE bool]
               [SCRIPTABLE bool]
               [STORED bool])

  • Q_PROPERTY: qt里定义的宏;
  • type name: 即类型名+属性名,属性名(name)在QObject的setProperty里被引用;
  • READ: 设置读取成员变量的函数名,一定要是const,可以返回void,Qvariant支持的对象,指针,或const的引用。READ是必须的,而write, reset等则是可选的;只有READ的属性为只读属性;
  • WRITE: 写成员变量的函数名,返回值必须是void,可以设置一个参数,这个参数可以是void,QVaraint支持的变量,指针,或const的引用。可选;具备READ和WRITe的属性是可读写属性。
  • DESIGNABLE: 指示该属性是否被图形编辑器(比如designer)使用。默认是TRUE;
  • SCRIPTABLE: 指示是否在script里使用,Trolltech公司同时有基于Qt的QSA,用于在应用程序的脚本编程;默认是TRUE;
  • STORED: 指示是否可被持久化(persistence)。只有WRITE被设定的时候,STORED才有效。默认是TRUE。

3. 使用
比有一个类,

class MyClass : public QObject
{
Q_OBJECT

public:
  MyClass (QString f) {this->f =f;}
  ~MyClass() {}

//property begin
  QString getF() const {return f;}
  void setF(QString ff) {f=ff;} 
//property end

private:
  QString f;
};

这时在public之前定义property
Q_PROPERTY (QString F READ getF WRITE setF)

照惯例,读取函数往往省略get,即定义了
QString F() const {return f;}
这时,Q_PROPERTY (QString F READ F WRITE setF)
但实际上,读取、写、和重置(reset)函数可以是任何名字,比如前面用getF。

在使用时,属性跟一般的成员函数一样被使用,比如:
MyClass classA("initial");
QString out=classA.getF();
//out = "initial"
QString t="this is a test";
classA.setF(t);
//classA里的f现在是"this is a test"

此外,可以通过QObject::setProperty()和property()来使用属性,比如
MyClass classB("classB");
//这时的f是"classB"
classB.setProperty("F", "this is a test");
//这时调用setF("this is a test"),成员变量f现在是"this is a test"

使用setProperty可能效率比直接调用setF低,但注意到setProperty是基类的成员,所以通过QObject::property/setProperty可以遍历全部派生自QOjbect的类的属性。比如:
QObject* p = &classA;
p->setProperty("F", "test A");
p=&classB;
p->setProperty("F", "test B");
熟悉多态的朋友,马上就应该联想到这种机制的一些优越性。其中奥秘请看多类的相关描述,这里主要讲Qt的属性,不赘。

QObject::property/setProperty跟QMetaObject::propertyCount(),和QMetaObject::property()结合起来,可以实现动态的函数调用,类似于dotnet里的reflection机制。

4. 如果property的参数是enum,那么在定义Q_PROPERTY时,必须先告诉meta system使用的enum,使用宏Q_ENUMS,次序无关,如:

Q_PROPERTY(Priority priority READ priority WRITE setPriority)
Q_ENUMS(Priority)

其中Priority是枚举类型。

5.一个较为复杂的例子,使用了一个引用输入属性的写函数。请注意,此引用必须为const。

////CaliforniaWhiteWine.h
#include <QObject>

class WhiteWine
{};

class CaliforniaWhiteWine :
    public QObject
{
    Q_OBJECT
    Q_PROPERTY(WhiteWine& m_wine READ getWine WRITE setWine)
public:
    CaliforniaWhiteWine();
    CaliforniaWhiteWine(WhiteWine& wine);
    ~CaliforniaWhiteWine();

    WhiteWine& getWine() const;
    void setWine(const WhiteWine& wine)
    {
        delete m_wine;
        *m_wine = wine;
    }
protected:
    WhiteWine* m_wine;
};

////CaliforniaWhiteWine.cpp
#include ".californiawhitewine.h"

CaliforniaWhiteWine::CaliforniaWhiteWine(void)
{
    this->m_wine=new WhiteWine();
}

CaliforniaWhiteWine::~CaliforniaWhiteWine(void)
{
    delete m_wine;
}

CaliforniaWhiteWine::CaliforniaWhiteWine(WhiteWine& wine)
{
   
}

WhiteWine& CaliforniaWhiteWine::getWine() const
{
    return *m_wine;
}

qtcn.org

才发现一个新的中文Qt讨论站(www.qtcn.org)。站长有志于将Qt
4的文档翻译成中文。很好很有意义的工作,但工作量怕不小,是个漫长的过程。但Trolltech作为一个商业公司,如果她感觉有必要做成中文文档来吸引
中国的开发者的话,估计他们自己会做这事情,开源社区却不宜花太多时间在文档的翻译工作上面。只是国内的Qt coder不多,而且水平基本偏低。
也许多写一些中文的入门引导性的文章(即便是英文的,同样有意义),在目前来看,我感觉居于比较重要的位置。
技术论坛还是要写位在技术讨论上,不管是qtcn还是cngis。只是坚持下去不是件容易的事。
最近在study win32  api class -> Qt
class的转化,TT编程人员真是做了件了不起的工作。比如meta
compiling和Qt的wrapping都是值得写c++代码的人借鉴的技术。看到wxWidget讲,Qt的这种meta
compile导致Qt不是一种真正的纯c++。并不十分赞同。在meta
compile底层讲,预编译的效果是纯cpp,从较上层讲,能最大限度简化编程人员的工作量就是成功。
不过象wxWidget这样使用消息映射宏,也是不错的一种选择。估计是借鉴了mfc。没有太深钻研wxw,以后有时间再看。