原文: http://zetcode.com/tutorials/ironpythontutorial/advancedcontrols/

在 IronPython Mono Winforms 教程的这一部分中,我们介绍一些更高级的控件。 即ListBoxListViewTreeView控件。

ListBox

ListBox控件用于显示项目列表。 用户可以通过单击选择一个或多个项目。

listbox.py

  1. #!/usr/bin/ipy
  2. import clr
  3. clr.AddReference("System.Windows.Forms")
  4. clr.AddReference("System.Drawing")
  5. from System.Windows.Forms import Application, Form, StatusBar
  6. from System.Windows.Forms import ListBox, DockStyle
  7. from System.Drawing import Size
  8. class IForm(Form):
  9. def __init__(self):
  10. self.Text = "ListBox"
  11. lb = ListBox()
  12. lb.Parent = self
  13. lb.Items.Add("Jessica")
  14. lb.Items.Add("Rachel")
  15. lb.Items.Add("Angelina")
  16. lb.Items.Add("Amy")
  17. lb.Items.Add("Jennifer")
  18. lb.Items.Add("Scarlett")
  19. lb.Dock = DockStyle.Fill
  20. lb.SelectedIndexChanged += self.OnChanged
  21. self.sb = StatusBar()
  22. self.sb.Parent = self
  23. self.Size = Size(220, 220)
  24. self.CenterToScreen()
  25. def OnChanged(self, sender, event):
  26. self.sb.Text = sender.SelectedItem
  27. Application.Run(IForm())

我们的示例显示了一个具有六个名称的列表框。 所选项目显示在状态栏中。

  1. lb = ListBox()
  2. lb.Parent = self

ListBox控件已创建。

  1. lb.Items.Add("Jessica")

这就是我们向ListBox控件添加新项目的方式。 该控件具有Items属性。 该属性是对列表框中项目列表的引用。 使用此引用,我们可以添加,删除或获取列表框中的项目数。

  1. lb.SelectedIndexChanged += self.OnChanged

当我们选择一个项目时,会触发SelectedIndexChanged事件。

  1. def OnChanged(self, sender, event):
  2. self.sb.Text = sender.SelectedItem

OnChange()方法内,我们获得列表框的选定值并将其设置为状态栏。

Mono Winforms 中的高级控件 - 图1

图:ListBox

ListView

ListView控件用于显示项目集合。 它是比ListBox控件更复杂的控件。 它可以在各种视图中显示数据。 它主要用于在多列视图中显示数据。

listview.py

  1. #!/usr/bin/ipy
  2. import clr
  3. clr.AddReference("System.Windows.Forms")
  4. clr.AddReference("System.Drawing")
  5. from System.Windows.Forms import Application, Form, StatusBar
  6. from System.Windows.Forms import ListView, View, ColumnHeader
  7. from System.Windows.Forms import ListViewItem, DockStyle, SortOrder
  8. from System.Drawing import Size
  9. class IForm(Form):
  10. def __init__(self):
  11. self.Text = 'ListBox'
  12. actresses = { 'Jessica Alba' : '1981', 'Angelina Jolie' : '1975',
  13. 'Natalie Portman' : '1981', 'Rachel Weiss' : '1971',
  14. 'Scarlett Johansson' : 1984 }
  15. name = ColumnHeader()
  16. name.Text = 'Name'
  17. name.Width = -1
  18. year = ColumnHeader()
  19. year.Text = 'Year'
  20. self.SuspendLayout()
  21. lv = ListView()
  22. lv.Parent = self
  23. lv.FullRowSelect = True
  24. lv.GridLines = True
  25. lv.AllowColumnReorder = True
  26. lv.Sorting = SortOrder.Ascending
  27. lv.Columns.AddRange((name, year))
  28. lv.ColumnClick += self.OnColumnClick
  29. for act in actresses.keys():
  30. item = ListViewItem()
  31. item.Text = act
  32. item.SubItems.Add(str(actresses[act]))
  33. lv.Items.Add(item)
  34. lv.Dock = DockStyle.Fill
  35. lv.Click += self.OnChanged
  36. self.sb = StatusBar()
  37. self.sb.Parent = self
  38. lv.View = View.Details
  39. self.ResumeLayout()
  40. self.Size = Size(350, 300)
  41. self.CenterToScreen()
  42. def OnChanged(self, sender, event):
  43. name = sender.SelectedItems[0].SubItems[0].Text
  44. born = sender.SelectedItems[0].SubItems[1].Text
  45. self.sb.Text = name + ', ' + born
  46. def OnColumnClick(self, sender, event):
  47. if sender.Sorting == SortOrder.Ascending:
  48. sender.Sorting = SortOrder.Descending
  49. else:
  50. sender.Sorting = SortOrder.Ascending
  51. Application.Run(IForm())

在我们的示例中,我们有一个包含两列的列表视图。 在第一列中,我们显示女演员的名字。 在第二个他们的出生日期。 数据存储在List集合中。 通过选择一行,一行中的数据将显示在状态栏中。 另外,通过单击列标题,可以对数据进行排序。

  1. actresses = { 'Jessica Alba' : '1981', 'Angelina Jolie' : '1975',
  2. 'Natalie Portman' : '1981', 'Rachel Weiss' : '1971',
  3. 'Scarlett Johansson' : 1984 }

我们将数据存储在女演员词典中。

  1. name = ColumnHeader()
  2. name.Text = 'Name'
  3. name.Width = -1

对于列表视图中的每一列,我们创建一个ColumnHeader。 通过将Width设置为 -1,列的宽度等于列中最长的项目。

  1. lv = ListView()
  2. lv.Parent = self

ListView控件已创建。

  1. lv.FullRowSelect = True
  2. lv.GridLines = True
  3. lv.AllowColumnReorder = True
  4. lv.Sorting = SortOrder.Ascending

在这里,我们设置控件的四个属性。 该代码行支持全行选择,显示网格线,通过拖动列对列进行重新排序并以升序对数据进行排序。

  1. lv.Columns.AddRange((name, year))

在这里,我们将两个ColumnHeader添加到ListView控件中。

  1. for act in actresses.keys():
  2. item = ListViewItem()
  3. item.Text = act
  4. item.SubItems.Add(str(actresses[act]))
  5. lv.Items.Add(item)

此循环填充列表视图控件。 每行作为ListViewItem类添加到列表视图。

  1. lv.View = View.Details

ListView控件可以具有不同的视图。 不同的视图以不同的方式显示数据。

  1. name = sender.SelectedItems[0].SubItems[0].Text
  2. born = sender.SelectedItems[0].SubItems[1].Text
  3. self.sb.Text = name + ', ' + born

OnChanged()方法内部,我们从选定的行中获取数据并将其显示在状态栏上。

  1. if sender.Sorting == SortOrder.Ascending:
  2. sender.Sorting = SortOrder.Descending
  3. else:
  4. sender.Sorting = SortOrder.Ascending

在这里,我们切换列的排序顺序。

Mono Winforms 中的高级控件 - 图2

图:ListView

TreeView

TreeView控件显示项目的分层集合。 此控件中的每个项目都由TreeNode对象表示。

treeview.py

  1. #!/usr/bin/ipy
  2. import clr
  3. clr.AddReference("System.Windows.Forms")
  4. clr.AddReference("System.Drawing")
  5. from System.Windows.Forms import Application, Form, StatusBar
  6. from System.Windows.Forms import TreeView, TreeNode, DockStyle
  7. from System.Drawing import Size
  8. class IForm(Form):
  9. def __init__(self):
  10. self.Text = 'TreeView'
  11. tv = TreeView()
  12. root = TreeNode()
  13. root.Text = 'Languages'
  14. child1 = TreeNode()
  15. child1.Text = 'Python'
  16. child2 = TreeNode()
  17. child2.Text = 'Ruby'
  18. child3 = TreeNode()
  19. child3.Text = 'Java'
  20. root.Nodes.AddRange((child1, child2, child3))
  21. tv.Parent = self
  22. tv.Nodes.Add(root)
  23. tv.Dock = DockStyle.Fill
  24. tv.AfterSelect += self.AfterSelect
  25. self.sb = StatusBar()
  26. self.sb.Parent = self
  27. self.Size = Size(220, 220)
  28. self.CenterToScreen()
  29. def AfterSelect(self, sender, event):
  30. self.sb.Text = event.Node.Text
  31. Application.Run(IForm())

这是TreeView控件的非常简单的演示。 我们有一个根项目和三个子项。

  1. tv = TreeView()

我们创建TreeView控件。

  1. root = TreeNode()
  2. root.Text = 'Languages'
  3. ...
  4. tv.Nodes.Add(root)

在这里,我们创建一个根节点。

  1. child1 = TreeNode()
  2. child1.Text = 'Python'

子节点以类似的方式创建。

  1. root.Nodes.AddRange((child1, child2, child3))

子节点插入到根节点的Nodes属性中。

Mono Winforms 中的高级控件 - 图3

图:TreeView

目录

下面的代码示例将更深入地研究TreeView控件。

directories.py

  1. #!/usr/bin/ipy
  2. import clr
  3. clr.AddReference("System.Windows.Forms")
  4. clr.AddReference("System.Drawing")
  5. from System.Windows.Forms import Application, Form, StatusBar
  6. from System.Windows.Forms import Button, TreeView, TreeNode
  7. from System.Windows.Forms import DockStyle, AnchorStyles
  8. from System.Drawing import Size, Point
  9. from System.IO import Directory, DirectoryInfo
  10. HOME_DIR = '/home/vronskij'
  11. class IForm(Form):
  12. def __init__(self):
  13. self.Text = 'Directories'
  14. self.Size = Size(400, 400)
  15. self.tv = TreeView()
  16. self.SuspendLayout()
  17. self.tv.Parent = self
  18. self.tv.Location = Point(10,10)
  19. self.tv.Size = Size(self.ClientSize.Width - 20, self.Height - 200)
  20. self.tv.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right
  21. self.tv.FullRowSelect = False
  22. self.tv.ShowLines = True
  23. self.tv.ShowPlusMinus = True
  24. self.tv.Scrollable = True
  25. self.tv.AfterSelect += self.AfterSelect
  26. expand = Button()
  27. expand.Parent = self
  28. expand.Location = Point(20, self.tv.Bottom + 20)
  29. expand.Text = 'Expand'
  30. expand.Anchor = AnchorStyles.Left | AnchorStyles.Top
  31. expand.Click += self.OnExpand
  32. expandAll = Button()
  33. expandAll.Parent = self
  34. expandAll.Location = Point(20, expand.Bottom + 5)
  35. expandAll.Text = 'Expand All'
  36. expandAll.Anchor = AnchorStyles.Left | AnchorStyles.Top
  37. expandAll.Click += self.OnExpandAll
  38. collapse = Button()
  39. collapse.Parent = self
  40. collapse.Location = Point(expandAll.Right + 5, expand.Top)
  41. collapse.Text = 'Collapse'
  42. collapse.Anchor = AnchorStyles.Left | AnchorStyles.Top
  43. collapse.Click += self.OnCollapse
  44. collapseAll = Button()
  45. collapseAll.Parent = self
  46. collapseAll.Location = Point(collapse.Left, collapse.Bottom + 5)
  47. collapseAll.Text = 'Collapse All'
  48. collapseAll.Anchor = AnchorStyles.Left | AnchorStyles.Top
  49. collapseAll.Click += self.OnCollapseAll
  50. self.sb = StatusBar()
  51. self.sb.Parent = self
  52. self.ShowDirectories(self.tv.Nodes, HOME_DIR)
  53. self.ResumeLayout()
  54. self.CenterToScreen()
  55. def AfterSelect(self, sender, event):
  56. self.sb.Text = event.Node.Text
  57. def ShowDirectories(self, trvNode, path):
  58. dirInfo = DirectoryInfo(path)
  59. if (dirInfo != None):
  60. subDirs = dirInfo.GetDirectories()
  61. tr = TreeNode(dirInfo.Name)
  62. if (subDirs.Length > 0):
  63. for dr in subDirs:
  64. if not dr.Name.StartsWith("."):
  65. self.ShowDirectories(tr.Nodes, dr.FullName)
  66. trvNode.Add(tr)
  67. def OnExpand(self, sender, event):
  68. self.tv.SelectedNode.Expand()
  69. def OnExpandAll(self, sender, event):
  70. self.tv.ExpandAll()
  71. def OnCollapse(self, sender, event):
  72. self.tv.SelectedNode.Collapse()
  73. def OnCollapseAll(self, sender, event):
  74. self.tv.CollapseAll()
  75. Application.Run(IForm())

我们的代码示例在TreeView控件中显示指定主目录的目录。 该应用启动有些延迟,因为它首先读取主目录的目录结构。 表单上还有四个按钮。 这些按钮以编程方式展开和折叠节点。

  1. self.tv.Scrollable = True

我们使TreeView控件可滚动,因为该控件显示了大量目录。

  1. self.ShowDirectories(self.tv.Nodes, HOME_DIR)

ShowDirectories()方法使用指定主目录中可用的目录填充TreeView控件的节点。

  1. if (subDirs.Length > 0):
  2. ...

我们检查是否有任何子目录。

  1. for dr in subDirs:
  2. if not dr.Name.StartsWith("."):
  3. self.ShowDirectories(tr.Nodes, dr.FullName)

我们遍历所有目录。 为此,我们使用了递归算法。 我们还跳过隐藏的目录。 它们以 Unix 系统上的点开头。

  1. trvNode.Add(tr)

此代码行实际上将目录添加到TreeView控件。

  1. def OnExpand(self, sender, event):
  2. self.tv.SelectedNode.Expand()

所有四个按钮都将事件插入到方法中。 这是展开按钮的方法。 它调用当前所选节点的Expand()方法。

Mono Winforms 中的高级控件 - 图4

图:Directories

在 IronPython Mono Winforms 教程的这一部分中,我们介绍了 Winforms 编程库中提供的几个高级控件。