跳轉到內容

從壓縮包程式設計 Gambas/表單排列

來自 Wikibooks,開放世界中的開放書籍

使控制元件在表單調整大小後擴充套件

[編輯 | 編輯原始碼]

GridView 和 TableView 通常在包含它們的視窗調整大小後進行拉伸和收縮。表單(即視窗)知道如何調整大小並排列其包含的控制元件。即使在表單開啟時,任何可以排列和擴充套件的控制元件都會被擴充套件。

建立一個帶有一個 TableView 的小型表單。

Gambas form with vertical arrangement Gambas form with vertical arrangement and panels, running


將表單的 *arrangement* 屬性設定為 Vertical。將 tableview 的 *expand* 屬性設定為 True。執行程式 (f5)。更改視窗大小,並注意 tableview 的大小如何隨之變化。

將表單的 *padding* 屬性調整為 8。再次執行程式 (F5)。TableView 和表單邊緣之間的空間增加了。表單內部的邊距即為填充。表格單元格也具有填充。

在 tableview 下方新增一個按鈕。再次執行程式。將按鈕移動到 tableview 的一側。再次執行程式。將 arrangement 屬性更改為 Horizontal 並再次嘗試。將其更改回 Vertical。

刪除按鈕。新增一個 HBox。在 HBox 中新增一個按鈕。(或者,右鍵單擊按鈕並選擇“*嵌入到容器中*”,然後右鍵單擊容器(它是一個面板)並*更改為...* HBox。)

HBox 中的控制元件水平排列。

彈簧將按鈕儘可能地推到右邊。嘗試使用和不使用彈簧。

如果你使按鈕變寬或變窄,它將保持你在 HBox 中給定的寬度。

按鈕垂直擴充套件以從上到下填充 HBox。更改 HBox 的高度並觀察。HBox 擴充套件其控制元件以填充其高度。在面板中,按鈕保持相同的高度,但你不能使用彈簧。

用於平均學生成績的電子表格

[編輯 | 編輯原始碼]

Tall Gambas form to average student marks Gambas program to average student marks, running

*tv1* 是一個 TableView。它的 *expand* 屬性設定為 True。

底部是一個 HBox。從左到右,裡面是一個標籤 *labC*、一個粗體標籤 *labAverage*、一個彈簧和一個名為 *bQuit* 的退出按鈕,其文字屬性為“退出”。

每輸入一個數字,就會重新計算平均值。空白單元格會被跳過。

*LabC* 顯示計數,*labAverage* 顯示平均值。

Public Names As New String[]
Public Scores As New Float[]

Public Sub bQuit_Click()
  Quit
End

Public Sub Form_Open()

  Names = ["Mereka AIKE", "Ernest AIRI", "John AME", "Stanley ANTHONY", "Natasha AUA", "Veronica AUFA", "John Taylor BUNA", "Romrick CLEMENT", "Philomena GAVIA", "Richard GHAM"]
  tv1.Rows.Count = Names.count
  Scores.Resize(Names.Count)
  tv1.Columns.Count = 2
  tv1.Columns[1].Alignment = Align.Right

End

Public Sub CalculateAverage()

  Dim i, n As Integer
  Dim t As Float

  For i = 0 To Scores.Max
    If Scores[i] = -1 Or IsNull(tv1[i, 1].text) Then Continue 'skip new but unfilled-in lines
    n += 1 'number of scores
    t += Scores[i] 'total
  Next
  If n = 0 Then Return
  labC.Text = "N= " & n
  labAverage.Text = "Avg= " & Format(t / n, "#0.00")

End

Public Sub tv1_Click()
  If tv1.Column = 1 Then tv1.Edit 'numbers column is editable; Enter goes down
End

Public Sub tv1_Activate() 'double-clicked a cell
  If tv1.Column = 0 Then tv1.Edit 'edit a name
End

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

  tv1[Row, Column].text = Value
  If Column = 1 Then
    Scores[Row] = Value
    CalculateAverage
  Else
    Names[Row] = Value
  Endif

End

Public Sub tv1_Data(Row As Integer, Column As Integer)

  If Column = 0 Then tv1[row, 0].text = Names[Row]
  If Row Mod 2 = 0 Then tv1[Row, Column].Background = &hDDDDFF 'light blue
  tv1.Columns[0].Width = -1 'Automatically set width based on contents

End

Public Sub tv1_Insert()

  tv1.Rows.Count += 1
  Scores.Add(-1)
  Names.Add("")
  tv1.MoveTo(tv1.Rows.max, 0)
  tv1.Edit

End

一開始就建立了兩個公共陣列。*Names[]* 是一個學生姓名的列表。*Scores[]* 是他們的成績列表。它們匹配:第一個分數對應第一個姓名,第二個分數對應第二個姓名,依此類推。

*tv1_Data(Row As Integer, Column As Integer)* 事件在每次需要重繪單元格時觸發。它為你提供了 Row 和 Column。可以把它看作是繪製單元格。

*_DATA* 事件有一個特殊考慮因素:它不會繪製不需要繪製的單元格。這對於顯示大量行非常有用。如果有 100,000 行而你只顯示了 15 行,那麼只有這 15 行上的單元格才會觸發 *_DATA* 事件,而不是所有的十萬行。如果你使用 *_DATA* 事件將數字放入單元格,請注意!可能只有這 100,000 個單元格中的 15 個單元格中有資料。在這裡沒有問題,因為我們自己輸入數字,並且每次完成輸入一個新數字後,它都會在 *_SAVE* 事件中被放入單元格中。(*tv1[Row, Column].text = Valu**e**)。但是,當我們從資料庫中使用 **_***DATA* 事件放置值時,我們只會將資料放入我們看到的單元格中。然後我們必須記住對內部儲存的資料進行計算,而不是對單元格的顯示內容進行計算。為了養成良好的習慣,我使用 *DATA[ ]* 陣列來儲存分數,並在計算平均值時使用它。歸根結底是:*如果你確定所有資料都在單元格中,請使用它們;如果不是,請使用你確信有資料的地方。*

以下幾行建立了 TableView 的上下文選單,包含四個條目

Public Sub tv1_Menu()

  Dim mn, su As Menu 'main menu and submenu

  mn = New Menu(Me) 'brackets contain the parent, the main window
  su = New Menu(mn) As "MenuCopyTable" 'submenu of mn; alias is MenuCopyTable
  su.Text = "Copy table..." 'first submenu's text
  su = New Menu(mn) As "MenuCopyNames"
  su.Text = "Copy names..." 'second submenu's text
  su = New Menu(mn) As "MenuDeleteRow"
  su.Text = "Delete Row" 'third submenu's text
  su = New Menu(mn) As "MenuRefresh"
  su.Text = "Refresh" 'fourth submenu's text
  mn.Popup

End

Public Sub MenuDeleteRow_Click()

  Names.Remove(tv1.Row)
  Scores.Remove(tv1.Row)
  tv1.Rows.Remove(tv1.Row)

End

Public Sub MenuCopyTable_Click() 'clicked the Copy Table menu item

  Dim z As String

  For i As Integer = 0 To Names.Max
    If Scores[i] = -1 Then Continue
    z = If(IsNull(z), "", z & gb.NewLine) & Names[i] & gb.Tab & Scores[i]
  Next
  Clipboard.Copy(z)
  Message("Table copied")

End

Public Sub MenuCopyNames_Click() 'clicked the Copy Names menu item

  Dim z As String
  For i As Integer = 0 To Names.Max
    If IsNull(Names[i]) Then Continue
    z = If(IsNull(z), "", z & gb.NewLine) & Names[i]
  Next
  Clipboard.Copy(z)
  Message("Names copied")

End

Public Sub MenuRefresh_Click()
  tv1.Clear 'clear the data
  tv1.Rows.Count = Names.Count 'reset number of rows to match Names[ ]
  For i As Integer = 0 To Names.Max
    tv1[i, 0].Text = Names[i]
    tv1[i, 1].Text = Scores[i]
    If i Mod 2 = 0 Then
      tv1[i, 0].Background = &hFFDDFF
      tv1[i, 1].Background = &hFFDDFF
    Endif
  Next
End

*_Menu()* 事件屬於 *tv1*,即 TableView。當右鍵單擊該物件(以顯示選單)時,該事件就會觸發。*_Click()* 事件屬於 *TableviewMenu*。那是什麼?它是選單 *su* 所知的別名。別名讓人想起穿著黑色風衣的秘密人物,但它只是它所知的名稱。

**mn** 和 **su** 只在彈出選單的持續時間記憶體在,因為它們在 *_Menu()* 事件中。一旦你單擊彈出選單上的任何專案,該子程式就會結束,*mn* 和 *su* 就會消失。幸運的是,我們已經說過 *su* 也被稱為 *TableviewMenu*。選單本身,當它使用 *New* 建立時,就有了那個名字。因此,選單收到的任何點選都由 *TableviewMenu_Click()* 處理。

選單(無論是主選單、子選單還是選單項)都有多個事件、方法和屬性。有關詳細資訊,請檢視 Gambas 幫助

This suspicious character is known by an alias, as menus are.
這個可疑的字元有一個別名,就像選單一樣。

Methods and Events for Menus

你可以告訴選單關閉、隱藏、彈出、顯示或刪除。

你可以告訴程式在單擊選單時、隱藏後或顯示之前執行操作。通常,在單擊選單時,選單就會開始工作。

Gambas Menu Properties

一些屬性是布林值(例如 *enabled*、*checked* 和 *visible*),另一些屬性是字串(例如 *text*、*name*)、圖片(*picture*)或變體(即任何型別,*tag*)。

</syntaxhighlight>

從壓縮包程式設計 Gambas
 ← 文字檔案 表單排列 上下文選單 → 
華夏公益教科書