在最前面的两章,我们介绍了具有属性和操作的对象。除了属性和操作,一些对象还带有事件(Event)。事件就像被触发的信号,例如,为了应对类似移动或点击鼠标的用户操作。某种程度上说,事件同操作是相对的。对于操作,您作为一个程序员调用操作让计算机做一些事情;然后对于事件,计算机通知您一些有意思的事情发生了。
事件是介绍程序交互性的核心。如果您想让用户同您的程序交互,您必须使用事件。比方说,您正在编写一个Tic-Tac-Toe 游戏(也有叫井字棋的,是一种类似于五子棋的连线游戏)。您希望能让用户选择他的角色,对吗?这里就涉及到事件 – 您在您的程序中使用事件来收到用户输入。如果这样的解释难以明白,不要担心,我们来看一个非常简单的示例来帮助您理解什么是事件以及如何使用事件。
下面是一个非常简单的程序,只有一行语句和一个子例程。子例程使用 GraphicsWindow(图形窗口)对象的 ShowMessage(显示消息)操作显示一个对话框给用户。
GraphicsWindow.MouseDown = OnMouseDown
Sub OnMouseDown
GraphicsWindow.ShowMessage("You Clicked.", "Hello")
EndSub
上面程序中一个有意思的部分是我们将一个子例程指派到 GraphicsWindow 对象的 MouseDown(按下鼠标)事件的那一行。您可能注意到了 MouseDown 看起来非常像一个属性 – 除了指定一些值(我们将子例程 OnMouseDown 指派给它)。这就是事件的特殊性 – 当事件发生时,子例程会自动被调用。在这个例子中,每次用户在 GraphicsWindow 上点击鼠标时子例程 OnMouseDown 都会被调用。让我们继续,运行并使用这个程序。任何时间当您在 GraphicsWindow 上点击鼠标时您都将看到如下面所示的对话框。
图 55 – 对事件的反应
这种事件处理是非常强大的,它支持非常有创造性和有意思的程序。使用这种方式编写的程序通常被成为事件驱动(event-driven)的程序。
您可以修改子例程OnMouseDown 实现比弹出一个对话框更多的事情。例如像下面的程序,您可以在用户点击鼠标的地方绘制大蓝点。
GraphicsWindow.BrushColor = "Blue"
GraphicsWindow.MouseDown = OnMouseDown
Sub OnMouseDown
x = GraphicsWindow.MouseX - 10
y = GraphicsWindow.MouseY - 10
GraphicsWindow.FillEllipse(x, y, 20, 20)
EndSub
图 56 – 处理鼠标点击事件
请注意在上面程序中,我们使用MouseX 和MouseY 来取得鼠标的坐标位置。然后我们用鼠标坐标点作为圆心绘制一个圆。
您想处理多少事件是没有限制的。您甚至可以使用一个子例程来处理多个事件。但是,您每次只能处理一个事件。如果您试图指派两个子例程给同一个事件,只有后面的子例程会起作用。
为了说明这一点,让我们使用前边的示例并添加一个处理键盘按键的子例程。同时,我们让新的子例程改变笔刷的颜色,这样当您点击鼠标时您将看到不同颜色的点。
GraphicsWindow.BrushColor = "Blue"
GraphicsWindow.MouseDown = OnMouseDown
GraphicsWindow.KeyDown = OnKeyDown
Sub OnKeyDown
GraphicsWindow.BrushColor = GraphicsWindow.GetRandomColor()
EndSub
Sub OnMouseDown
x = GraphicsWindow.MouseX - 10
y = GraphicsWindow.MouseY - 10
GraphicsWindow.FillEllipse(x, y, 20, 20)
EndSub
图 57 – 处理多个事件
原来当您运行程序并在窗口中点击时,您将看到蓝色的点。现在,如果您按键盘上的任意键然后再点击鼠标,您将看到不同颜色的点。当您按下键盘上的键时子例程 OnKeyDown(按下键盘按键)被执行,它将笔刷的颜色改为随机颜色。然后您再点击鼠标时,您就会看到一个使用新设置的颜色(随机产生的颜色)的圆点。
由于事件和子例程的帮助,我们现在可以编写让用户在窗口中绘图的程序了。只要我们把问题分解为较小的模块,编写这样一个程序就变得简单得令人吃惊了。第一步,我们写一个允许用户在图形窗口任意移动鼠标的程序,鼠标走过的地方会留下一道轨迹。
GraphicsWindow.MouseMove = OnMouseMove
Sub OnMouseMove
x = GraphicsWindow.MouseX
y = GraphicsWindow.MouseY
GraphicsWindow.DrawLine(prevX, prevY, x, y)
prevX = x
prevY = y
EndSub
不过,当您运行这个程序时,第一道轨迹总是从窗口的左上角即(0, 0) 开始。我们可以通过处理MouseDown 事件并捕捉当事件发生时的 prevX 和 prevY 值来修复这个问题。
同时,我们只需要把用户按下鼠标时的轨迹记录下来。在其他时间我们不必绘制轨迹线。为了实现这样的行为,我们将使用 Mouse(鼠标)对象的 IsLeftButtonDown(鼠标左键按下)属性。该属性告诉我们鼠标左键是否被按下。如果这个值为 true(真),我们就画轨迹线,否则就不画。
GraphicsWindow.MouseMove = OnMouseMove
GraphicsWindow.MouseDown = OnMouseDown
Sub OnMouseDown
prevX = GraphicsWindow.MouseX
prevY = GraphicsWindow.MouseY
EndSub
Sub OnMouseMove
x = GraphicsWindow.MouseX
y = GraphicsWindow.MouseY
If (Mouse.IsLeftButtonDown) Then
GraphicsWindow.DrawLine(prevX, prevY, x, y)
EndIf
prevX = x
prevY = y
EndSub
伺服电机(servo motor )是指在伺服系统中控制机械元件运转的发动机,是一种补助马达间接变速装置。
在编程时我们经常遇到需要重复执行相同一组步骤的情况。这种情况下,多次重写相同的语句是不合理的。这时我们需要借助子例程。
Small Basic 语言中也引入了 Turtle (龟标)对象,编程人员可以通过Small Basic 自带的很多命令调用这个对象。
在这一章节中,我们将运用前面学到的知识来做一些有趣的事。
Small Basic 还有一组强大的图形功能。