2012-08-25 92 views
7

JMenuBar沒有開始顯示JMenuItem s被選中或顯示JMenu彈出式窗口,直到第一次點擊。在JMenuBar中單擊某處後,所有這些項目都會響應鼠標懸停。在懸停時激活JMenuBar

我想繞過所需的初始點擊並在鼠標懸停後自動激活它。有沒有辦法做到這一點?

+3

你爲什麼要這麼做的很好的理由?所有應用程序中的所有菜單欄都表現得如此 – Robin

+0

那麼我的菜單具有自定義外觀,而且這種行爲更適合自然。另外,我相信這種行爲對於用戶來說更加互動。 – springcorn

回答

9

方法是在JMenu上添加一個MouseListener,並收聽事件mouseEntered。在事件處理程序中,您只需使用doClick單擊它。例如,

jMenuFile.addMouseListener(new MouseListener(){ 
    public void mouseEntered(MouseEvent e) { 
     jMenuFile.doClick(); 
    } 
    ... 
}); 

一旦以編程方式點擊鼠標進入,它會自動打開彈出菜單。要激活整個JMenuBar,您必須在每個JMenu上添加一個偵聽器。爲此,最好分別創建一個偵聽器對象。

我有欄上兩個菜單項,所以我所做的:

MouseListener ml = new MouseListener(){ 
    public void mouseClicked(MouseEvent e) {} 
    public void mousePressed(MouseEvent e) {} 
    public void mouseReleased(MouseEvent e) {} 
    public void mouseExited(MouseEvent e) {} 
    public void mouseEntered(MouseEvent e) { 
     ((JMenu)e.getSource()).doClick(); 
    } 
    }; 
    jMenuFile.addMouseListener(ml); 
    jMenuHelp.addMouseListener(ml); 

如果你有欄上這麼多的菜單項,你可以遍歷它:

for (Component c: jMenuBar1.getComponents()) { 
    if (c instanceof JMenu){ 
     c.addMouseListener(ml); 
    } 
} 
+0

我瞭解mouseEntered監聽器,但是如何從mousentered激活整個JMenuBar? – springcorn

+0

剛纔編輯 –

+0

謝謝。這讓我走上了正軌,但我想我希望有一個更簡單的方法來做到這一點,如jMenuBar.activate(),而不是單獨強制點擊。對於JMenuItem,您不能調用doClick(),而是我相信生成此行爲的最佳方式是s​​etArmed(true) – springcorn

1

羅馬C'S初始和接受的答案不會自動關閉帶有子菜單項的菜單作爲JMenuBar的一部分。運行一個((JMenu)e.getSource())。doClick();在鼠標輸入模擬單擊到JMenu父母之一,但不能簡單地添加到mouseExited方法,因爲MouseListener需要附加到子菜單項以及JMenu父母。 (它不會在正常分配給MenuBar時執行 - 只附加到父JMenu對象)。

此外,由於嘗試讓MouseExit偵聽器在鼠標離開整個Menu結構(即子菜單下拉列表)時觸發「close」方法,因此出現問題。

下面是從我的生活應用程序採取了一個有效的答案:

我解決了關閉鼠標在菜單的方法是在構造頂部運行布爾變量「isMouseOut」追蹤,然後以更友好的OO方式分配MouseListener,以便在用戶與菜單交互時跟蹤多個MouseIn-MouseOut事件。它調用一個單獨的menuClear方法來處理布爾型「isMouseOut」的狀態。該類實現MouseListener。這是如何完成的。

創建一個ArrayList,首先將所有菜單項添加到該數組中。像這樣:

for (Component c : aMenuItms) { 
     if (c instanceof JMenuItem) { 
      c.addMouseListener(ml); 
     } 
    } 

現在設置JMenu的父母爲菜單欄:

// Now set JMenu parents on MenuBar 
    final JMenu mnFile = new JMenu("File"); 
    menuBar.add(mnFile).setFont(menuFont); 
    final JMenu mnView = new JMenu("View"); 
    menuBar.add(mnView).setFont(menuFont); 
    final JMenu mnHelp = new JMenu("Help"); 
    menuBar.add(mnHelp).setFont(menuFont); 

Font menuFont = new Font("Arial", Font.PLAIN, 12); 
    JMenuBar menuBar = new JMenuBar(); 
    getContentPane().add(menuBar, BorderLayout.NORTH); 

// Array of MenuItems 
    ArrayList<JMenuItem> aMenuItms = new ArrayList<JMenuItem>(); 
    JMenuItem mntmRefresh = new JMenuItem("Refresh"); 
    JMenuItem mntmNew = new JMenuItem("New"); 
    JMenuItem mntmNormal = new JMenuItem("Normal"); 
    JMenuItem mntmMax = new JMenuItem("Max"); 
    JMenuItem mntmStatus = new JMenuItem("Status"); 
    JMenuItem mntmFeedback = new JMenuItem("Send Feedback"); 
    JMenuItem mntmEtsyTWebsite = new JMenuItem("EtsyT website"); 
    JMenuItem mntmAbout = new JMenuItem("About"); 

    aMenuItms.add(mntmRefresh); 
    aMenuItms.add(mntmNew); 
    aMenuItms.add(mntmNormal); 
    aMenuItms.add(mntmMax); 
    aMenuItms.add(mntmStatus); 
    aMenuItms.add(mntmFeedback); 
    aMenuItms.add(mntmEtsyTWebsite); 
    aMenuItms.add(mntmAbout); 

那麼在這個階段使用for()循環添加的MouseListener在ArrayList的迭代然後將下拉菜單項子項添加到JMenu父項:

// Now set menuItems as children of JMenu parents 
    mnFile.add(mntmRefresh).setFont(menuFont); 
    mnFile.add(mntmNew).setFont(menuFont); 
    mnView.add(mntmNormal).setFont(menuFont); 
    mnView.add(mntmMax).setFont(menuFont); 
    mnHelp.add(mntmStatus).setFont(menuFont); 
    mnHelp.add(mntmFeedback).setFont(menuFont); 
    mnHelp.add(mntmEtsyTWebsite).setFont(menuFont); 
    mnHelp.add(mntmAbout).setFont(menuFont); 

添加mouseListeners到JMenu父母作爲單獨的步驟:

for (Component c : menuBar.getComponents()) { 
     if (c instanceof JMenu) { 
      c.addMouseListener(ml); 
     } 
    } 

現在孩子菜單項元素都有自己的聽衆,是獨立於母公司JMenu的元素和菜單欄本身 - 識別是很重要的MouseListener()實例中的對象類型,以便您可以在鼠標懸停時獲得菜單自動打開(在本例中爲3x JMenu父項),但也避免子例外錯誤,並允許清理識別菜單結構的mouseOUT,而不嘗試監視鼠標位置是。該的MouseListener如下:

MouseListener ml = new MouseListener() { 
     public void mouseClicked(MouseEvent e) { 
     } 

     public void mousePressed(MouseEvent e) { 
     } 

     public void mouseReleased(MouseEvent e) { 
     } 

     public void mouseExited(MouseEvent e) { 
      isMouseOut = true; 
      timerMenuClear(); 
     } 

     public void mouseEntered(MouseEvent e) { 
      isMouseOut = false; 
      Object eSource = e.getSource(); 
      if(eSource == mnHelp || eSource == mnView || eSource == mnFile){ 
       ((JMenu) eSource).doClick(); 
      } 
     } 
    }; 

以上只是模擬鼠標點擊進入JMenu的父母(3次在這個例子中),因爲它們是爲孩子菜單的下拉列表中的觸發器。該timerMenuClear()方法調用的對象MenuSelectionManager清空任何selectedpath點是活在真實的鼠標移開時:

public void timerMenuClear(){ 
    ActionListener task = new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      if(isMouseOut == true){ 
       System.out.println("Timer"); 
      MenuSelectionManager.defaultManager().clearSelectedPath(); 
      } 
     } 
    };   
    //Delay timer half a second to ensure real mouseOUT 
    Timer timer = new Timer(1000, task); 
    timer.setInitialDelay(500);   
    timer.setRepeats(false); 
    timer.start(); 
} 

我花了一個小測試,監測什麼樣的價值觀,我可以在其發展過程中的JVM內訪問 - 但它適用於一種享受!即使嵌套菜單:)我希望很多人發現這個完整的例子非常有用。

相關問題