Archive:Development/Tutorials/Qt4 Ruby Tutorial/Chapter 07 (zh CN)
Template:I18n/Language Navigation Bar (zh CN)
Template:TutorialBrowser (zh CN)
One Thing Leads to Another
档案:
概览
这个范例展示如何建立具有讯号和槽的自定义 widget,以及如何用更复杂的方式将它们连接起来。这是第一次,原始码被分割在几个档案中。
一行一行的浏览
这个档案主要是抄袭自第6章,这里只提出比较特别的改变。
signals 'valueChanged(int)'
slots 'setValue(int)'
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 会自动调整值。
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
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 把手的左侧。会发生什么事?为什么这是正确的行为?