下面显示了如何使用信号和槽来创建自定义窗口部件,和如何使用更加复杂的方式把它们连接起来。

首先,源文件被我们分成几部分并放在放在t7目录下。

t7/lcdrange.h包含LCDRange类定义。
t7/lcdrange.cpp包含LCDRange类实现。
t7/main.cpp包含MyWidget和main。

t7/lcdrange.h这个文件主要利用了前面博文的main.cpp,在这里只是说明一下改变了哪些。

#ifndef LCDRANGE_H
    #define LCDRANGE_H
这里是一个经典的C语句,为了避免出现一个头文件被包含不止一次的情况。如果你没有使用过它,这是开发中的一个很好的习惯。#ifndef需要把这个头文件的全部都包含进去。

#include <qvbox.h>
qvbox.h被包含了。LCDRange继承了QVBox,所以父类的头文件必须被包含。我们在前几章里面偷了一点懒,我们通过包含其它一些头文件,比如qpushbutton.h,这样就可以间接地包含qwidget.h。

class QSlider;
这里是另外一个小伎俩,但是没有前一个用的多。因为我们在类的界面中不需要QSlider,仅仅是在实现中,我们在头文件中使用一个前置的类声明,并且在.cpp文件中包含一个QSlider的头文件。

这会使编译一个大的项目变得更快,因为当一个头文件改变的时候,很少的文件需要重新编译。它通常可以给大型编译加速两倍或两倍以上。

    class LCDRange : public QVBox
{
Q_OBJECT
public:
LCDRange( QWidget *parent=0, const char *name=0 );
        int value() const;
    public slots:
        void setValue( int );
    signals:
        void valueChanged( int );

meta object file. 注意Q_OBJECT。这个宏必须被包含到所有使用信号和/或槽的类。如果你很好奇,它定义了在元对象文件中实现的一些函数。

这三个成员函数构成了这个窗口部件和程序中其它组件的接口。直到现在,LCDRange根本没有一个真正的接口。

value()是一个可以访问LCDRange的值的公共函数。setValue()是我们第一个自定义槽,并且valueChanged()是我们第一个自定义信号。

槽必须按通常的方式实现(记住槽也是一个C++成员函数)。信号可以在元对象文件中自动实现。信号也遵守C++函数的保护法则(比如,一个类只能发射它自己定义的或者继承来的信号)。

当LCDRange的值发生变化时,valueChanged()信号就会被使用——你从这个名字中就可以猜到。这将不会是你将会看到的命名为somethingChanged()的最后一个信号。

t7/lcdrange.cpp这个文件主要利用了t6/main.cpp,在这里只是说明一下改变了哪些。

        connect( slider, SIGNAL(valueChanged(int)),
lcd, SLOT(display(int)) );
connect( slider, SIGNAL(valueChanged(int)),
SIGNAL(valueChanged(int)) );

这个代码来自LCDRange的构造函数。

第一个connect和你在上一篇中看到的一样。第二个是新的,它把滑块的valueChanged()信号和这个对象的valueChanged信号连接起来了。带有三个参数的connect()函数连接到this对象的信号或槽。

是的,这是正确的。信号可以被连接到其它的信号。当第一个信号被发射时,第二个信号也被发射。

让我们来看看当用户操作这个滑块的时候都发生了些什么。滑块看到自己的值发生了改变,并发射了valueChanged()信号。这个信号被连接到QLCDNumber的display()槽和LCDRange的valueChanged()信号。

所以,当这个信号被发射的时候,LCDRange发射它自己的valueChanged()信号。另外,QLCDNumber::display()被调用并显示新的数字。

注意你并没有保证执行的任何顺序——LCDRange::valueChanged()也许在QLCDNumber::display()之前或者之后发射,这是完全任意的。

    int LCDRange::value() const
{
return slider->value();
}

value()的实现是直接了当的,它简单地返回滑块的值。

    void LCDRange::setValue( int value )
{
slider->setValue( value );
}

setValue()的实现是相当直接了当的。注意因为滑块和LCD数字是连接的,设置滑块的值就会自动的改变LCD数字的值。另外,如果滑块的值超过了合法范围,它会自动调节。

        LCDRange *previous = 0;
for( int r = 0 ; r < 4 ; r++ ) {
for( int c = 0 ; c < 4 ; c++ ) {
LCDRange* lr = new LCDRange( grid );
if ( previous )
connect( lr, SIGNAL(valueChanged(int)),
previous, SLOT(setValue(int)) );
previous = lr;
}
}

main.cpp中所有的部分都是上一章复制的,除了MyWidget的构造函数。当我们创建16个RCDRange对象时,我们现在使用信号/槽机制连接它们。每一个的valueChanged()信号都和前一个的setValue()槽连接起来了。因为当LCDRange的值发生改变的时候,发射一个valueChanged()信号(惊奇!),我们在这里创建了一个信号和槽的“链”。

编译
为一个多文件的应用程序创建一个makefile和为一个单文件的应用程序创建一个makefile是没有什么不同的。如果你已经把这个例子中的所有文件都保存到它们自己的目录中,你所要做的就是这些:

qmake -project
qmake
第一个命令调用qmake来生成一个.pro(项目)文件。第二个命令根据这个项目文件来生成一个(系统相关的)makefile。你现在可以输入make(或者nmake,如果你使用Visual Studio)。

Qt入门(18)——使用信号和槽连接控件的更多相关文章

  1. Qt入门(17)——组装复杂的控件

    下面是如何把两个窗口部件封装成一个新的组件.首先,我们使用一个自定义的窗口部件作为一个子窗口部件. #include <qapplication.h> #include <qpush ...

  2. QT 信号与槽连接

    转帖 http://www.cnblogs.com/cnhome/archive/2009/10/01/1577277.html 信号(SIGNAL)和槽(SLOT)是Qt编程的一个重要部分.这个机制 ...

  3. 第七章 探秘Qt的核心机制-信号与槽

    第七章 探秘Qt的核心机制-信号与槽 注:要想使用Qt的核心机制信号与槽,就必须在类的私有数据区声明Q_OBJECT宏,然后会有moc编译器负责读取这个宏进行代码转化,从而使Qt这个特有的机制得到使用 ...

  4. Qt Quick 事件处理之信号与槽

    前面两篇文章<QML 语言基础>和<Qt Quick 简单教程>中我们介绍了 QML 语言的基本的语法和 Qt Quick 的常见元素,亲们,通过这两篇文章,您应该已经能够完毕 ...

  5. 2.QT-窗口组件(QWidget),QT坐标系统,初探消息处理(信号与槽)

    本章主要内容如下: 1) 窗口组件(QWidget) 2) QT坐标系统 3) 消息处理(信号与槽) 窗口组件(QWidget) 介绍 Qt以组件对象的方式构建图形用户界面 Qt中没有父组件的顶级组件 ...

  6. Qt对象模型之一:信号和槽

    一.信号和槽机制概述 信号槽是 Qt 框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal).这种发出是没有目 ...

  7. Qt Quick 事件处理之信号与槽(foruok的博客)

    前面两篇文章<QML 语言基础>和<Qt Quick 简单教程>中我们介绍了 QML 语言的基本语法和 Qt Quick 的常见元素,亲们,通过这两篇文章,您应该已经可以完成简 ...

  8. [ PyQt入门教程 ] PyQt5信号与槽

    信号和槽是PyQt编程对象之间进行通信的机制.每个继承自QWideget的控件都支持信号与槽机制.信号发射时(发送请求),连接的槽函数就会自动执行(针对请求进行处理).本文主要讲述信号和槽最基本.最经 ...

  9. vs2017中信号与槽连接

    在vs2012里和在Qt Creator里添加信号和槽不一样,这里把两种环境下怎么添加详细说明一下 1.在vs2012里添加信号和槽 新建一个qt的项目QtDemo 在qtdeom.h里添加槽 pri ...

随机推荐

  1. 为什么我选择使用 Blocks(块)

    扯淡:到了新公司接手新框架之后,发现大量的使用Blocks,之前很多时候都是使用代理,突然面对这个陌生的语法,特地科普总结了一番. 什么是Blocks 一句话概括就是,带有局部变量的匿名函数(即不带名 ...

  2. iOS的内存管理

    在Objective-C 这种面向对象的语言里,内存管理是个重要的概念.要想用一门语言写出内存使用效率高而且又没有bug的代码,就得掌握其内存管理模型的种种细节. 一旦理解了这些规则,你就会发现,其实 ...

  3. 9.20 noip模拟试题

      Problem 1 双色球(ball.cpp/c/pas) [题目描述] 机房来了新一届的学弟学妹,邪恶的chenzeyu97发现一位学弟与他同名,于是他当起了善良的学长233 “来来来,学弟,我 ...

  4. asp.net 的脚本

    asp.net的 Web 控件有时会包装一些用户端脚本 (client-side scripting),在控件被绘制时输出到用户端,这些脚本多数被包装在 DLL 的资源档中,并由 ScriptReso ...

  5. Android WebView和JavaScript交互

    JavaScript在现在的网页设计中用得很多,Android 的WebView可以载入网页,WebView也设计了与JavaScript通信的桥梁.这篇主要介绍一下WebViewk控件如何和Java ...

  6. angularjs kindEditor 中自定义按钮 弹出dialog

    1.angular-kindeditor.js 第38行左右加 editorConfig.items = ["placehoder"]; 2.en.js 第234行 placeho ...

  7. Member var and Static var.

    /* member variable and static variable: 1,invoke ways: member variable,also called 'instance' variab ...

  8. 【POJ1823】【线段树】Hotel

    Description The "Informatics" hotel is one of the most luxurious hotels from Galaciuc. A l ...

  9. 《chkconfig命令》-linux命令五分钟系列之四

    本原创文章属于<Linux大棚>博客. 博客地址为http://roclinux.cn. 文章作者为roc 希望您能通过捐款的方式支持Linux大棚博客的运行和发展.请见“关于捐款” == ...

  10. CSS3 Animation学习笔记

    Internet Explorer 9,以及更早的版本, 不支持 @keyframe 规则或 animation 属性. Internet Explorer 10.Firefox 以及 Opera 支 ...