Qt4.4参考文档翻译之教程7—One Thing Leads to Another

文件:

                   

 

这个例子显示了如何用信号和槽来创建自定义的窗口部件,以及如何用更复杂的方法把它们连接起来。首先,源文件被分开放到多个文件中并放在教程7目录中。

 

一行一行地品读

 

t7/lcdrange.h

 

这个文件主要利用了第六章的main.cpp;这里只是说明一下非常规的改变。

 

#ifndef LCDRANGE_H

 #define LCDRANGE_H

 

这里,包括#endif在文件的末尾,是标准的C++构造函数来避免某个头文件被包含了多次的错误。如果你还没有用过它(就使用它吧),这是一个程序开发的好习惯。

 

#include <QWidget>

 

<QWidget>被包含了因为我们的LCDRange类继承QWidget。父类的头文件应该总是被包含——在前面的章节我们实际上是“投机取巧”的行为:我们让<QWidget>通过其他头文件间接的被包含。

 

class QSlider;

 

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

 

这会使编译一个大的工程变的快很多,因为编译器通常花费大多数时间去解析头文件,而不是实际的源代码。仅这个小伎俩单独就能将编译的速度加快两倍或者两倍以上。

 

class LCDRange : public QWidget

 {

     Q_OBJECT

 

 public:

     LCDRange(QWidget *parent = 0);

 

注意Q_OBJECT。这个宏必须被包含在所有包含信号和/或槽的类中。如果你很好奇,(你会发现)它定义了在元对象文件中实现的函数。

 

     int value() const;

 

 public slots:

     void setValue(int value);

 

 signals:

void valueChanged(int newValue);

 

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

 

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

 

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

valueChanged()信号在LCDRange的值发生变化时就会被使用。

t7/lcdrange.cpp

这个文件主要利用了第六章的main.cpp,这里只是说明一下有哪些改变。

connect(slider, SIGNAL(valueChanged(int)),

             lcd, SLOT(display(int)));

     connect(slider, SIGNAL(valueChanged(int)),

this, SIGNAL(valueChanged(int)));

 

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

 

第一个connect和你在上一章中看到的一样。第二个是新的,它把滑块的valueChanged()信号和这个对象的valueChanged()信号连接起来了。是的,这是正确的。信号可以被连接到其它的信号。当第一个信号被发射时,第二个信号也被发射。

 

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

 

因此,当这个信号被发射的时候,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数字的值。另外,如果滑块的值超过了合法范围,它会自动调节。

 

t7/main.cpp

 

     LCDRange *previousRange = 0;

 

     for (int row = 0; row < 3; ++row) {

         for (int column = 0; column < 3; ++column) {

             LCDRange *lcdRange = new LCDRange;

             grid->addWidget(lcdRange, row, column);

             if (previousRange)

                 connect(lcdRange, SIGNAL(valueChanged(int)),

                         previousRange, SLOT(setValue(int)));

             previousRange = lcdRange;

         }

     }

 

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

 

编译

 

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

 

qmake -project

 qmake

 

第一个命令告诉qmake去穿件一个.pro文件。第二个命令让它根据这个项目文件来生成一个(相关平台的)makefile。你现在应该可以键入make(或者nmake,如果你用的是Visual Studio)来建立你的应用程序。

 

运行这个应用程序

 

在开始的时候,这个程序看起来和前一章的一样。试着操作右下角的滑块。

 

练习

 

使用右下角的滑块将所有的LCD设置到50。然后通过点击上面一排的滑块将上面的6个设置为30。现在,你可以通过把最后一个调到左边来把前五个LCD设置回50

 

点击右下角滑块的滑块的左边。发生了什么?为什么这是正确的行为?

 

注:原文见http://doc.trolltech.com/4.4/tutorials-tutorial-t7.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值