Archive:Development/Tutorials/Qt4 Ruby Tutorial/Chapter 07 (zh CN): Difference between revisions
No edit summary |
Neverendingo (talk | contribs) m (Text replace - "<code ruby>" to "<syntaxhighlight lang="ruby">") |
||
Line 25: | Line 25: | ||
这个档案主要是抄袭自第6章,这里只提出比较特别的改变。 | 这个档案主要是抄袭自第6章,这里只提出比较特别的改变。 | ||
< | <syntaxhighlight lang="ruby"> | ||
signals 'valueChanged(int)' | signals 'valueChanged(int)' | ||
slots 'setValue(int)' | slots 'setValue(int)' | ||
</code> | </code> | ||
< | <syntaxhighlight lang="ruby"> | ||
def value() | def value() | ||
@slider.value() | @slider.value() | ||
Line 51: | Line 51: | ||
'''<tt>setValue()</tt>''' 的实作也同样简单。请注意,因为 slider 和 LCD number 连接,设定 slider 的值时,LCD number 也会自动更新。此外,如果超出规定范围,slider 会自动调整值。 | '''<tt>setValue()</tt>''' 的实作也同样简单。请注意,因为 slider 和 LCD number 连接,设定 slider 的值时,LCD number 也会自动更新。此外,如果超出规定范围,slider 会自动调整值。 | ||
< | <syntaxhighlight lang="ruby"> | ||
connect(@slider, SIGNAL('valueChanged(int)'), | connect(@slider, SIGNAL('valueChanged(int)'), | ||
lcd, SLOT('display(int)')) | lcd, SLOT('display(int)')) | ||
Line 67: | Line 67: | ||
'''[http://www.darshancomputing.com/qt4-qtruby-tutorial/tutorial/t7/t7.rb t7.rb]''' | '''[http://www.darshancomputing.com/qt4-qtruby-tutorial/tutorial/t7/t7.rb t7.rb]''' | ||
< | <syntaxhighlight lang="ruby"> | ||
previousRange = nil | previousRange = nil | ||
Revision as of 20:43, 29 June 2011
Template:I18n/Language Navigation Bar (zh CN)
Template:TutorialBrowser (zh CN)
One Thing Leads to Another
档案:
概览
这个范例展示如何建立具有讯号和槽的自定义 widget,以及如何用更复杂的方式将它们连接起来。这是第一次,原始码被分割在几个档案中。
一行一行的浏览
这个档案主要是抄袭自第6章,这里只提出比较特别的改变。
<syntaxhighlight lang="ruby"> signals 'valueChanged(int)' slots 'setValue(int)' <syntaxhighlight lang="ruby"> def value()
@slider.value()
end
def setValue(value)
@slider.setValue(value)
end
这些构成了这个 widget 和程序中其他组件之间的接口。到目前为止,LCDRange 还没真的拥有一个 API。
value() 是一个存取 LCDRange 值的公开(public)函式、setValue() 是我们第一个自定义槽,而 valueChanged()是我们第一个自定义讯号。
Slot 必须用正规方式实作(槽也是一个 Ruby 成员函式)。讯号会被自动实作。讯号遵循 Ruby 保护(protected)函式的存取规则(换言之,只有定义他们的类别或继承的类别可以发出它们)。
当 LCDRange 的值发生改变时,valueChanged() 讯号就会被使用。
value() 的实作非常简单。它只是返回 slider 的值。
setValue() 的实作也同样简单。请注意,因为 slider 和 LCD number 连接,设定 slider 的值时,LCD number 也会自动更新。此外,如果超出规定范围,slider 会自动调整值。
<syntaxhighlight lang="ruby"> connect(@slider, SIGNAL('valueChanged(int)'),
lcd, SLOT('display(int)'))
connect(@slider, SIGNAL('valueChanged(int)'),
self, SIGNAL('valueChanged(int)'))
第一个 QObject::connect() 呼叫与前几章看到的相同。第二个是新的,它连接 QAbstractSlider::valueChanged() 讯号到这个对象的 valueChanged() 讯号。是的,没错。讯号也可以连接到其他的讯号。当第一个讯号被发出时,第二个讯号也被发出。
让我们看看当使用者操作 slider 时,会发生什么事。当 slider 发现它的值已经改变,就会发出QAbstractSlider::valueChanged() 讯号。这个讯号连接到 Qt::LCDNumber 的 QLCDNumber::display() 槽和 LCDRange 的 valueChanged() 讯号。
因此,当这个讯号发出时,LCDRange 也发出自己的 valueChanged() 讯号。此外,QLCDNumber::display() 被呼叫并显示新的数字。
请注意,你不能确定任何执行的特定顺序,LCDRange::valueChanged() 可能会在QLCDNumber::display() 被呼叫之前或之后发出。
t7.rb <syntaxhighlight lang="ruby"> previousRange = nil
for row in 0..2
for column in 0..2 lcdRange = LCDRange.new() grid.addWidget(lcdRange, row, column) unless previousRange.nil? connect(lcdRange, SIGNAL('valueChanged(int)'), previousRange, SLOT('setValue(int)')) end previousRange = lcdRange end
end
当我们建立9个 LCDRange 对象时,我们使用讯号与槽机制将它们连接在一起。每一个 LCDRange 的 valueChanged() 讯号都会连接到前一个的 setValue() 槽。因为每当 LCDRange 的值改变时,都会发出 valueChanged() 讯号,所以我们在这里建立一个讯号与槽的连锁反应。
执行应用程序
在启动时,这支程序的外观和前一章的一模一样。尝试操作右下角的 slider。
练习
使用右下角的 slider 来设定所有 LCD 为50。然后单击底部中间 slider 把手的左侧,设定除了最后一个所有的 LCD 为40。现在,使用左下角的 slider 来设定前七个 LCD 回到50。
按下右下角 slider 把手的左侧。会发生什么事?为什么这是正确的行为?