qt教程(编辑修改稿)内容摘要:

ublic: LCDRange( QWidget *parent=0, const char *name=0 )。 }。 LCDRange::LCDRange( QWidget *parent, const char *name ) : QVBox( parent, name ) { QLCDNumber *lcd = new QLCDNumber( 2, this, lcd )。 QSlider * slider = new QSlider( Horizontal, this, slider )。 slidersetRange( 0, 99 )。 slidersetValue( 0 )。 connect( slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)) )。 } class MyWidget : public QVBox { public: MyWidget( QWidget *parent=0, const char *name=0 )。 }。 MyWidget::MyWidget( QWidget *parent, const char *name ) : QVBox( parent, name ) { QPushButton *quit = new QPushButton( Quit, this, quit )。 quitsetFont( QFont( Times, 18, QFont::Bold ) )。 connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) )。 QGrid *grid = new QGrid( 4, this )。 for( int r = 0。 r 4。 r++ ) for( int c = 0。 c 4。 c++ ) (void)new LCDRange( grid )。 } int main( int argc, char **argv ) { QApplication a( argc, argv )。 MyWidget w。 ( amp。 w )。 ()。 return ()。 } 一行一行地解说 class LCDRange : public QVBox { public: LCDRange( QWidget *parent=0, const char *name=0 )。 }。 LCDRange 窗口部件是一个没有任何 API的 窗口部件。 它只有一个构造函数。 这种窗口部件不是很有用,所以我们一会儿会加入一些 API。 LCDRange::LCDRange( QWidget *parent, const char *name ) : QVBox( parent, name ) { QLCDNumber *lcd = new QLCDNumber( 2, this, lcd )。 QSlider * slider = new QSlider( Horizontal, this, slider )。 slidersetRange( 0, 99 )。 slidersetValue( 0 )。 connect( slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)) )。 } 这里直接利用了第五章里面的 MyWidget的构造函数。 唯一的不同是按钮被省略了并且这个类被重新命名了。 class MyWidget : public QVBox { public: MyWidget( QWidget *parent=0, const char *name=0 )。 }。 MyWidget 也是除了一个构造函数之外没有包含任何 API。 MyWidget::MyWidget( QWidget *parent, const char *name ) : QVBox( parent, name ) { QPushButton *quit = new QPushButton( Quit, this, quit )。 quitsetFont( QFont( Times, 18, QFont::Bold ) )。 connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) )。 这个按钮被放在 LCDRange 中,这样我们就有了一个 “Quit”按钮和许多LCDRange 对象。 QGrid *grid = new QGrid( 4, this )。 我们创建了一个四列的 QGrid对象。 这个 QGrid窗口部件可以自动地把自己 地子窗口部件排列到行列中,你可以指定行和列的数量,并且 QGrid可以发现它的新子窗口部件并且把它们安放到网格中。 for( int r = 0。 r 4。 r++ ) for( int c = 0。 c 4。 c++ ) (void)new LCDRange( grid )。 四行,四列。 我们创建了一个 4*4 个 LCDRanges,所有这些都是这个 grid 对象的子窗口部件。 这个 QGrid 窗口部件会安排它们。 } 这就是全部了。 行为 这个程序显示了在同一时间使用许多窗口部件是多么的容易。 其中的滑块和LCD 数字的行为在前一章已经提到过了。 还有就是,就是实现的不同。 (请看 编译 来学习如何创建一个 makefile 和连编应用程序。 ) 练习 在开始的时候使用不同的或者随机的值初始化每个滑块。 源代码中的 “4”出现了 3 次。 如果你改变 QGrid构造函数中调用的那个,会发生什么。 改变另外两个又会发生什么呢。 为什么呢。 现在你可以进行 第七章 了。 Qt 教程一 —— 第七章:一个事物领导另一个 这个例子显示了如何使用信号和槽来创建自定义窗口部件,和如何使用更加复杂的方式把它们连接起来。 首先,源文件被我们分成几部分并放在放在 t7 目录下。 t7/ LCDRange 类定义。 t7/ LCDRange 类实现。 t7/ MyWidget 和 main。 一行一行地解说 t7/ 这个文件主要利用了第六章的 ,在这里只是说明一下改变了哪些。 ifndef LCDRANGE_H define LCDRANGE_H 这里是一个经典的 C语句, 为了避免出现一个头文件被包含不止一次的情况。 如果你没有使用过它,这是开发中的一个很好的习惯。 ifndef 需要把这个头文件的 全部 都包含进去。 include。 LCDRange 继承了 QVBox,所以父类的头文件必须被包含。 我们在前几章里面偷了一点懒,我们通过包含其它一些头文件,比如 ,这样就可以间接地包含。 class QSlider。 这里是另外一个小伎俩,但是 没有前一个用的多。 因为我们在类的 界面 中不需要 QSlider,仅仅是在实现中,我们在头文件中使用一个前置的类声明,并且在 .cpp文件中包含一个 QSlider 的头文件。 这会使编译一个大的项目变得更快,因为当一个头文件改变的时候,很少的文件需要重新编译。 它通常可以给大型编译加速两倍或两倍以上。 class LCDRange : public QVBox { Q_OBJECT public: LCDRange( QWidget *parent=0, const char *name=0 )。 meta object file. 注意 Q_OBJECT。 这个宏必须被包含到 所有 使用信号和 /或槽的类。 如果你很好奇,它定义了在 元对象文件 中实现的一些函数。 int value() const。 public slots: void setValue( int )。 signals: void valueChanged( int )。 这三个成员函数构成了这个 窗口部件和程序中其它组件的接口。 直到现在,LCDRange 根本没有一个真正的接口。 value()是一个可以访问 LCDRange 的值的公共函数。 setValue()是我们第一个自定义槽,并且 valueChanged()是我们第一个自定义信号。 槽必须按通常的方式实现(记住槽也是一个 C++成员函数)。 信号可以在 元对象 文件中自动实现。 信号也遵守 C++函数的保护法则(比如,一个类只能发射 它自己定义的或者继承来的信号)。 当 LCDRange 的值发生变化时, valueChanged()信号就会被使用 ——你从这个名字中就可以猜到。 这将不会是你将会看到的命名为 somethingChanged()的最后一个信号。 t7/ 这个文件主要利用了 t6/,在这里只是说明一下改变了哪些。 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 slidervalue()。 } value()的实现是直接了当的,它简单地返回滑块的值。 void LCDRange::setValue( int value ) { slidersetValue( value )。 } setValue()的实现是相当直接了当的。 注意因为滑块和 LCD 数字是连接的,设置滑块的值就会自动的改变 LCD 数字的值。 另外,如果滑块的值超过了合法范围,它会自动调节。 t7/ 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。 } } ,除了 MyWidget 的构造函数。 当我们创建 16 个RCDRange 对象时,我们现在使用 信号 /槽 机制连接它们。 每一个的 valueChanged()信号都和前一个的 setValue()槽。
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。