<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 第十章 創建和使用wxPython菜單 1. [創建和使用wxPython菜單](#A.2BUhte.2BlSMT391KA-wxPython.2Bg9xTVQ-) 1. [創建菜單](#A.2BUhte.2BoPcU1U-) 1. [如何創建一個菜單欄并把它附加到一個框架?](#A.2BWYJPVVIbXvpOAE4qg9xTVWgPXnZiiluDlkRSoFIwTgBOKmhGZ7b.2FHw-) 2. [如何創建一個菜單并把它附加到菜單欄?](#A.2BWYJPVVIbXvpOAE4qg9xTVV52Yopbg5ZEUqBSMIPcU1VoD.2F8f-) 3. [如何給下拉菜單填加項目?](#A.2BWYJPVX7ZTgtiyYPcU1VYa1KgmHl27v8f-) 4. [如何響應一個菜單事件?](#A.2BWYJPVVTNXpROAE4qg9xTVU6LTvb.2FHw-) 2. [使用菜單項工作](#A.2BT391KIPcU1WYeV3lT1w-) 1. [如何在一個菜單中找到一個特定的菜單項?](#A.2BWYJPVVcoTgBOKoPcU1VOLWJ.2BUjBOAE4qcnlbmnaEg9xTVZh5.2Fx8-) 2. [如何使一個菜單項有效或無效?](#A.2BWYJPVU9.2FTgBOKoPcU1WYeWcJZUhiFmXgZUj.2FHw-) 3. [如何將一個菜單項與一個快捷鍵關聯起來?](#A.2BWYJPVVwGTgBOKoPcU1WYeU4OTgBOKl.2FrY3eVLlFzgFSNd2dl.2Fx8-) 4. [如何創建一個復選或單選開關菜單項?](#A.2BWYJPVVIbXvpOAE4qWQ2QCWIWU1WQCV8AUXOD3FNVmHn.2FHw-) 3. [進一步構建菜單](#A.2Bj9tOAGtlZ4Re.2BoPcU1U-) 1. [如何創建一個子菜單?](#A.2BWYJPVVIbXvpOAE4qW1CD3FNV.2Fx8-) 2. [如何創建彈出式菜單?](#A.2BWYJPVVIbXvpfOVH6Xw.2BD3FNV.2Fx8-) 3. [如何創建自己個性的菜單?](#A.2BWYJPVVIbXvqB6l3xTipgJ3aEg9xTVf8f-) 4. [菜單設計的適用性準則](#A.2Bg9xTVYu.2Bi6F2hJACdShgJ1HGUhk-) 1. [使菜單有均衡的長度](#A.2BT3.2BD3FNVZwlXR4hhdoSVf16m-) 2. [創建合理的項目組](#A.2BUhte.2BlQIdAZ2hJh5du5.2BxA-) 5. [本章小結](#A.2BZyx64FwPftM-) **本章內容包括**: 創建菜單 使用菜單項工作 添加子菜單、彈出菜單和自定義菜單 菜單的設計準則 難以想象一個應用程序的頂部沒有我們常見的以`File`和`Edit`開頭,以`Help`結尾的欄目。這太糟糕了。菜單是那些隱藏在背后并不太重視繪制的標準界面工具的一個公共的部分,由于菜單使得用戶能夠快速而容易地訪問所有的功能,所以它實實在在是一個革命。 在`wxPython`中有三個主要的類,它們管理菜單的功能。類`wx.MenuBar`管理菜單欄自身,而`wx.Menu`管理一個單獨的下拉或彈出菜單。當然,一個`wx.MenuBar`實例可以包含多個`wx.Menu`實例。類`wx.MenuItem`代表一個`wx.Menu`中的一個特定項目。 在第二章中我們對菜單作了一個簡要的介紹,在例5.5中我們提供了一個容易創建菜單項的機制,在第7章中我對特殊的菜單效果作了一些介紹。在這一章,我們將對`wxPython`菜單的創建和使用提供更多的細節。 ## 創建菜單 首先,我們將討論菜單欄。要使用一個菜單欄,就要執行下面這些行動: ·創建菜單欄 ·把菜單欄附加給框架 ·創建單個的菜單 ·把菜單附加給菜單欄或一個父菜單 ·創建單個的菜單項 ·把這些菜單項附加給適當的菜單 ·為每個菜單項創建一個事件綁定 上面行動的執行順序可以靈活點,只要你在使用之前創建所有項目,并且所有行動在框架的初始化方法中完成就可以了。在這個過程中你可以以后來處理菜單,但是在框架可見后,你的執行順序將影響用戶所見到的東西。例如,如果你在框架創建后將菜單欄附加給框架,或等到直到所有其它的過程完成了。考慮到可讀性和維護的目的,我們推薦你將相關的部分分整理在一起。對于如何組織菜單的創建的建議,請看第5章的重構。在接下來的部分,我們將涉及基本的菜單任務。 ### 如何創建一個菜單欄并把它附加到一個框架? 要創建一個菜單欄,使用`wx.MenuBar`構造函數,它沒有參數: ``` wx.MenuBar() ``` 一旦菜單欄被創建了,使用`SetMenuBar()`方法將它附加給一個`wx.Frame`(或其子類)。通常這些都在框架的`__init__`或`OnInit()`方法中實施: ``` menubar = wx.MenuBar() self.SetMenuBar ``` 你不必為菜單欄維護一個臨時變量,但是這樣做將使得添加菜單到菜單欄多少更簡單點。要掌握程序中的其它地方的菜單欄,使用`wx.Frame.GetMenuBar()`。 ### 如何創建一個菜單并把它附加到菜單欄? `wxPython`菜單欄由一個個的菜單組成,其中的每個菜單都需要分別被創建。下面顯示了`wx.Menu`的構造函數: ``` wx.Menu(title="", style=0) ``` 對于`wx.Menu`只有一個有效的樣式。在`GTK`下,樣式`wx.MENU_TEAROFF`使得菜單欄上的菜單能夠被分開并作為獨立的選擇器。在其它平臺下,這個樣式沒有作用。如果平臺支持,那么菜單被創建時可以有一個標題。圖10.1顯示了一個帶有三個菜單的空白窗口。例10.1顯示了被添到一個菜單欄上的一系列菜單,這些菜單沒有被添加菜單項。 **圖10.1** ![](https://box.kancloud.cn/2016-08-21_57b9964400c67.gif) **例10.1 添加菜單到一個菜單欄** ``` import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, "Simple Menu Example") p = wx.Panel(self) menuBar = wx.MenuBar()# 創建一個菜單欄 menu = wx.Menu()# 創建一個菜單 menuBar.Append(menu, "Left Menu")# 添加菜單到菜單欄 menu2 = wx.Menu() menuBar.Append(menu2, "Middle Menu") menu3 = wx.Menu() menuBar.Append(menu3, "Right Menu") self.SetMenuBar(menuBar) if __name__ == "__main__": app = wx.PySimpleApp() frame = MyFrame() frame.Show() app.MainLoop() ``` 在`wxPython`的菜單`API`中,一個對象的大部分處理是由它的容器類來管理的。在本章的后面,我們將討論`wx.Menu`的特定的方法,因為這些方法的大多數涉及到菜單中的菜單項的處理。在這一節的剩余部分,由于我們正在談論處理`wx.Menu`對象,所以我們將列出`wx.MenuBar`的那些涉及到菜單的方法。表10.1顯示了`wx.MenuBar`中的四個方法,它們處理菜單欄的內容。 **表10.1** **在菜單欄處理菜單的`wx.MenuBar`的方法** | | | | --- | --- | | `Append(menu`, `title)` | 將`menu`參數添加到菜單欄的尾部(靠右顯示)。`title`參數被用來顯示新的菜單。如果成功返回`True`,否則返回`False`。 | | `Insert(pos`, `menu`, `title)` | 將給定的`menu`插入到指定的位置`pos`(調用這個函數之后,`GetMenu(pos)` == `menu`成立)。就像在列表中插入一樣,所有后面的菜單將被右移。菜單的索引以0開始,所以`pos`為0等同于將菜單放置于菜單欄的左端。使用`GetMenuCount()`作為`pos`等同于使用`Append`。`title`被用于顯示名字。函數如果成功則返回`True`。 | | `Remove(pos)` | 刪除位于`pos`的菜單,之后的其它菜單左移。函數返回被刪除的菜單。 | | `Replace(pos`, `menu`, `title)` | 使用給定的`menu`,和`title`替換位置`pos`處的菜單。菜單欄上的其它菜單不受影響。函數返回替換前的菜單。 | `wx.MenuBar`包含一些其它的方法。它們用另外的方式處理菜單欄中的菜單,如表10.2所示。 **表10.2** **`wx.MenuBar`的菜單屬性方法** | | | | --- | --- | | `EnableTop(pos`, `enable)` | 設置位置`pos`處的菜單的可用/不可用狀態。如果`enable`是`True`,那么該菜單是可用的,如果是`False`,那么它不可用。 | | `GetMenu(pos)` | 返回給定位置處的菜單對象。 | | `GetMenuCount()` | 返回菜單欄中的菜單的數量。 | | `FindMenu(title)` | 返回菜單欄有給定`title`的菜單的整數索引。如果沒有這樣的菜單,那么函數返回常量`wx.NOT_FOUND`。該方法將忽略快捷鍵,如果有的話。 | | `GetLabelTop(pos)`,`SetLabelTop(pos`, `label)` | 得到或設置給定位置的菜單的標簽。 | ### 如何給下拉菜單填加項目? 這里有一對機制用于將新的菜單項添加給一個下拉菜單。較容易的是使用`wx.Menu`的`Append()`方法: ``` Append(id, string, helpStr="", kind=wx.ITEM_NORMAL) ``` 參數`id`是一個`wxPython` `ID`。參數`string`是將被顯示在菜單上的字符串。當某個菜單高亮時,如果設置了參數`helpStr`,那么該參數將被顯示在框架的狀態欄中。`kind`參數使你能夠設置菜單項的類型,通過該參數可以將菜單項設置為開關類型。在這一章的后面,我們將討論管理開關項的更好的方法。`Append`方法把新的項放到菜單的尾部。 例10.2 顯示了一個使用`Append()`方法來建立一個有兩個項鏈和一個分隔符的菜單。 **例10.2 添加項目到一個菜單的示例代碼** ``` import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, "Simple Menu Example") p = wx.Panel(self) self.CreateStatusBar() menu = wx.Menu() simple = menu.Append(-1, "Simple menu item", "This is some help text") menu.AppendSeparator() exit = menu.Append(-1, "Exit") self.Bind(wx.EVT_MENU, self.OnSimple, simple) self.Bind(wx.EVT_MENU, self.OnExit, exit) menuBar = wx.MenuBar() menuBar.Append(menu, "Simple Menu") self.SetMenuBar(menuBar) def OnSimple(self, event): wx.MessageBox("You selected the simple menu item") def OnExit(self, event): self.Close() if __name__ == "__main__": app = wx.PySimpleApp() frame = MyFrame() frame.Show() app.MainLoop() ``` 圖10.2 顯示了一個帶有分隔符和狀態文本的菜單。 **圖10.2** ![](https://box.kancloud.cn/2016-08-21_57b9964414ce2.gif) 連同`Append()`一起,這里還有兩個另外的用于菜單項插入的方法。要把一個菜單項放在菜單的開頭,使用下面兩個方法之一: ·`Prepend(id`, `string`, `helpStr`="", `kind`=`wx.ITEM_NORMAL)` ·`PrependSeparator()` 要把新的項放入菜單中的任一位置,使用這下面的`insert`方法之一: ·`Insert(pos`, `id`, `string`, `helpStr`="", `kind`=`wx.ITEM_NORMAL)` ·`InsertSeparator(pos)` 參數`pos`是菜單項要插入的位置的索引,所以如果索引為0,則新的項被放置在開頭,如果索引值為菜單的尺寸,那么新的項被放置在尾部。所以在插入點后的菜單項將被向下移動。 所有的這些插入方法都隱含地創建一個`wx.MenuItem`類的實例。你也可以使用該類的構造函數顯式地創建該類的一個實例,以便設置該菜單項的除了標簽以外的其它的屬性。比如你可以設置自定義的字體或顏色。`wx.MenuItem`的構造函數如下: `wx.MenuItem(parentMenu`=`None`, `id`=`ID_ANY`, `text`="", * `helpString`="", `kind`=`wx.ITEM_NORMAL`, `subMenu`=`None)` 參數`parentMenu`必須是一個`wx.Menu`實例(如果設置了的話)。當構造時,這個新的菜單項不是自動被添加到父菜單上顯示的。你必須自己來實現。這個行為與`wxPython`窗口部件和它們的容器的通常的行為不同。參數`id`是新項的標識符。參數`text`是新項顯示在菜單中的字符串,參數`helpString`是當該菜單項高亮時顯示在狀態欄中的字符串。`kind`是菜單項的類型,`wx.ITEM_NORMAL`代表純菜單項;我們以后會看到開關菜單項有不同的類型值。如果參數`subMenu`的值不是`null`,那么這個新的菜單項實際上就是一個子菜單。我們不推薦你使用這個機制來創建子菜單;替而代之,可以使用在10.3節中說明的機制來裝扮你的菜單。 不像大多數窗口部件,創建菜單項并不將它添加到指定的父菜單。要將新的菜單項添加到一個菜單中,使用下面的`wx.Menu`方法之一: ·`AppendItem(aMenuItem)` ·`InsertItem(pos`, `aMenuItem)` ·`PrependItem(aMenuItem)` 要從菜單中刪除一個菜單項,使用方法`Remove(id)`,它要求一個`wxPython` `ID`,或`RemoveItem(item)`,它要求一個菜單項作為參數。刪除一個菜單項后,后面的菜單項將上移。`Remove()`方法將返回所刪除的實際的菜單項。這使你能夠存儲該菜單項以備后用。與菜單欄不同,菜單沒有直接替換菜單項的方法。替換必須通過先刪除再插入來實現。 `wx.Menu`類也有兩個用來獲取它的菜單項的信息的`get`*方法。`GetMenuItemCount()`返回菜單中項目的數量,`GetMenuItems()`返回菜單中項目的一個列表,項目在列表中的順序與菜單中的位置相一致。這個列表是菜單中實際列表的一個拷貝,意味著改變所返回的列表,不會改變菜單本身。 對于有效的菜單,你可以在運行時繼續添加或刪除菜單項。例10.3顯示了在運行時添加菜單的示例代碼。當按鈕被按下時,調用`OnAddItem()`的方法來插入一個新的項到菜單的尾部。 **例10.3** **運行時添加菜單項** ``` import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, "Add Menu Items") p = wx.Panel(self) self.txt = wx.TextCtrl(p, -1, "new item") btn = wx.Button(p, -1, "Add Menu Item") self.Bind(wx.EVT_BUTTON, self.OnAddItem, btn)# 綁定按鈕的事件 sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(self.txt, 0, wx.ALL, 20) sizer.Add(btn, 0, wx.TOP|wx.RIGHT, 20) p.SetSizer(sizer) self.menu = menu = wx.Menu() simple = menu.Append(-1, "Simple menu item") menu.AppendSeparator() exit = menu.Append(-1, "Exit") self.Bind(wx.EVT_MENU, self.OnSimple, simple) self.Bind(wx.EVT_MENU, self.OnExit, exit) menuBar = wx.MenuBar() menuBar.Append(menu, "Menu") self.SetMenuBar(menuBar) def OnSimple(self, event): wx.MessageBox("You selected the simple menu item") def OnExit(self, event): self.Close() def OnAddItem(self, event): item = self.menu.Append(-1, self.txt.GetValue())# 添加菜單項 self.Bind(wx.EVT_MENU, self.OnNewItemSelected, item)# 綁定一個菜單事件 def OnNewItemSelected(self, event): wx.MessageBox("You selected a new item") if __name__ == "__main__": app = wx.PySimpleApp() frame = MyFrame() frame.Show() app.MainLoop() ``` 在這個例子中,`OnAddItem()`讀取文本域中的文本,并使用`Append()`來添加一個新的項到菜單中。另外,它綁定了一個菜單事件,以便這個新的菜單項有相應的功能。在下一節,我們將討論菜單事件。 ### 如何響應一個菜單事件? 在最后這一小節,我們展示兩個響應菜單選擇的例子代碼。像我們在第8章見過的許多窗口部件一樣,選擇一個菜單項將觸發一個特定類型的`wx.CommandEvent`的一個實例。在此處,該類型是`wx.EVT_MENU`。 菜單項事件在兩個方面與系統中其它的命令事件不同。首先,用于關聯菜單項事件與特定回調函數的`Bind()`函數是在包含菜單欄的框架上的。第二,由于框架通常有多個與`wx.EVT_MENU`觸發相對應的菜單項,所以`Bind()`方法需要第三個參數,它就是菜單項本身。這使得框架能區分不同的菜單項事件。 一個典型的綁定一個菜單事件的調用如下所示: ``` self.Bind(wx.EVT_MENU, self.OnExit, exit_menu_item) ``` `self`是框架,`self.OnExit`是處理方法,`exit_menu_item`是菜單項自身。 盡管通過框架綁定菜單事件的主意似乎有一點古怪,但是它是有原因的。通過框架綁定事件使你能夠透明地綁定一個工具欄按鈕到與菜單項相同的處理器。如果該工具欄按鈕有與一個菜單項相同的`wxPython` `ID`的話,那么這個單個的對`wx.EVT_MENU`的`Bind()`調用將同時綁定該菜單選擇和該工具欄按鈕敲擊。這是可行的,因為菜單項事件與工具事件都經由該框架得到。如果菜單項事件在菜單欄中被處理,那么菜單欄將不會看到工具欄事件。 有時,你會有多個菜單項需要被綁定到同一個處理器。例如,一套單選按鈕開關菜單(它們本質上作相同的事情)可能被綁定給同一處理器。如果菜單項有連續的標識符號的話,為了避免分別的一一綁定,可以使用`wx.EVT_MENU_RANGE`事件類型: ``` self.Bind(wx.EVT_MENU_RANGE, function, id=menu1, id2=menu2) ``` 在這種情況下,所有標識號位于[`menu1`,`menu2`]間菜單項都將綁定到給定的函數。 盡管通常你只關心菜單項命令事件,但是這兒有你能夠響應的另外的菜單事件。在`wxPython`中,類`wx.MenuEvent`管理菜單的繪制和高亮事件。表10.3說明了`wx.MenuEvent`的四個事件類型。 **表10.3 `wx.MenuEvent`的事件類型** | | | | --- | --- | | `EVT_MENU_CLOSE` | 當一個菜單被關閉時觸發。 | | `EVT_MENU_HIGHLIGHT` | 當一個菜單項高亮時觸發。綁定到一個特定的菜單項的`ID`。默認情況下這將導致幫助文本被顯示在框架的狀態欄中。 | | `EVT_MENU_HIGHLIGHT_ALL` | 當一個菜單項高亮時觸發,但是不綁定到一個特定的菜單項的`ID`——這意味對于整個菜單欄只有一個處理器。如果你希望任何菜單的高亮都觸發一個動作,而不考慮是哪個菜單項被選擇的話,你可以調用這個。 | | `EVT_MENU_OPEN` | 當一個菜單被打開時觸發。 | 現在我們已經討論了創建菜單的基礎知識,我們將開始說明如何使用菜單項來工作。 ## 使用菜單項工作 盡管菜單和菜單欄對于一個菜單系統很明顯是至關重要的,但是你的大部分時間和工作將化在處理菜單項上。在下面的幾節中,我們將談論通常的菜單項函數,如查找一個項目,使一個菜單項有效或無效,創建開關菜單項和分配快捷鍵。 ### 如何在一個菜單中找到一個特定的菜單項? 在`wxPython`中有許多方法用于查找一個特定的菜單或給定了標簽或標識符的菜單項。你經常在事件處理器中使用這些方法,尤其是當你想修改一個菜單項或在另一個位置顯示它的標簽文本時。例10.1對先前的動態菜單例子作了補充,它通過使用`FindItemById()`得到菜單項以顯示。 **例10.4** **發現一個特定的菜單項** ``` import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, "Find Item Example") p = wx.Panel(self) self.txt = wx.TextCtrl(p, -1, "new item") btn = wx.Button(p, -1, "Add Menu Item") self.Bind(wx.EVT_BUTTON, self.OnAddItem, btn) sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(self.txt, 0, wx.ALL, 20) sizer.Add(btn, 0, wx.TOP|wx.RIGHT, 20) p.SetSizer(sizer) self.menu = menu = wx.Menu() simple = menu.Append(-1, "Simple menu item") menu.AppendSeparator() exit = menu.Append(-1, "Exit") self.Bind(wx.EVT_MENU, self.OnSimple, simple) self.Bind(wx.EVT_MENU, self.OnExit, exit) menuBar = wx.MenuBar() menuBar.Append(menu, "Menu") self.SetMenuBar(menuBar) def OnSimple(self, event): wx.MessageBox("You selected the simple menu item") def OnExit(self, event): self.Close() def OnAddItem(self, event): item = self.menu.Append(-1, self.txt.GetValue()) self.Bind(wx.EVT_MENU, self.OnNewItemSelected, item) def OnNewItemSelected(self, event): item = self.GetMenuBar().FindItemById(event.GetId()) #得到菜單項 text = item.GetText() wx.MessageBox("You selected the '%s' item" % text) if __name__ == "__main__": app = wx.PySimpleApp() frame = MyFrame() frame.Show() app.MainLoop() ``` 在這個例子中,`FindItemById()`被用來得到一個菜單項的標簽文本以便顯示。 `wx.MenuBar`和`wx.Menu`對于查找特定的菜單項有著本質上相同的方法。其主要的區別是,`wx.MenuBar`的方法將查找整個菜單欄上的菜單項,而`wx.Menu`只查找特定的菜單。大多數情況下,推薦使用`wx.MenuBar`的方法,因為菜單欄容易使用`wx.Frame.GetMenuBar()`方法來訪問。 要從一個菜單欄查找一個頂級的菜單,使用菜單欄方法`FindMenu(title)`。這個方法返回相應菜單的索引或常量`wx.NOT_FOUND`。要得到實際的菜單,使用`GetMenu()`: ``` def FindMenuInMenuBar(menuBar, title): pos = menuBar.FindMenu(title) if pos == wx.NOT_FOUND: return None return menuBar.GetMenu(pos) ``` `FindMenu`方法的`title`參數匹配菜單的標題(不管菜單的標題有無修飾標簽字符)。例如,即使菜單的標題是 ,`FindMenu(`"`File`")仍將匹配該菜單項。在菜單類中的所有基于標簽字符串發現一個菜單項的方法都有這個功能。 表10.4指出了`wx.MenuBar`的這些方法,它們能夠被用于查找或處理一個特定的菜單項。 **表10.4 `wx.MenuBar`的菜單項處理方法** | | | | --- | --- | | `FindMenuItem(menuString`,`itemString)` | 在一個名為`menuString`的菜單中查找名為`itemString`的菜單項。返回找到的菜單項或`wx.NOT_FOUND`。 | | `FindItemById(id)` | 返回與給定的`wxPython`標識符相關聯的菜單項。如果沒有,返回`None`。 | | `GetHelpString(id)`,`SetHelpString(id`,`helpString)` | 用于給定`id`的菜單項的幫助字符串的獲取或設置。如果沒有這樣的菜單項,那么`get`*方法返回"",`set`*方法不起作用。 | | `GetLabel(id)`,`SetLabel(id`, `label)` | 用于給定`id`的菜單項的標簽的獲取或設置。如果沒有這樣的菜單項,那么`get`*方法返回"",`set`*方法不起作用。這些方法只能用在菜單欄已附加到一個框架后。 | 表10.5 顯示了用于`wx.Menu`的菜單項處理方法。它們分別與菜單欄中的方法相類似,除了所返回的菜單項必須在所調用的菜單實例中。 在菜單項返回后,你可能想做些有用的事情,如使該菜單項有效或無效。在下一節,我們將討論使用菜單項有效或無效。 **表10.5 `wx.Menu`的菜單項方法** | | | | --- | --- | | `FindItem(itemString)` | 返回與給定的`itemString`相關的菜單項或`wx.NOT_FOUND`。 | | `FindItemById(id)` | 返回與給定的`wxPython`標識符相關聯的菜單項。如果沒有,返回`None`。 | | `FindItemByPosition(pos)` | 返回菜單中給定位置的菜單項 | | `GetHelpString(id)`,`SetHelpString(id`,`helpString)` | 與菜單欄的對應方法相同。 | | `GetLabel(id)`,`SetLabel(id`, `label)` | 與菜單欄的對應方法相同。 | ### 如何使一個菜單項有效或無效? 類似于其它的窗口部件,菜單和菜單項也可以有有效或無效狀態。一個無效的菜單或菜單項通常顯示為灰色文本,而非黑色。無效的菜單或菜單項不觸發高亮或選擇事件,它對于系統來說是不可見的。 例10.5顯示了開關菜單項的有效狀態的示例代碼,其中在按鈕的事件處理器中使用了菜單欄的`IsEnabled()`和`Enable()`方法。 **例10.5** ``` import wx ID_SIMPLE = wx.NewId() class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, "Enable/Disable Menu Example") p = wx.Panel(self) self.btn = wx.Button(p, -1, "Disable Item", (20,20)) self.Bind(wx.EVT_BUTTON, self.OnToggleItem, self.btn) menu = wx.Menu() menu.Append(ID_SIMPLE, "Simple menu item") self.Bind(wx.EVT_MENU, self.OnSimple, id=ID_SIMPLE) menu.AppendSeparator() menu.Append(wx.ID_EXIT, "Exit") self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT) menuBar = wx.MenuBar() menuBar.Append(menu, "Menu") self.SetMenuBar(menuBar) def OnSimple(self, event): wx.MessageBox("You selected the simple menu item") def OnExit(self, event): self.Close() def OnToggleItem(self, event): menubar = self.GetMenuBar() enabled = menubar.IsEnabled(ID_SIMPLE) menubar.Enable(ID_SIMPLE, not enabled) self.btn.SetLabel( (enabled and "Enable" o "Disable") + " Item") if __name__ == "__main__": app = wx.PySimpleApp() frame = MyFrame() frame.Show() app.MainLoop() ``` 要查看或改變菜單項自身或菜單欄上的,或特定菜單上的一個菜單項的有效狀態,調用 `wx.MenuItem.IsEnabled()`、`wx.MenuBar.IsEnabled(id)`或`wx.Menu.IsEnabled(id)`方法。菜單欄和菜單方法都要求一個菜單項的`wxPython`標識符。如果該菜單項存在且有效,那么這兩個方法都返回`True`,如果該菜單項不存在或無效,那么這兩個方法都返回`False`。唯一的區別是`wx.Menu`的方法只在特定的菜單中搜索,而菜單欄方法搜索整個菜單欄。`wx.MenuItem`方法不要求參數,它返回特定菜單項的狀態。 要改變有效狀態,使用`wx.MenuBar.Enable(id`, `enable)`, `wx.Menu.Enable(id`,`enable)`, 或 `wx.MenuItem.Enable(enable)`。`enable`參數是布爾值。如果為`True`,相關菜單項有效,如果為`False`,相關菜單項無效。`Enable()`方法的作用域和`IsEnabled()`方法相同。你也可以使用`wx.MenuBarEnableTop(pos`,`enable)`方法來讓整個頂級菜單有效或無效。在這里,`pos`參數是菜單欄中菜單的整數位置,`enable`參數是個布爾值。 ### 如何將一個菜單項與一個快捷鍵關聯起來? 圖10.3顯示了一個示例菜單。注意該菜單的菜單名中有一個帶下劃線的字符,其中的標簽為`Accelerated`的菜單項的快捷鍵是`Ctrl`-A。 **圖10.3** ![](https://box.kancloud.cn/2016-08-21_57b9964428a50.gif) 研究表明快捷鍵并不總是能夠節省時間。但是它們是標準的界面元素,并且你的用戶也希望它們的存在。 例10.6顯示了給菜單項添加快捷鍵的代碼。 **例10.6** ``` import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, "Accelerator Example") p = wx.Panel(self) menu = wx.Menu() simple = menu.Append(-1, "Simple item") # Creating a mnemonic accel = menu.Append(-1, " \tCtrl-A") # Creating an accelerator menu.AppendSeparator() exit = menu.Append(-1, "E ") self.Bind(wx.EVT_MENU, self.OnSimple, simple) self.Bind(wx.EVT_MENU, self.OnAccelerated, accel) self.Bind(wx.EVT_MENU, self.OnExit, exit) menuBar = wx.MenuBar() menuBar.Append(menu, " ") self.SetMenuBar(menuBar) acceltbl = wx.AcceleratorTable( [ #Using an accelerator table (wx.ACCEL_CTRL, od('Q'), exit.GetId()) ]) self.SetAcceleratorTable(acceltbl) def OnSimple(self, event): wx.MessageBox("You selected the simple menu item") def OnAccelerated(self, event): wx.MessageBox("You selected the accelerated menu item") def OnExit(self, event): self.Close() if __name__ == "__main__": app = wx.PySimpleApp() frame = MyFrame() frame.Show() app.MainLoop() ``` 在`wxPython`中有兩種快捷鍵;`mnemonics`(助記符)和`accelerator`(加速器)。下面,我們將討論這兩種的區別。 **使用助記符快捷方式** 助記符是一個用來訪問菜單項的單個字符,以一個帶有下劃線的字母表示。助記符可以通過為菜單或菜單項指定顯示的文本來創建,并在你想用來作為助記符的字符前面放置一個&符號,例如 , 或`Ma` 。如果你希望在你的菜單文本中有一個&符號,那么你必須輸入兩個&&符號,例如&&。 助記符是作為在菜單樹中選擇的一個備用的方法。它僅在被用戶顯式地調用時被激活;在微軟`Windows`下,通過按下`alt`鍵來激活它。一旦助記符被激活,下一步按下頂級菜單的助記符來打開頂級菜單。這樣一步打開菜單,直到一個菜單項被選擇,此時一個菜單事件被觸發。助記符在菜單中必須是獨一無二的,但在整個菜單欄中可以不是獨一無二。通常菜單文本的第一個字符被用作助記符。如果你有多個菜單項有相同的開頭字母,那么就沒有特定的準則來決定那個字符用作助記符(最常用的選擇是第二個和最后一個,這要看哪個更合理)。菜單文本清晰的含義比有一個好的助記符更重要。 **使用加速器快捷方式** 在`wxPython`中加速器是一個更加典型的鍵盤快捷方式,它意味能夠隨時調用的按鍵組合,這些按鍵組合直接觸發菜單項。加速器可以用兩種方法創建。最簡單的方法是,在菜單或菜單項的顯示文本中包括加速器按鍵組合(當菜單或菜單項被添加到其父中時)。實現的方法是,在你的菜單項的文本后放置一個\t。在\t之后定義組合鍵。組合鍵的第一部分是一個或多個`Alt`, `Ctrl`, 或`Shift`,由一個+或一個-分隔,隨后是實際的加速器按鍵。例如:`New`\`tctrl`-n, `SaveAs`\`tctrl`-`shift`-s。即使在第一部分你只有一個專用的鍵,你仍可使用+或-來將該部分與實際的按鍵分隔。這不區分按鍵組合的大小寫。 實際的鍵可以是任何數字、字母或功能鍵(如`F1`~`F12`),還有表10.6所列出的專用詞。 `wxPython`的方法在通過名字查找一個菜單或菜單項時忽略助記符和加速器。換句話說,對`menubar.FindMenuItem(`"`File`", "`SaveAs`")的調用將仍匹配`Save` `as`菜單項,即使菜單項的顯示名是以`Save` \`tctrl`-`shift`-s形式輸入的。 加速器也可能使用加速器表被直接創建,加速器表是類`wx.AccleratorTable`的一個實例。一個加速器表由`wx.AccelratorEntry`對象的一個列表組成。`wx.AcceleratorTable`的構造函數要求一個加速器項的列表,或不帶參數。在例10.6中,我們利用了`wxPython`將隱式使用參數(`wx.ACCEL_CTRL`, `od(`'Q'),`exit.GetId())`調用`wx.AcceleratorEntry`構造函數的事實。`wx.AcceleratorEntry`的構造函數如下: `wx.AcceleratorEntry(flags`, `keyCode`, `cmd)` `flags`參數是一個使用了一個或多個下列常量的位掩碼:`wx.ACCEL_ALT`, `wx.ACCEL_CTRL`, `wxACCEL_NORMAL` , 或`wx.ACCEL_SHIFT`。該參數表明哪個控制鍵需要被按下來觸發該加速器。`keyCode`參數代表按下來觸發加速器的常規鍵,它是對應于一個字符的`ASCII`數字,或在`wxWidgets`文本中的`Keycodes`下的一個專用字符。`cmd`參數是菜單項的`wxPython`標識符,該菜單項當加速器被調用時觸發其命令事件。正如你從例10.6所能看到的,使用這種方法聲明一個加速器,不會在這個帶菜單項顯示名的菜單上列出組合鍵。你仍需要單獨實現它。 **表10.6 非字母順序的加速器鍵** **加速器** **鍵** `delDelete` `deleteDelete` `downDown` `arrow` `endEnd` `enterEnter` `escEscape` `escapeEscape` `homeHome` `insInsert` `insertInsert` `leftLeft` `arrow` `pgdnPage` `down` `pgupPage` `Up` `returnEnter` `rightRight` `arrow` `spaceSpace` `bar` `tabTab` `upUp` `arrow` ### 如何創建一個復選或單選開關菜單項? 菜單項不僅用于從選擇表單中得到用戶的輸入,它們也被用于顯示應用程序的狀態。經由菜單項來顯示狀 態的最常用的機制是開關菜單項的使用,開關菜單項仿效一個復選框或單選按鈕(你只能夠通過改變該菜 單項的文本或使用有效或無效狀態來反映應用程序的狀態)。圖10.4顯示了復選和單選菜單項的例子。 **圖10.4** ![](https://box.kancloud.cn/2016-08-21_57b996443c913.gif) 顧名思義,一個復選開關菜單項在它每次被選擇時,它在開和關狀態間轉換。在一個組中,一次只允許一 個單選菜單項處于開的狀態。當同一組中的另一個菜單項被選擇時,先前的菜單項改變為關狀態。例10.7 顯示了如何創建復選和單選菜單項。 **例10.7** **建造開關菜單項** ``` import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, "Toggle Items Example") p = wx.Panel(self) menuBar = wx.MenuBar() menu = wx.Menu() exit = menu.Append(-1, "Exit") self.Bind(wx.EVT_MENU, self.OnExit, exit) menuBar.Append(menu, "Menu") menu = wx.Menu() menu.AppendCheckItem(-1, "Check Item 1") menu.AppendCheckItem(-1, "Check Item 2") menu.AppendCheckItem(-1, "Check Item 3") menu.AppendSeparator() menu.AppendRadioItem(-1, "Radio Item 1") menu.AppendRadioItem(-1, "Radio Item 2") menu.AppendRadioItem(-1, "Radio Item 3") menuBar.Append(menu, "Toggle Items") self.SetMenuBar(menuBar) def OnExit(self, event): self.Close() if __name__ == "__main__": app = wx.PySimpleApp() frame = MyFrame() frame.Show() app.MainLoop() ``` 正如你從例子所見到的,通過使用方法`AppendCheckItem(id`, `item`, `helpString`="")來添加一個復選框菜 單項,該方法類似于`Append()`。該方法的參數是`wxPython`標識符、顯示在菜單中的名字、顯示在狀態欄聽 幫助字符串。同樣,你可以使用`PrependCheckItem(id`,`item`, `helpString`="")和`InsertCheckItem(pos`, `id`, `item`, `helpString`=""),這兩個方法的行為與它們的無復選框的版本相同。 單選按鈕菜單項可以使用`AppendRadioItem(id`,`item`,`helpString`="")方法來添加,你也可以使用 `PrependRadioItem(id`,`item`, `helpString`="")和`InsertRadioItem(pos`, `id`, `item`, `helpString`="") 方法。一系列連續的單選菜單項被作為一組,一組中一次只能有一個成員被觸發。組以第一個非單選菜單 項或菜單分隔符為界。默認情況下,當單選組被創建時,該組中的第一個成員處于選中狀態。 開關菜單項可以通過使用`Append()`來創建。`Append()`的`kind`參數要求下列常量值之一:`wx.ITEM_CHECK`, `wx.ITEM_NORMAL`, `wx.ITEM_RADIO`或`wx.ITEM_SEPARATOR`,其中的每個值創建一個適當類型的菜單項。這是有用的,如果你正在使用某種數據驅動過程自動創建這些菜單項的話。所有類型的菜單項都可以使用這同種方法來創建,盡管指定`kind`為`wx.ITEM_SEPARATOR`來生成一個分隔符必須給`id`參數傳遞`wx.ID_SEPARATOR`。 當你使用`wx.MenuItem`構造函數時你也可以創建一個開關菜單項(給參數`kind`一個相應的常量值)。所得 的菜單項可以使用`AppendItem()`, `PrependItem()`, `InsertItem()`之一的方法被添加到一個菜單。 要確定一個菜單項的開關狀態,使用`IsCheckable()`,如果該項是一個復選或單選項,函數返回`True`,使 用`IsChecked()`,如果該項是可開關的且處于選中狀態,那么返回`True`。你也可以使用`Check(check)`方法 來設置一個菜單項的開關狀態,`check`是一個布爾參數。使用`Check(check)`方法設置時,被設置的菜單項 是單選的,那么將影響同一組別的項。 你也可以使用`IsChecked(id)`從菜單或菜單欄得到一個菜單項的開關狀態,它要求相應菜單項的`id`。你也 可以使用`Check(id`, `check)`來設置菜單欄或菜單中的菜單項,參數`check`是布爾值。 ## 進一步構建菜單 在接下來的幾節,我們將通過使你的菜單更雜化來讓它更有用。首先我們將討論嵌套的子菜單,然后是在你的程序中加入彈出菜單。最后是構建喜愛樣式的菜單項。 ### 如何創建一個子菜單? 如果你的應用程序變得太復雜,你可以在頂級菜單中創建子菜單,這使你能夠在一個項級菜單中嵌套菜單項且裝入更多的項目。對于將一系列的屬于同一邏輯的選項組成一組,子菜單是十分有用的,尤其是要將太多的選項地放入頂級菜單的時候。圖10.5顯示了一個使用子菜單的示例。 **圖10.5** ![](https://box.kancloud.cn/2016-08-21_57b99644522d5.gif) 例10.8顯示了產生圖10.5的代碼。 **例10.8** **建造一個嵌套的子菜單** ``` import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, "Sub-menu Example") p = wx.Panel(self) menu = wx.Menu() submenu = wx.Menu() submenu.Append(-1, "Sub-item 1") submenu.Append(-1, "Sub-item 2") menu.AppendMenu(-1, "Sub-menu", submenu)#添加子菜單 menu.AppendSeparator() exit = menu.Append(-1, "Exit") self.Bind(wx.EVT_MENU, self.OnExit, exit) menuBar = wx.MenuBar() menuBar.Append(menu, "Menu") self.SetMenuBar(menuBar) def OnExit(self, event): self.Close() if __name__ == "__main__": app = wx.PySimpleApp() frame = MyFrame() frame.Show() app.MainLoop() ``` 你從例10.8會注意到,子菜單的創建方法與頂級菜單的相同。你創建類`wx.Menu`的一個實例,然后以相同的方法給子菜單增加菜單項。不同的是子菜單沒有被添加到頂級菜單欄,而是使用`AppendMenu(id`, * `text`, `submenu`, `helpStr)`把它添加給另一個菜單。該函數的參數類似于`Append()`的。參數`id`是要添加到的菜單的`wxPython`標識符。參數`text`是子菜單顯示在父菜單中的字符串。參數`submenu`是子菜單自身,`helpStr`是顯示在狀態欄中的文本。另外還有子菜單的插入方法:`PrependMenu(id`,`text`, `submenu`, `helpStr)`和`InsertMenu(pos`, `text`, `submenu`, `helpStr)`。這些方法的行為與這章前面我們所討論的菜單項的插入方法的行為類似。 記住,子菜單創建的步驟的順序相對于單純的菜單項來說是較為重要的,我們推薦你先將項目添加給子菜單,然后將子菜單附加給父菜單。這使得`wxPython`能夠正確地為菜單注冊快捷鍵。你可以嵌套子菜單到任意深度,這通過給已有的子菜單添加子菜單來實現,而非將子菜單添加到頂級菜單,在添加新的子菜單之前,你仍需要創建創建它。 ### 如何創建彈出式菜單? 菜單不僅能夠從框架頂部的菜單欄向下拉,而且它們也可以在框架的任一處彈出。多數情況下,一個彈出菜單用于根據上下文和用戶所敲擊位置的對象來提供相應的行為。圖10.6顯示了一個彈出式菜單的例子。 **圖10.6** ![](https://box.kancloud.cn/2016-08-21_57b9964499f76.gif) 彈出菜單的創建是非常類似于標準菜單的,但是它們不附加到菜單欄。例10.9顯示了一個彈出菜單的示例代碼。 **例10.9** **在任意一個窗口部件中創建一個彈出式菜單** ``` import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, "Popup Menu Example") self.panel = p = wx.Panel(self) menu = wx.Menu() exit = menu.Append(-1, "Exit") self.Bind(wx.EVT_MENU, self.OnExit, exit) menuBar = wx.MenuBar() menuBar.Append(menu, "Menu") self.SetMenuBar(menuBar) wx.StaticText(p, -1, "Right-click on the panel to show a popup menu", (25,25)) self.popupmenu = wx.Menu()#創建一個菜單 for text in "one two three four five".split():#填充菜單 item = self.popupmenu.Append(-1, text) self.Bind(wx.EVT_MENU, self.OnPopupItemSelected, item) p.Bind(wx.EVT_CONTEXT_MENU, self.OnShowPopup)#綁定一個顯示菜單事件 def OnShowPopup(self, event):#彈出顯示 pos = event.GetPosition() pos = self.panel.ScreenToClient(pos) self.panel.PopupMenu(self.popupmenu, pos) def OnPopupItemSelected(self, event): item = self.popupmenu.FindItemById(event.GetId()) text = item.GetText() wx.MessageBox("You selected item '%s'" % text) def OnExit(self, event): self.Close() if __name__ == "__main__": app = wx.PySimpleApp() frame = MyFrame() frame.Show() app.MainLoop() ``` 彈出菜單像任一其它菜單一樣被創建(注意`for`循環對于快速創建菜單項的用法)。它沒有被添加到菜單欄,它被存儲在實例變量`self.popupmenu`中。然后,框架將方法`OnShowPopup()`綁定到事件`wx.EVT_CONTEXT_MENU`。該事件被操作系統的觸發彈出菜單的標準機制所觸發。在微軟`Windows`和`GTK`下,這個機制是鼠標右鍵敲擊,在`Mac` `OS`下,它是一個`control`敲擊。 當用戶在框架上執行一個彈出觸發敲擊的時候,處理器`OnShowPopup()`被調用。該方法所做的第一件事是確定顯示菜單的位置。傳遞給該方法的事件的位置(在`wx.EVT_CONTEXT_MENU`的實例中)是以屏幕的絕對坐標存儲的,所以我們需要將位置坐標轉換為相對于包含彈出菜單的面板的坐標,我們使用方法`ScreenToClient()`。 此后,使用方法`PopupMenu(menu`, `pos)`調用彈出菜單,你也可以使用相關的方法`PopupMenuXY(menu`, x, `y)`。`PopupMenu`函數不返回,直到一個菜單項被選擇或通過按下`Esc`或在該彈出菜單之外敲擊使該彈出菜單消失。如果一個菜單項被選擇,那么它的事件被正常處理(這意味它必須有一個方法與事件`EVT_MENU`綁定),并且在`PopupMenu`方法返回前該事件也被完成。`PopupMenu`的返回值是布爾值,沒什么意思。 彈出菜單可以有一個標題,當彈出菜單被激活時它顯示在彈出菜單的頂部。這個標題使用屬性`wx.Menu.SetTitle(title)`和`wx.Menu.GetTitle()`來處理。 ### 如何創建自己個性的菜單? 如果普通的菜單項引不起你足夠的興趣,你可以添加自定義的位圖到菜單項的旁邊(或用作自定義的檢查符號)。在微軟`Windows`下,你也可以調整菜單項的字體和顏色。圖10.7顯示了一個個性菜單的例子。 **圖10.7** ![](https://box.kancloud.cn/2016-08-21_57b99644abb2c.gif) 例10.10顯示了產生這種菜單的代碼。要確定程序是否運行在`Windows`下,你可以檢查‘`wxMSW`’是否在`wx.PlatformInfo`元組中。 **例10.10** **個性菜單項的示例代碼** ``` import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, "Fancier Menu Example") p = wx.Panel(self) menu = wx.Menu() bmp = wx.Bitmap("open.png", wx.BITMAP_TYPE_PNG) item = wx.MenuItem(menu, -1, "Has Open Bitmap") item.SetBitmap(bmp)#增加一個自定義的位圖 menu.AppendItem(item) if True o 'wxMSW' in wx.PlatformInfo: font = wx.SystemSettings.GetFont( wx.SYS_DEFAULT_GUI_FONT) font.SetWeight(wx.BOLD) item = wx.MenuItem(menu, -1, "Has Bold Font") item.SetFont(font)#改變字體 menu.AppendItem(item) item = wx.MenuItem(menu, -1, "Has Red Text") item.SetTextColour("red")#改變文本顏色 menu.AppendItem(item) menu.AppendSeparator() exit = menu.Append(-1, "Exit") self.Bind(wx.EVT_MENU, self.OnExit, exit) menuBar = wx.MenuBar() menuBar.Append(menu, "Menu") self.SetMenuBar(menuBar) def OnExit(self, event): self.Close() if __name__ == "__main__": app = wx.PySimpleApp() frame = MyFrame() frame.Show() app.MainLoop() ``` 處理控制顯示屬性的主要的內容是給一個菜單項添加顏色或樣式。適合除了`Windows`外(包括`Windows)`的平臺的唯一的屬性是`bitmap`,由`GetBitmap()`管理,該函數返回一個`wx.Bitmap`類型的項。這兒有兩個`set`*方法。第一個是`SetBitmap(bmp)`,它工作于所有的平臺上。它總是在菜單項的旁邊設置一個顯示的位圖。如果你是在微軟`Windows`上,并且你想為一個開關菜單設置一個自定義的位圖,你可以使用`SetBitmaps(checked`, `unchecked`=`wx.NullBitmap)`,它使得當該項被選中時顯示一個位圖,該項未選中時顯示另一個位圖。如果該菜單項不是一個開關菜單項,那么`checked`參數是沒有用的。 在微軟`Windws`下,有三個另外的屬性,你可以用來改變菜單項的外觀,如表10.7所示。我們建議你謹慎地使用它們,并且僅在它們能夠明顯地增強用戶的體驗的情況下。 **表10.7 菜單項的外觀屬性** | | | | --- | --- | | `GetBackgroundColour()` | 屬性類型是`wx.Colour`,該`set`*方法的參數也可以是一個`wxPython`顏色的名稱字符串。管理項目的背景色。 | | `SetBackgroundColour(colour)` | | `GetFont()` | 項目的顯示字體。類型是`wx.Font`。 | | `SetFont(font)` | | `GetTextColour()` | 管理顯示在項目中的文本的顏色。類型和背景色的相同。 | | `SetTextColour(colour)` | 目前我們已經討論了使用菜單功能方面的內容,接下來我們將對如何更好的使用菜單以及如何使你的應用程序對用戶來說更容易使用的問題作一個綱要性的說明,以結束本章。 ## 菜單設計的適用性準則 對于大多數復雜的應用程序,菜單欄是用戶訪問應用程序功能的主要入口。正確的設計菜單對你的程序的易用性有很大的幫助。本著這一想法,我們提供了一些關于菜單設計的適用性準則。 ### 使菜單有均衡的長度 建議菜單所包含的項目的最大數量在10到15之間。超過這個最大長度的菜單將會看不全。你應該學習創建長度基本一致的菜單,記住,這有時是不可能或不必要的。 ### 創建合理的項目組 你不應該創建一個沒有分隔符的多于五個項目的組,除非你有非常合理的理由這樣做——如一個歷史列表,或一個插件列表。多于五個項目的組,用戶處理起來非常困難。要有一個更大的組,項目需要被強有力地聯系在一起并且要有用戶期望長于五個項目的列表的原因。 **菜單的順序要遵循標準** 對于菜單的順序,你應該遵循公認的標準。最左邊的菜單應該是`FILE`(文件),并且它包含`new`(新建),`open`(打開),`save`(保存),`print`(打印)和`quit`(退出)功能,所包含的功能的順也是這樣,另外的一些功能通常添加在打印和退出之間。幾乎每個應用程序都要使用到這些功能。下一個菜單是`EDIT`(編輯),它包含`undo`(撤消),`cut`(剪切),`copy`(拷貝),`paste`(粘貼)和常用的`find`(查找),這些依賴于你的程序的應用范圍。`HELP`(幫助)菜單總是在最右邊,并且`windows`(窗口)菜單經常是挨著它的。中間的其它菜單通常由你自己來決定。 **對通常使用的項目提供方便的訪問** 用戶總是會更先訪問到菜單中更上面的項目。這就說明了更常用的選項應放在頂部。有一個例外就是多數研究顯示,第二項先于第一項。 **使用有含義的菜單名稱** 記住,位于菜單欄上的菜單的寬度是與它的名稱成正比的,并且當菜單打開時它的寬度與它所包含的項目的最長的名字成正比。盡量避免使頂級菜單的名字少于四個字母。除了通常的名稱外,我們建議只要有可能,名字再長點,但意義要清楚。不要害怕給一個菜單項較長的文本,盡管30~40個字符可能難讀。 **當一個項目會調用一個對話框時,記住帶有省略號** 任何會導致一個對話框被顯示的菜單項,都應該有一個以省略號(...)結尾的標簽。 **使用標準的快捷鍵** 對快捷鍵,使用通常功能的公認的標準,如表10.8所示。 **表10.8 快捷鍵功能** | | | | --- | --- | | `Ctrl`-a | 全選 | | `Ctrl`-c | 拷貝 | | `Ctrl`-f | 查找 | | `Ctrl`-g | 查找下一個 | | `Ctrl`-n | 新建 | | `Ctrl`-o | 打開 | | `Ctrl`-p | 打印 | | `Ctrl`-q | 退出 | | `Ctrl`-s | 保存 | | `Ctrl`-v | 粘貼 | | `Ctrl`-w | 關閉 | | `Ctrl`-x | 剪切 | | `Ctrl`-z | 撤消 | 這里沒有列出`Redo`(重做)的公認的快捷鍵,你有時會看到用于它的`Ctrl`-y,`Alt`-z或其它的組合。如果你給通常功能提供了更多的快捷鍵,那么建議你給用戶提供一個方案來改變它們。快捷鍵在用戶做大量的輸入工作時是很有用的,例如一個文本編輯器。但是對于大部分用鼠標完成的工作,它們的作用就很少了。 **反映出開關狀態** 當創建一個開關菜單時,有兩個事情需要注意。第一,記住,一個未選中的復選菜單項看起來與一個通常的菜單項相同。如果該菜單項的文本如`fancy` `mode` `on`的話,那么用戶就有可能不知道選擇這個菜單項會改變樣式。另一個要注意的是,菜單項文本要反映出當前不是被激活的狀態,而非激活狀態。比如菜單文本說明如果選擇它會執行什么動作。例如,如果`fancy`樣式是打開的,那么文本使用`Turn` `fancy` `mode` `off`。菜單中沒有語句表明`fancy`樣式實際是什么樣的,這可以引起混淆。要避免這個問題,對于一個未被選擇的菜單,使用一個自定義的位圖以視覺的方式說明這個菜單是一個開關菜單,是一個好的主意(平臺允許的話)。如果你的平臺不支的話,使用像 `toggle` `fancy` `mode`或`switch` `fancy` `mode` (`now` `on)`這樣的文本意思會更清楚。 **慎重地使用嵌套** 嵌套層次的菜單對于瀏覽來說不方便。 **避免使用字體和顏色** 你記得有哪一個應用程序在它的菜單項中使用了字體和顏色的。我們也不這要使用(但是用于選擇字體或顏色的菜單是例外)。很明顯,這種使用非常少見。 ## 本章小結 ·在圖形用戶界面中,菜單是最常用來讓用戶觸發命令的機制。在`wxPython`中,創建菜單使用三個主要的類:`wx.MenuBar`,它表示菜單欄并包含菜單,菜單使用`wx.Menu`。菜單由菜單項組成,菜單項使用`wx.MenuItem`。對于菜單部分的創建,首先創建菜單欄并將它附加到框架。然后分別創建個個菜單,并添加菜單項。再將菜單添加到菜單欄。菜單項可以被添加到菜單的任意位置。一個菜單項也可以是一個菜單分隔符,而非普通的菜單項。當菜單項被添加到其父菜單時,菜單項對象可以被顯式地或隱含地創建。 ·選擇一個菜單將觸發一個`wx.EVT_MENU`類型的命令事件。菜單事件經由框架綁定,而非菜單項,菜單或菜單欄。這讓工具欄按鈕可以觸發與一個菜單項相同的`wx.EVT_MENU`事件。如果你有多個有著連續標識符的菜單項,它們有相同的處理器的話,那么它們可以使用`wx.EVT_MENU_RANGE`事件類型被綁定在一起調用。 ·菜單項能夠從包含它們的菜單或菜單欄使用`ID`或標簽來查找。也可以被設置成有效或無效。 ·一個菜單可以被附加給另一個菜單,而非菜單欄,從而形成一個嵌套的子菜單。`wx.Menu`有特定的方法使你能夠添加子菜單,同樣也能夠添加一個菜單項。 ·菜單可以用兩種方法與按鍵關聯。助記符和加速器。 ·一個菜單項可以有一個開關狀態。它可以是一個復選菜單項,也可以是一個單選菜單項。菜單項的選擇狀態可以經由包含它的菜單或菜單來查詢或改變。 ·可以創建彈出式菜單。這通過捕獲`wx.EVT_CONTEXT_MENU`類型事件,并使用`PopupMenu()`方法來顯示彈出。在彈出中的菜單項事件被正常地處理。 ·你可以為一個菜單項創建一個自定義的位圖,并且在`Windows`操作系統下,你可以改變一個菜單項的顏色和字體。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看