从 Zip/三件事编程 Gambas
本节中的代码是 Gambas。上一节是伪代码。
计算机可以做三件事:内存、重复和条件执行。重复是像处理数百万个数字或数千条记录一样一遍又一遍地做事。条件执行意味着做出选择。
计算器有时有 M+ 和 MR 键。当您按下 M+ 时,显示的任何数字都会进入内存。每当您需要再次使用该数字时,为了避免重新输入,请按下内存召回按钮,MR。内存就像您给自己做的一个便条,提醒您记住这个数字。
计算机拥有您喜欢的任意数量的内存,您可以为它们命名。将东西放入内存就像输入Age = 23一样简单。右侧的内容将放入左侧的内存中。要查看名为Age的内存中的内容,请将其打印出来或将其放到您可以看到的地方。Label1.text = "您的年龄是" & Age。
在您使用某些名称作为内存之前,您必须告诉 Gambas 将存储在其中的内容的类型。这就是DIM语句的作用。您在使用它之前声明它。例如,Dim Age As Integer 或 Dim 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%" | 空值 |
变体
|
任何数据类型。它必须在使用之前转换为某种类型。 | 空值 |
有六个标签,三个文本框和一个按钮。标签的名称无关紧要,但文本框和按钮的名称应如所示。该程序是
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 无法获得那个的 Val( )。
tbKilometres.text 是Null。我们应该预料到有人可能会在不输入任何数字的情况下点击按钮。这里有两种方法来处理这种情况,第二种方法更好,因为“预防胜于治疗”
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 事件?tbKilometres 和 tbHours 都检查是否有数字,并相应地启用或禁用按钮。如果这两个文本框都像一个文本框一样,那不是很好吗?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 之间想一个数字。您尝试用尽可能少的猜测来找出这个数字。每次都会告诉你“太高了!”或“太低了!”。
有三个标签和一个文本框。上面写着“猜...”的大标签名为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.Enter和Key.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类的属性和常量
常量返回整数。属性是输入的内容。因此,您可以通过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…。
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]什么是&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]单击“+插入”。将此菜单命名为MenuFile,并将标题设置为File。标题是用户看到的内容。名称是我们用于在编程中引用菜单的方式。
再次单击“+插入”。我们希望它成为File菜单的一部分,因此请单击工具栏上的向右推按钮。趁此机会,为菜单设置快捷键CTRL-Q。
现在编写一个处理程序,用于处理用户单击MenuQuit时的事件。(要执行此操作,请在表单中找到File菜单并单击它,然后单击菜单项Quit。)
Public Sub MenuQuit_Click()
Quit
End
代码的重复部分称为循环。有几种不同的重复方式。
Gambas 帮助列表在 http://Gambaswiki.org/wiki/cat/loop
计数固定次数
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
'do something
Until x > 50
While x < 50
'do something
Wend
要退出循环,用 BREAK。要退出子程序,用 RETURN。要进行下一个重复,用 CONTINUE。
还有无限循环 DO ... LOOP,以及用于编号列表中项目的 FOR EACH ... NEXT。
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 将进度延迟千分之一秒。此延迟允许重新绘制按钮。X 和 Y 通常用于表示 横向 和 纵向。按钮从左到右移动,然后再返回,所以我们需要改变的是 Button1 的 X。按钮一直向右移动,直到它的左边加上它的宽度等于窗体的宽度。换句话说,当按钮的右边到达窗体的右边时,它停止向右移动。在那之后,我们开始从 X 中减去,直到它到达窗体的左边。尝试在按钮移动时改变窗口的大小:按钮仍然会移动到边缘。
键入任意数字,每个数字用 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> 将在垂直列表中显示编号。
此程序在你键入 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