Qt开发:信号、槽与面向对象

CMake依赖

使用CMake构建Qt程序的时候,可以使用命令find_package来定位Qt的头文件路径、库文件路径以及库文件。

如:

FIND_PACKAGE (Qt6 NAMES Qt6 COMPONENTS Core Gui Widgets REQUIRED)

*** 注意:执行成功以后,将会按照COMPONENTS列表中的项目,生成一组变量。

如头文件路径为:

CMAKE_INCLUDE_DIR(${Qt6Core_INCLUDE_DIRS}  
        ${Qt6Gui_INCLUDE_DIRS}  
        ${Qt6Widgets_INCLUDE_DIRS})

将要连接的路径为:

ADD_EXECUTE(helloworld helloworld.cc)
TARGET_LINK_LIBRARIES(helloworld Qt6::Core Qt6::Gui Qt6::Widgets)

另外,Qt的一些宏依赖编译开始前的moc机制,比如需要支持信号(SIGNAL)与槽(SLOT)的类,如果不进行moc,将会无法连接。

在CMake配置文件CMakeLists.txt中,可以使用AUTOMOC来自动moc。

如果要在编译时对目标helloworld的源文件自动moc,可以如下指定:

ADD_EXECUTE(helloworld helloworld.cc)
SET_PROPERTY(TARGET helloword PROPERTY AUTOMOC ON)

信号的声明

一个类如果要支持信号,需要满足以下条件:

  1. 类必须派生自QObject(或其子类),且在类的开头加了Q_OBJECT宏。
  2. 类的信号的返回值需要是void。
  3. 类的信号只有声明,没有定义。
  4. 类的信号前面用signals: 宏来修饰。

如定义一个类Hello,声明一个信号say:

public Hello: public QObject
{
  Q_OBJECT
public:
  Hello() = default;
  ……
signals:
  void say(QString);
}

如此,就可以在其它地方用emit发送这个信号。

槽的连接

一个类要支持槽的连接,也需要满足一些条件:

  1. 类必须派生自QObject(或其子类),且在类的开头加了Q_OBJECT宏。
  2. 类的槽的前面用slots: 宏来修饰。

*** connect的时候,SIGNAL()宏包含的信号要包括完整正确的函数参数,但是不能包含参数名称 ***

比如,上面的Hello类的say信号,如果如下进行连接会返回没有这个信号:

QObject::connect(this, SIGNAL(say(QString message), this, SLOT(hear(QString));

正确的做法是:

QObject::connect(this, SIGNAL(say(QString), this, SLOT(hear(QString));

QObject的反射机制

Qt的QObject非常强大,已经在一定程度上实现了Java语言中的动态反射机制。

这一切都是使用QObject的元类对象QMetaObject来实现的。

QMetaObject的方法有:

QMetaClassInfo 	classInfo(int index) const
int 	classInfoCount() const
int 	classInfoOffset() const

const char *	className() const

QMetaMethod 	constructor(int index) const
int 	constructorCount() const

QMetaEnum 	enumerator(int index) const
int 	enumeratorCount() const
int 	enumeratorOffset() const

int 	indexOfClassInfo(const char *name) const
int 	indexOfConstructor(const char *constructor) const
int 	indexOfEnumerator(const char *name) const
int 	indexOfMethod(const char *method) const
int 	indexOfProperty(const char *name) const
int 	indexOfSignal(const char *signal) const
int 	indexOfSlot(const char *slot) const

bool 	inherits(const QMetaObject *metaObject) const

QMetaType 	metaType() const

QMetaMethod 	method(int index) const
int 	methodCount() const
int 	methodOffset() const

QObject *	newInstance(Args &&... arguments) const

QMetaProperty 	property(int index) const
int 	propertyCount() const
int 	propertyOffset() const

const QMetaObject *	superClass() const
QMetaProperty 	userProperty() const

其中:

className()可以返回类的名称。

method(int index)可以获取类的方法QMetaMethod,QMetaMethod包含方法的类型、名称、参数等各种相信。

比如,下面的代码片段,可以打印出hello对象支持的所有信号,以及它的参数:

  auto meta = hello->metaObject();
  for (auto ind = 0; ind < meta->methodCount(); ++ ind)
    {
      auto method = meta->method (ind);
      if (method.methodType() == QMetaMethod::MethodType::Signal)
        {
          auto signature = method.methodSignature().toStdString();
          debug("signal %s->%s", meta->className(), signature.c_str());
        }
    }

inherits(const QMetaObject *metaObject)可以判断当前对象是否是某个类以及它的父类。

另外,QObject也有一个inherits(const char *)方法,可以以字符串的形式直接查询一个对象是否是某个类或者它的父类。

如:

auto layout = new QBoxLayout();
layout->inherits("QObject"); // 返回true
layout->inherits("QLayout"); // 返回true
layout->inherits("QVBoxLayout"); //返回假
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值