⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qt教程一 —— 第七章:一个事物领导另一个.htm

📁 嵌入式QT开发系列文档
💻 HTM
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0061)http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial1-07.html -->
<!-- /home/reggie/tmp/qt-3.0-reggie-5401/qt-win-commercial-3.0.5/doc/tutorial.doc:670 --><HTML><HEAD><TITLE>Qt教程一 —— 第七章:一个事物领导另一个</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content=Cavendish name=Translator>
<META content=http://www.qiliang.net/qt name="Qt zh_CN Documents Website">
<STYLE type=text/css>H3.fn {
	MARGIN-LEFT: 1cm; TEXT-INDENT: -1cm
}
SPAN.fn {
	MARGIN-LEFT: 1cm; TEXT-INDENT: -1cm
}
A:link {
	COLOR: #004faf; TEXT-DECORATION: none
}
A:visited {
	COLOR: #672967; TEXT-DECORATION: none
}
BODY {
	BACKGROUND: #ffffff; COLOR: black; FONT-FAMILY: "Times New Roman"
}
</STYLE>

<META content="MSHTML 6.00.2900.2180" name=GENERATOR></HEAD>
<BODY>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
  <TBODY>
  <TR bgColor=#e5e5e5>
    <TD vAlign=center><A 
      href="http://www.qtopia.org.cn/doc/qiliang.net/qt/index.html"><FONT 
      color=#004faf>主页</FONT></A> | <A 
      href="http://www.qtopia.org.cn/doc/qiliang.net/qt/classes.html"><FONT 
      color=#004faf>所有的类</FONT></A> | <A 
      href="http://www.qtopia.org.cn/doc/qiliang.net/qt/mainclasses.html"><FONT 
      color=#004faf>主要的类</FONT></A> | <A 
      href="http://www.qtopia.org.cn/doc/qiliang.net/qt/annotated.html"><FONT 
      color=#004faf>注释的类</FONT></A> | <A 
      href="http://www.qtopia.org.cn/doc/qiliang.net/qt/groups.html"><FONT 
      color=#004faf>分组的类</FONT></A> | <A 
      href="http://www.qtopia.org.cn/doc/qiliang.net/qt/functions.html"><FONT 
      color=#004faf>函数</FONT></A> </TD>
    <TD vAlign=center align=right><IMG height=32 
      src="Qt教程一 —— 第七章:一个事物领导另一个.files/logo32.png" width=64 align=right 
      border=0></TD></TR></TBODY></TABLE>
<H1 align=center>Qt教程一 —— 第七章:一个事物领导另一个</H1>
<P>
<CENTER><IMG alt="Screenshot of tutorial seven" 
src="Qt教程一 —— 第七章:一个事物领导另一个.files/t7.png"></CENTER>
<P>这个例子显示了如何使用信号和槽来创建自定义窗口部件,和如何使用更加复杂的方式把它们连接起来。首先,源文件被我们分成几部分并放在放在<TT>t7</TT>目录下。 

<P>
<UL>
  <LI><A 
  href="http://www.qtopia.org.cn/doc/qiliang.net/qt/t7-lcdrange-h.html">t7/lcdrange.h</A>包含LCDRange类定义。 

  <LI><A 
  href="http://www.qtopia.org.cn/doc/qiliang.net/qt/t7-lcdrange-cpp.html">t7/lcdrange.cpp</A>包含LCDRange类实现。 

  <LI><A 
  href="http://www.qtopia.org.cn/doc/qiliang.net/qt/t7-main-cpp.html">t7/main.cpp</A>包含MyWidget和main。 
  </LI></UL>
<P>
<H2>一行一行地解说 </H2><A name=1></A>
<P>
<H3><A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/t7-lcdrange-h.html">t7/lcdrange.h</A> 
</H3><A name=1-1></A>
<P>这个文件主要利用了第六章的<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial1-06.html#main">main.cpp</A>,在这里只是说明一下改变了哪些。 

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

<P><PRE>    #include &lt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qvbox-h.html">qvbox.h</A>&gt;
</PRE>
<P><A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qvbox-h.html">qvbox.h</A>被包含了。LCDRange继承了<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qvbox.html">QVBox</A>,所以父类的头文件必须被包含。我们在前几章里面偷了一点懒,我们通过包含其它一些头文件,比如<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qpushbutton-h.html">qpushbutton.h</A>,这样就可以间接地包含<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qwidget-h.html">qwidget.h</A>。 

<P><PRE>    class QSlider;
</PRE>
<P>这里是另外一个小伎俩,但是没有前一个用的多。因为我们在类的<EM>界面</EM>中不需要<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qslider.html">QSlider</A>,仅仅是在实现中,我们在头文件中使用一个前置的类声明,并且在.cpp文件中包含一个QSlider的头文件。 

<P>这会使编译一个大的项目变得更快,因为当一个头文件改变的时候,很少的文件需要重新编译。它通常可以给大型编译加速两倍或两倍以上。 
<P><PRE>    class LCDRange : public <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qvbox.html">QVBox</A>
    {
        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/metaobjects.html#Q_OBJECT">Q_OBJECT</A>
    public:
        LCDRange( <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qwidget.html">QWidget</A> *parent=0, const char *name=0 );
</PRE>
<P><A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/metaobjects.html">meta 
object file</A>. 注意Q_OBJECT。这个宏必须被包含到<EM>所有</EM>使用信号和/或槽的类。如果你很好奇,它定义了在<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/metaobjects.html">元对象文件</A>中实现的一些函数。 

<P><PRE>        int value() const;
    public slots:
        void setValue( int );

    signals:
        void valueChanged( int );
</PRE>
<P>这三个成员函数构成了这个窗口部件和程序中其它组件的接口。直到现在,LCDRange根本没有一个真正的接口。 
<P>value()是一个可以访问LCDRange的值的公共函数。setValue()是我们第一个自定义槽,并且valueChanged()是我们第一个自定义信号。 

<P>槽必须按通常的方式实现(记住槽也是一个C++成员函数)。信号可以在<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/signalsandslots.html">元对象</A>文件中自动实现。信号也遵守C++函数的保护法则(比如,一个类只能发射它自己定义的或者继承来的信号)。 

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

<P>
<H3><A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/t7-lcdrange-cpp.html">t7/lcdrange.cpp</A> 
</H3><A name=1-2></A>
<P>
<P>这个文件主要利用了<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial1-06.html#main">t6/main.cpp</A>,在这里只是说明一下改变了哪些。 

<P><PRE>    <A name=x2265></A>    <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qobject.html#connect">connect</A>( slider, SIGNAL(<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qslider.html#valueChanged">valueChanged</A>(int)),
    <A name=x2262></A>             lcd, SLOT(<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html#display">display</A>(int)) );
        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qobject.html#connect">connect</A>( slider, SIGNAL(<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qslider.html#valueChanged">valueChanged</A>(int)),
                 SIGNAL(valueChanged(int)) );
</PRE>
<P>这个代码来自LCDRange的构造函数。 
<P>第一个connect和你在上一章中看到的一样。第二个是新的,它把滑块的valueChanged()信号和这个对象的valueChanged<EM>信号</EM>连接起来了。带有三个参数的connect()函数连接到<TT>this</TT>对象的信号或槽。 

<P>是的,这是正确的。信号可以被连接到其它的信号。当第一个信号被发射时,第二个信号也被发射。 
<P>让我们来看看当用户操作这个滑块的时候都发生了些什么。滑块看到自己的值发生了改变,并发射了valueChanged()信号。这个信号被连接到<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html">QLCDNumber</A>的display()槽和LCDRange的valueChanged()信号。 

<P>所以,当这个信号被发射的时候,LCDRange发射它自己的valueChanged()信号。另外,<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html#display">QLCDNumber::display</A>()被调用并显示新的数字。 

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

<P><PRE>    int LCDRange::value() const
    {
    <A name=x2264></A>    return slider-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qslider.html#value">value</A>();
    }
</PRE>
<P>value()的实现是直接了当的,它简单地返回滑块的值。 
<P><PRE>    void LCDRange::setValue( int value )
    {
    <A name=x2263></A>    slider-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qslider.html#setValue">setValue</A>( value );
    }
</PRE>
<P>setValue()的实现是相当直接了当的。注意因为滑块和LCD数字是连接的,设置滑块的值就会自动的改变LCD数字的值。另外,如果滑块的值超过了合法范围,它会自动调节。 

<P>
<H3><A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/t7-main-cpp.html">t7/main.cpp</A> 
</H3><A name=1-3></A>
<P>
<P><PRE>        LCDRange *previous = 0;
        for( int r = 0 ; r &lt; 4 ; r++ ) {
            for( int c = 0 ; c &lt; 4 ; c++ ) {
                LCDRange* lr = new LCDRange( grid );
                if ( previous )
                    <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qobject.html#connect">connect</A>( lr, SIGNAL(valueChanged(int)),
                             previous, SLOT(setValue(int)) );
                previous = lr;
            }
        }
</PRE>
<P>main.cpp中所有的部分都是上一章复制的,除了MyWidget的构造函数。当我们创建16个RCDRange对象时,我们现在使用<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/signalsandslots.html">信号/槽</A>机制连接它们。每一个的valueChanged()信号都和前一个的setValue()槽连接起来了。因为当LCDRange的值发生改变的时候,发射一个valueChanged()信号(惊奇!),我们在这里创建了一个信号和槽的“链”。 

<P><A name=compiling></A>
<H2>编译 </H2><A name=2></A>
<P>为一个多文件的应用程序创建一个makefile和为一个单文件的应用程序创建一个makefile是没有什么不同的。如果你已经把这个例子中的所有文件都保存到它们自己的目录中,你所要做的就是这些: 
<PRE>qmake -project
qmake
</PRE>
<P>第一个命令调用<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qmake-manual.html">qmake</A>来生成一个<TT>.pro</TT>(项目)文件。第二个命令根据这个项目文件来生成一个(系统相关的)makefile。你现在可以输入<TT>make</TT>(或者<TT>nmake</TT>,如果你使用Visual 
Studio)。 
<P>
<H2>行为 </H2><A name=3></A>
<P>在开始的时候,这个程序看起来和上一章里的一样。试着操作滑块到右下角…… 
<P>
<H2>练习 </H2><A name=4></A>
<P>seven LCDs back to 50. 
使用右下角的滑块并设置所有的LCD到50。然后设置通过点击这个滑块的左侧把它设置为40。现在,你可以通过把最后一个调到左边来把前七个LCD设置回50。 
<P>点击右下角滑块的滑块的左边。发生了什么?为什么只是正确的行为? 
<P>现在你可以进行<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial1-08.html">第八章</A>了。 
<P>[<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial1-06.html">上一章</A>] 
[<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial1-08.html">下一章</A>] 
[<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial.html">教程一主页</A>] 
<P><!-- eof -->
<P>
<ADDRESS>
<HR>

<DIV align=center>
<TABLE cellSpacing=0 width="100%" border=0>
  <TBODY>
  <TR>
    <TD>Copyright &copy; 2002 <A href="http://www.trolltech.com/">Trolltech</A> 
    <TD><A href="http://www.trolltech.com/trademarks.html">Trademarks</A> 
    <TD><A 
      href="http://www.qtopia.org.cn/doc/qiliang.net/qt/zh_CN.html">译者:Cavendish</A> 

    <TD align=right>
      <DIV align=right>Qt 
3.0.5版</DIV></TR></TBODY></TABLE></DIV></ADDRESS></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -