如何开发一个Qt工具箱内的控件

      Qt是一款不错的IDE相信不少公司在用,那么想来肯定很多人会希望开发一些自定义控件并添加到Qt的工具箱里吧?

      那么今天,就以我们实际的开发实例为基础来简单介绍一下这个工具箱控件开发中一些被教材或网络文档忽略的细节。开发一款工具箱控件,在Qt5(或Qt4)里是很方便的,这便利主要来自Qt程序的开发人员预先布置,当然要感谢这些人无私的奉献(当然,Qt也是有收费版的,但很多时间里Qt一直是一款免费IDE)。

      说道具体步骤,毫无疑问首先是创建Qt控件代码的工程。选择新建文件或项目时,在列表里选择 “其他项目” -> ”设计师自定义项目“,跟着向导一步一步走即可。我们这里的项目名称是QGeoImage,这是一个地球物理成像相关控件,保存的路径是(svncc/QGeoImage)。如果没有特别的需求可以不用大改自动生成的代码:不过需要注意 icon和name两个虚方法在新的继承类中,势必需要修改,因为一个决定了控件的名称,另一个决定了控件在工具箱内的图标。

      经过简单的修改,项目就已经能够编译了,为了能够被Qt或者Qt Creator调用到,显示在工具箱里,我们要将编译出的release版.so文件(我之前没说我们是在linux环境下么?)

 将它copy到Qt安装目录的plugin/designer/里。注意一点是很多其他博文会给出一个更详细的路径例如 Qt 4.2.0/plugins/designer等。但实际情况略复杂不是所有版本Qt都是这样的路径比如我这里就是Qt5.1.1/5.1.1/gcc_64/plugins/designer/(这个影响Qt Designer)以及 Qt5.1.1/Tools/QtCreator/bin/plugins/designer(这个影响QtCreator),这是受到各种因素影响的。

    好了,将so文件copy过去以后重启qt,是不是在编辑界面的时候已经能够从左侧的工具箱里看到自己定义的控件了?如果你定义了这个控件的icon,也把icon图片文件copy过去了,那么你此时应该能看到这个图片了。

   在这里请注意一点,Qt5 并不是绝对向下兼容的,在Qt4中注册控件的语句 Q_EXPORT_PLUGIN2已经无效了,在Qt5中这个宏改成了

#define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
Q_STATIC_ASSERT_X(false, "Old plugin system used")
#define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS) \
Q_STATIC_ASSERT_X(false, "Old plugin system used")
,现在需要使用 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface")。

      正常情况下,在Qt5和Qt Creator的工具栏里面应该已经有一个User Define控件了。

      当然现在这个控件上面什么东西都没有,接下来要做的事情还有很多。

       首先来看看这个工程内包含哪些东西: 最主要的就是一个plugin类和一个实现类(我这边是QGeoImagePlugin , QGeoImage),QGeoImagePlugin继承自QDesignerCustomWidgetInterface,注意它的createWidget方法,

QWidget *QGeoImagePlugin::createWidget(QWidget *parent)
{
    return new QGeoImage(parent);
}
可见这个插件实现了通过createidget方法来调用QGeoImage功能类实现。但是生成的so文件是QGeoImagePlugin的.so文件,他没有导出QGeoImage类的代码,这导致我们使用这个控件的程序想要编译通过就需要将QGeoImage的h/ CPP文件添加到功能模块内,是不是有点麻烦呢?

我这里给出了一个变通的方案(不排除有更好的方法), 我将.h文件添加到了Qt的include文件夹内。而QGeomage功能类,可以单独编译成so文件,这样我们就不必把cpp文件到处拷贝了!


其实这个方案本身也是Qt设计师向导类支持的方式,在创建设计师(控件)类时,我们是可以选择从现有库文件中创建的。

那让我们看看具体的控件功能如何实现。首先要知道控件功能不是实现在QGeomageoPlugin类里面,而是在QGeoImage类里。

这个类一般继承子QWidget,你在里面添加各种QWidget和Layout和代码就能实现各种功能了,这里我不具体举例了。

不过要着重介绍一点,如果你想要让自己的控件在ide可视化界面有自定义属性,那就要用到几个基本的Qt宏。

首先是Q_PROPERTY(TYPE name READ name WRITE setName)

如果想要添加一个非常简单的属性那只要实现name和setName方法即可,例如:

class QGeoImage{
   Q_OBJECT
   Q_PROPERTY(int step READ step WRITE setStep)
public:
    //...略
private:
    int step();
    void setStep(int);
    int m_Step;
}
int QGeoImage::step()
{
     return m_Step;
}

void QGeoImage::setStep(int value)
{
     m_Step = value;
}


这样在IDE界面就可以在编码时设定控件的属性了。

那如果想要实现一个下拉选单式的属性呢?这里需要用到枚举QEnum()宏

见代码

class QGeoImage : public QWidget
{
    Q_OBJECT
    Q_ENUMS(eGraphMode)
    Q_PROPERTY(eGraphMode graphMode READ graphMode WRITE setGraphMode)

public:


    //
    enum eGraphMode{
        a = 1,
        b = 2,
        c = 3,
    };
//其他代码略
    

从以上代码可以看到,要实现一个下拉选单型的控件也是非常容易的。

那让我们更进一步,实现一下联合属性,好比DockOptions这样的。这就比较复杂了,我搜了很多资料都找不到,但实际上得来全部废功夫,好好看Qt源代码即可。

QMainWindows类就有很多类似的实现。比如DockOptions,大家可以去看看,我这里有类似的模仿,很简单把。主要就是这些Q_XXXXXXX的宏,值得关注。

展示一下代码:

class QGeoImage : public QWidget
{
    Q_OBJECT
    Q_ENUMS(eScaleShowOption)
    Q_FLAGS(ScaleShowOptions)
public:
    Q_PROPERTY(ScaleShowOptions scaleShow READ scaleShow WRITE setScaleShow)

    enum eScaleShowOption {
        TopRectShow = 0x01,
        LeftRectShow = 0x02,
        RightRectShow = 0x04,
        BottomRectShow = 0x08
    };

    Q_DECLARE_FLAGS(ScaleShowOptions, eScaleShowOption)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoImage::ScaleShowOptions)

目前我的范例就做到这样,各位还可以继续深入,比如含有多种变量类型的联合属性(类似QPolicySize)的开发。

好了,当你完成了这个控件,并且将它编辑位发布版的库文件并放大镜敖我前文所说的位置后,下次再打开Qt,就能在工具箱里看到你自己的控件了。


最后,当控件编写成功后,你可以在使用到控件的地方将你编译出的库以及头文件,pri文件copy到需要使用控件的工程里,一起编译。


但是实际上还有更合理的方法,就是利用prf文件,这里我参考了Qt的手册。另外还有一篇翻译好的博文,供大家参考:浅谈qmake

基本上就是在Qt安装目录下的mkspecs/features目录里,添加一个.prf文件,将需要include的头文件以及编译所需的库文件写进去,然后在需要用到控件的工程文件里添加CONFIG += XXXX (XXXX为你缩写的prf文件的文件名)即可。

你可能感兴趣的:(操作系统,计算机科学)