跳转到内容

从 Zip/三件事编程 Gambas

来自 Wikibooks,开放世界中的开放书籍

计算机可以做什么

[编辑 | 编辑源代码]

本节中的代码是 Gambas。上一节是伪代码。

计算机可以做三件事:内存重复条件执行。重复是像处理数百万个数字或数千条记录一样一遍又一遍地做事。条件执行意味着做出选择。

计算器有时有 M+ 和 MR 键。当您按下 M+ 时,显示的任何数字都会进入内存。每当您需要再次使用该数字时,为了避免重新输入,请按下内存召回按钮,MR。内存就像您给自己做的一个便条,提醒您记住这个数字。

计算机拥有您喜欢的任意数量的内存,您可以为它们命名。将东西放入内存就像输入Age = 23一样简单。右侧的内容将放入左侧的内存中。要查看名为Age的内存中的内容,请将其打印出来或将其放到您可以看到的地方。Label1.text = "您的年龄是" & Age

在您使用某些名称作为内存之前,您必须告诉 Gambas 将存储在其中的内容的类型。这就是DIM语句的作用。您在使用它之前声明它。例如,Dim Age As IntegerDim FirstName as String。如果内存与某个东西相关联,它们被称为变量属性

您可以在一行中声明内存并将内容放入内存中

Dim FirstName as String = "Michael"

您可以使用内存来计算某些内容,并将答案放入另一个内存中

Dim Speed as float = 45
Dim Time as float = 1.5
Dim Distance as Float = Speed * Time
Label1.text = Format(Distance, "##0.##") & "km/hr"

DIMension 东西,您需要知道允许的类型。这是一份数据类型列表

姓名 描述 例子 默认值
布尔值 真或假 1 = 2
整数 从 -2147483648 ... +2147483647 的整数 123 0
浮点数 带小数部分的数字,如 2.34 2.34 0.0
日期 日期和时间,每个都存储在一个整数中。 空值
字符串 字母、数字和符号串在一起。文本。 "ABC 12%" 空值
变体 任何数据类型。它必须在使用之前转换为某种类型。 空值

从距离和时间计算速度

[编辑 | 编辑源代码]

Speed Calculator Form Speed Calculator, running

有六个标签,三个文本框和一个按钮。标签的名称无关紧要,但文本框和按钮的名称应如所示。该程序是

Public Sub bCalculate_Click()
  tbSpeed.text = Val(tbKilometres.text) / Val(tbHours.text)
End

“Val”接受字符串并将其转换为数字。它的意思是“的值”。它可以这样写,使用变量,但这将需要更多行

Public Sub bCalculate_Click()
  Dim d As Float = Val(tbKilometres.text)
  Dim t As Float = Val(tbHours.text)
  Dim s As Float = d / t
  tbSpeed.text = s
End

如果您想为变量赋予更好的名称,

Public Sub bCalculate_Click()
  Dim distance, time, speed As Float
  distance = Val(tbKilometres.text)
  time = Val(tbHours.text)
  speed = distance /  time
  tbSpeed.text = speed
End

您可以编写一个接受距离和时间并返回速度的函数。教计算机做事是件好事。在这里,我们已经教会了计算机,Speed(5,2) 是 2.5。我们的计算按钮使用它。我们可能有一个也使用它的菜单项。

Public Sub bCalculate_Click()
  tbSpeed.text = Speed(Val(tbKilometres.text), Val(tbHours.text))
End

Public Sub Speed(d As Float, t As Float) As Float  
  Return d / t  
End

现在让我们欺骗我们的程序。不要为距离或时间输入任何内容。只需点击“计算”按钮。可怜的家伙无法应对。我们得到这个错误

Gambas Error Message

问题出现在极端情况下。在重复的节段中,它们最有可能出现在第一次或最后一次重复中。这里有一个极端的输入:什么都没有,零,空。Gambas 无法获得那个的 Val( )。

tbKilometres.textNull。我们应该预料到有人可能会在不输入任何数字的情况下点击按钮。这里有两种方法来处理这种情况,第二种方法更好,因为“预防胜于治疗”

1. 提前结束(从子程序中提前返回)

Public Sub bCalculate_Click()
   Dim d, t, s As Float
  If IsNull(Val(tbKilometres.text)) Then
    Message("Hey, you there! Give me a NUMBER for the kilometres.")
    Return
    Else
      d = Val(tbKilometres.text)
  Endif
  If IsNull(Val(tbHours.text)) Then
    Message("A number would be nice for the hours. Please try again.")
    Return
    Else
      t = Val(tbHours.text)
  Endif
  s = d / t
  tbSpeed.text = s 'To round to 2 decimal places, change s to format(s,"#.00")
End

2. 只有在计算能够继续进行时才启用按钮。将按钮的 Enabled 属性设置为 False,作为开始。我们需要处理一些事件。

Public Sub bCalculate_Click()
  tbSpeed.text = Val(tbKilometres.text) / Val(tbHours.text) 
  Fmain.SetFocus 'otherwise the button stays highlighted; focus the form
End

Public Sub tbKilometres_Change()
  CheckBothAreNumbers
End

Public Sub tbHours_Change()
  CheckBothAreNumbers
End

Public Sub CheckBothAreNumbers()
  bCalculate.Enabled = Not IsNull(Val(tbKilometres.text)) And Not  IsNull(Val(tbHours.text))
End

bCalculate.Enabled = 表示“将按钮的 Enabled 属性设置为...”

Not IsNull(Val(tbKilometres.text)) 表示如果公里文本框中的文本可以转换为数字,则为

每个文本框都有一个 Change 事件。它在框中的文本发生更改时触发。每次您按下某个键时,该 Change 事件都会查看是否该启用 bCalculate 按钮。

因为我不能让事情顺利进行,我为引入“Group”属性表示歉意。您可能需要咖啡。或者跳过本节。您是否注意到这两个文本框必须以相同的方式分别处理 Change 事件?tbKilometrestbHours 都检查是否有数字,并相应地启用或禁用按钮。如果这两个文本框都像一个文本框一样,那不是很好吗?Gambas 可以做到这一点。将它们放在一个Group中。然后,这个单一的组将有一个Change事件,您可以只处理一次。Group 是一个属性。找到每个的 Group 属性并将其设置为“InputBox”。现在您的代码变得最简单

Public Sub bCalculate_Click()
  tbSpeed.text = Val(tbKilometres.text) / Val(tbHours.text) 
  Fmain.SetFocus 'otherwise the button stays highlighted; focus the form
End

Public Sub InputBox_Change()
  CheckBothAreNumbers
End

Public Sub CheckBothAreNumbers()
  bCalculate.Enabled = Not IsNull(Val(tbKilometres.text)) And Not IsNull(Val(tbHours.text))
End

就好像这两个文本框变成了输入框(您刚发明的名称),具有相同的事件。一组用于多个对象的事件处理程序。

它很健壮(能够抵抗那些坚持不按您期望的方式使用您的应用程序的用户)。它很简洁(3 个事件处理程序,4 行代码)。它有效。只有一件事:一个写着 QUIT 的按钮,它的 Click 事件中只有一件事:Quit 命令。交给你了。

条件执行

[编辑 | 编辑源代码]

如果..那么..否则 — 高低游戏

[编辑 | 编辑源代码]

这个游戏很容易玩:一个人在 1 到 100 之间想一个数字。您尝试用尽可能少的猜测来找出这个数字。每次都会告诉你“太高了!”或“太低了!”。

HiLo Window HiLo Game, running

有三个标签和一个文本框。上面写着“猜...”的大标签名为labMyReply。文本框名为tbGuess。左下角的小标签名为labCount

Public MyNumber As Integer

Public Sub Form_Open()
  MyNumber = Rand(1, 100)
End

Public Sub tbGuess_KeyPress()
  If Key.Code = Key.Enter Or Key.Code = Key.Return Then GiveMessage
End

Public Sub GiveMessage()

  If IsNull(tbGuess.text) Then 'no guess at all
    labMyReply.text = "Guess..."
    Return
  Endif

  Dim YourGuess As Integer = Val(tbGuess.text)

  If MyNumber = YourGuess Then
    labMyReply.Text = "Right! " & MyNumber
    MyNumber = Rand(1, 100)
    tbGuess.text = ""
    FMain.Background = Color.Green
    labCount.text = "0"
    Return
  Endif

  If YourGuess > MyNumber Then labMyReply.Text = "Too High!" Else labMyReply.Text = "Too Low!"
  tbGuess.text = ""
  FMain.Background = Color.Pink
  labCount.text = Val(labCount.text) + 1

End

该程序在文本框中按下 ENTER 或 RETURN 时检查猜测。Key 类是静态的,这意味着它始终存在——您不必声明或创建它。如果您需要检查某个键(例如 SHIFT-C)是否被按下,您将编写

If Key.SHIFT And Key.Text = "C" Then
    GiveMessage
    Stop Event
  Endif

Stop Event 行是为了防止大写 C 被打印在文本框中,这在您在文本框中输入 Shift-C 时通常会发生。

Public MyNumber As Integer 表示我们要一个名为MyNumber的公共属性。您可以说 Private 而不是 public。私有属性只能在属于该表单的代码中访问。如果我们有其他表单(即窗口),它们看不到另一个表单的私有属性。将属性声明为private 是一种告诉您(程序员)的方式,您只在您正在查看的此表单的代码中使用了此属性。此外,另一个表单可以有它自己的属性并使用相同的名称。

Event Form_Open()事件处理程序中,Rand(1,100)是一个内置函数,表示1到100之间的随机数。

Event tbGuess_KeyPress()事件处理程序中,刚刚输入的键与Enter键和Return键进行比较。如果它其中之一,则检查猜测。每个键都有一个数字。Enter是16777221,Return是16777220。我们不需要知道这些数字,因为它们存储在Key.EnterKey.Return中。这些是Key类中的常量。因为Key类是静态的,所以我们不必创建它的新实例:它始终存在,我们可以通过其名称引用它。我们永远不需要另一个实例。键盘只有一个。我们永远不必说“ACER笔记本电脑键盘的Key”或“在HP笔记本电脑键盘上输入的Key”。

If IsNull(tbGuess.text) Then … End避免了用户在没有任何数字的情况下按Enter键的糟糕情况。

Dim YourGuess As Integer = Val(tbGuess.text)将输入内容的数值放入名为YourGuess的变量中。这是一个整数。如果用户输入了34.56,则只有34会被放入YourGuess中。

If MyNumber = YourGuess Then…检查YourGuess是否与MyNumber匹配。如果是,则显示“正确!”消息并使表单的背景颜色变为绿色。选择另一个随机数以备下次游戏,然后Return,因为不需要再做其他操作。

If YourGuess > MyNumber Then labMyReply.Text = "太高了!" Else labMyReply.Text = "太低了!"将相应的消息放入labMyReply文本框中。这是一个单行If...Then...Else语句。无论哪种情况,都会继续使背景变成粉红色。

从Gambas帮助页面中,这些是Key类的属性和常量

Screenshot of Links on a Gambas help page
Gambas帮助页面上的链接截图

常量返回整数。属性是输入的内容。因此,您可以通过if Key.Code = Key.PgDown then…来检查用户是否输入了PgDown键。浏览和阅读帮助页面本身就是一项技能。

Select … Case … — 多种选择

[edit | edit source]
评分学生成绩
[edit | edit source]

让我们将数字输入TableView并使其计算出每个学生是否获得了A、B、C、D、E或F等级。我们需要两列。第一列用于分数,第二列用于等级。

目前我们将跳过为学生姓名添加一列。为了避免使用许多IF...THEN...语句,我们将使用它的“兄长”SELECT...CASE…
GambasPic120 GambasPic123

TableView的名称是tvMarks。文本框的名称是tbRows。双击表单的空白部分,输入表单的open事件的代码。

Public Sub Form_Open()
  tvMarks.Columns.count = 2
End

双击文本框并输入

Public Sub tbRows_KeyPress()
  If Key.Code = Key.Return Or Key.Code = Key.Enter Then tvMarks.Rows.Count =  Val(tbRows.Text)
End

右键单击TableView > 事件 > 点击,然后右键单击 > 事件 > 保存,并输入以下内容

Public Sub tvMarks_Click()
    If tvMarks.Column = 0 Then tvMarks.Edit
End

Public Sub tvMarks_Save(Row As Integer, Column As Integer, Value As String)
  tvMarks[Row, Column].Text = Value
  Dim x As Float = Val(Value)
  Select Case x
    Case 90 To 100
        tvMarks[Row, 1].Text = "A"
    Case 80 To 89
        tvMarks[Row, 1].Text = "B"
    Case 70 To 79
        tvMarks[Row, 1].Text = "C"
    Case 60 To 69
        tvMarks[Row, 1].Text = "D"
    Case 50 To 59
        tvMarks[Row, 1].Text = "E"
    Case Else
        tvMarks[Row, 1].Text = "F"
  End Select
End

tvMarks_Click()处理程序允许您在列为0时在单元格中输入内容。如果单击列1,则您将无法输入内容:单击时不会发生任何事情。

您可能会认为您在单元格中输入的任何内容都应该显示出来。但事实并非如此。它会引发Save事件。您可能希望显示的内容与输入的内容不同。在Save事件期间,将输入的文本实际放入单元格的text属性中。

tvMarks[Row, Column].Text = Value

Save事件带三个参数,您可以在事件处理程序过程中自由使用:tvMarks_Save(Row As Integer, Column As Integer, Value As String)。这行代码将输入的值放入单元格的文本中。哪个单元格?tvMarks[row, column]。这就是单元格。

您可以使用方括号引用单元格:tvMarks[1,0]指的是第1行第0列。(请记住,行和列从零开始编号。)tvMarks.Rows[2]是第2行。tvMarks.Columns[1]是整个第1列。

一个不错的补充 - 交替着色行
[edit | edit source]

TableView_Data()事件非常有用。它会在每次需要在屏幕上重新绘制单元格时引发(发生)。(请记住,它处理的是单元格,而不是行或列或整个表格。)右键单击TableView,然后 > 事件 > 数据,并输入以下内容

Public Sub tvMarks_Data(Row As Integer, Column As Integer)
        If Row Mod 2 = 0 Then tvMarks[Row, Column].Background = &F0F0FF
End

这将使交替行显示浅蓝色(非常漂亮)。解释一下,单元格有一个名为“background”的属性。它是一种颜色。可以使用多种方式描述颜色:使用直接数字是最简单的。数字是&F0F0FF。

颜色编号

[edit | edit source]
LCD Screen Closeup
计算机屏幕上充满了发光的红色、绿色和蓝色的灯。

什么是&F0F0FF这样的数字?“&”符号表示数字是用十六进制表示的。通常我们使用十进制系统,它是10进制。您从零计数到九,然后数字回到零,并将左侧数字增加一。以下是10进制的正常计数:0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,16… 使用十六进制,您有16个数字,而不是十个。以下是16进制的计数:0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C, 1D, 1E, 1F, 20, 21… 十进制系统中的第十一个数字写为11。十六进制系统中的第十一个数字写为B

现在,&F0F0FF是什么颜色?十六进制数字F0F0FF实际上是三个两位数:F0、F0、FF。第一个数字表示多少红色。第二个数字表示多少绿色。第三个数字表示多少蓝色。这就是RGB,即红绿蓝。每个数字从00到FF。第一个位置的00表示“完全没有红色”。第一个位置的FF表示“最大红色!”。纯红色是&FF0000。纯绿色是&00FF00,纯蓝色是&0000FF。因此,纯黑色是&000000。纯白色是&FFFFFF,即所有颜色都尽可能明亮。

这种颜色是灰色:&F0F0F0。红色、绿色和蓝色的灯光大部分都亮着,但没有完全亮。F0不如FF亮。要获得更深的灰色,请降低数字,但要同时降低所有数字,例如,C0C0C0。再深一些,B0B0B0。比这稍微深一点的是AFAFAF,因为AF之后是B0。重点是,当所有数字都相同时,您将获得灰色阴影。因此,请查看F0F0FF。它是一种非常浅的灰色(F0F0F0),但最后一个数字(用于蓝色)稍微亮一点。它是FF。因此,这种颜色是一种非常浅的灰色,只是蓝色稍微亮一点。也就是说,它是一种非常浅的蓝色。它完全取决于三种颜色的混合,即红色、绿色和蓝色。这是淡粉色:FFD0D0。这是淡绿色:D0FFD0。这是淡黄色:FFFFD0。(红色=最亮,绿色=最亮,蓝色=稍微暗一些)。这是满黄色:FFFF00。

这完全取决于您屏幕上的微型LED灯。它们有数百万个,但它们以三个一组排列 - 一个红色、一个绿色和一个蓝色。您可以控制每个微型灯的亮度。亮度范围从00到FF,或者用十进制表示,从0到255。(FF=255)。一个红色、一个绿色和一个蓝色就像一个彩色点。它被称为像素。典型的笔记本电脑屏幕的分辨率为1366 x 768像素。即1,049,088个像素。每个像素都有三个微型LED灯,总共有3,147,264个灯光在您的屏幕上,每个灯光有256个亮度等级。太神奇了!

添加退出菜单
[edit | edit source]

Section of Gambas IDE

Adding a File Menu in Gambas IDE
添加文件菜单

单击“+插入”。将此菜单命名为MenuFile,并将标题设置为File。标题是用户看到的内容。名称是我们用于在编程中引用菜单的方式。

再次单击“+插入”。我们希望它成为File菜单的一部分,因此请单击工具栏上的向右推按钮。趁此机会,为菜单设置快捷键CTRL-Q。

Gambas Menu Editor
添加退出菜单项
添加Ctrl-Q作为键盘快捷键

现在编写一个处理程序,用于处理用户单击MenuQuit时的事件。(要执行此操作,请在表单中找到File菜单并单击它,然后单击菜单项Quit。)

Public Sub MenuQuit_Click()
  Quit
End

代码的重复部分称为循环。有几种不同的重复方式。

Gambas 帮助列表在 http://Gambaswiki.org/wiki/cat/loop

计数固定次数

For … Next

[编辑 | 编辑源代码]
For i as integer = 1 to 5
        'do something
Next

i 是一个整数,计数 1、2、3、4、5。如果你已经有了 DIM i As Integer,不要放“as integer”。

你可以在循环中使用 i,但不要改变它的值。NEXT 这个词会把它加 1,并将计算机送回开头(FOR 行),在那里 i 会被检查是否大于 5。如果它大于 5,就会去 NEXT 后的那行。

Repeat … Until

[编辑 | 编辑源代码]
Repeat
        'do something
Until x > 50

While ... Wend

[编辑 | 编辑源代码]
While x < 50
        'do something
Wend

要退出循环,用 BREAK。要退出子程序,用 RETURN。要进行下一个重复,用 CONTINUE

还有无限循环 DO ... LOOP,以及用于编号列表中项目的 FOR EACH ... NEXT

移动按钮

[编辑 | 编辑源代码]

Moving Button form

Public Sub Button1_Click()

  Do
    Repeat 'move to the right
      Button1.x += 1
      Wait 0.001
    Until Button1.x + Button1.w = FMain.Width

    Repeat 'move to the left
      Button1.x -= 1
      Wait 0.001
    Until Button1.x = 0
  Loop

End

Public Sub Form_KeyPress()
  Quit
End

当你按下键盘上的一个键时,程序结束。Wait 0.001 将进度延迟千分之一秒。此延迟允许重新绘制按钮。XY 通常用于表示 横向纵向。按钮从左到右移动,然后再返回,所以我们需要改变的是 Button1 的 X。按钮一直向右移动,直到它的左边加上它的宽度等于窗体的宽度。换句话说,当按钮的右边到达窗体的右边时,它停止向右移动。在那之后,我们开始从 X 中减去,直到它到达窗体的左边。尝试在按钮移动时改变窗口的大小:按钮仍然会移动到边缘。

一个将 5 个数字加起来的 Tableview

[编辑 | 编辑源代码]

Tableview on a tall form Tableview to add up 5 numbers

键入任意数字,每个数字用 Enter 键结束,以进入下一行。当你按下 Enter 键时,总计会更新。

Public Sub Form_Open()
  tv1.Rows.Count = 6
  tv1.Columns.Count = 1
End

Public Sub tv1_Save(Row As Integer, Column As Integer, Value As String)

  Dim t As Integer
  tv1[Row, Column].Text = Value
  For i As Integer = 0 To 4
    If IsNull(tv1[i, 0].text) Then Continue
    If Not IsNumber(tv1[i, 0].text) Then Continue
    t += Val(tv1[i, 0].text)
  Next
 
  tv1[5, 0].Background = Color.LightGray
  tv1[5, 0].Foreground = Color.Blue
  tv1[5, 0].RichText = "<b>" & t & "</b>" 'tv1[5, 0].text = t

End

Public Sub tv1_Click()
  If tv1.Row < 5 Then tv1.Edit
End

注意总计单元格是如何在浅灰色上显示蓝色,以及文本是如何加粗的。"<b>" & t & "</b>" 是总计两侧的标签。富文本是带有标签的文本。第一个标签是“打开加粗”,第二个标签带斜线,是“关闭加粗”。

当按下 Enter 键或 Return 键时,就会发生 Save 事件。将键入的数字放入带有 tv1[Row, Column].Text = Value 的单元格后,新的总计会放入单元格 tv1[5, 0] 的富文本中。

富文本标签

[编辑 | 编辑源代码]

Gambas 允许在富文本中使用这些标签。它们是 HTML超文本标记语言)的一部分,网页浏览器用它来显示网页。每个标签都会先打开,然后在末尾关闭,例如 "<b><i>这是加粗斜体</b></i>"

<h1>,<h2>, <h3>, <h4>, <h5>, <h6> →标题 <sup> 上标
<b> 加粗字体 <small> 小字体
<i> 斜体 <p> 段落
<s> 删除线 <br> 换行
<u> 下划线 <a> 链接
<sub> 下标 <font> 字体

字体标签的使用方式如下:"<Font Color=#B22222>" & "<Font Face=Candara>" & t & "</Font>"

段落标签表示段落,浏览器通常用空行将它们隔开。它可以使用这种方式:<p align=right>一些文本</p>,但在一个关于 HTML 的网页上,它说,“<p> 标签上的 align 属性已过时,不应该使用”。(https://mdn.org.cn/en-US/docs/Web/HTML/Element/p)。同时,它也能使用。

<tt> 单行源代码文本 <pre> 预格式化文本(保留空格)
<hr> 水平线(不需要结束标签) <ul> 无序列表
<li> 列表项 <ol> 列表

<ul><li>吉姆</li><li>约翰</li><li>安</li></ul> 将在垂直列表中显示项目符号。

<ol><li>吉姆</li><li>约翰</li><li>安</li></ol> 将在垂直列表中显示编号。

一个将表格中所有数字加起来的 Tableview

[编辑 | 编辑源代码]

Form showing a tableview Tableview on form, running

此程序在你键入 4 x 5 网格中的数字时将其加起来。

Public Sub Form_Open()
  tv1.Rows.Count = 5
  tv1.Columns.Count = 4
End

Public Sub tv1_Save(Row As Integer, Column As Integer, Value As String)
  Dim i, j, t As Integer
  tv1[Row, Column].Text = Value
  For i = 0 To tv1.Rows.Max
      For j = 0 To tv1.Columns.Max
          If IsNull(tv1[i, j].text) Then Continue
          If Not IsNumber(tv1[i, j].text) Then Continue
          t += Val(tv1[i, j].text)
      Next
  Next
  Label1.Text = t
End

Public Sub tv1_Click()
  tv1.Edit
End

循环嵌套在一起。它们的意思是“对于每一行,遍历所有的列”。

For i = 0 To tv1.Rows.Max 'for every row going down...
      For j = 0 To tv1.Columns.Max 'go across every column
         ...
      Next
Next
从 Zip 中编程 Gambas
 ← 语法 三件事 数组 → 
华夏公益教科书