3

最近、メニューの目的で、GWT MenuBar をアプリケーションの一部にアタッチしました。

基本的に、トップレベルのメニューにマウスを合わせるとサブメニューが開くようにしたいのですが、これは簡単です。

menubar.setAutoOpen(true);

また、ユーザーのマウスがサブメニューを離れると、サブメニューが自動的に非表示になるようにしたいと考えています。理想的には、突然消えるのを防ぐために何らかの遅延が必要ですが、私は非表示にするだけで解決します.

これは組み込まれていないようで、GWT の MenuItem オブジェクトは UIObject を直接サブクラス化します。これは、比較的単純な onBrowserEvent() や、マウス リスナーをアタッチする場所がないことを意味します。おそらく、MenuItem を拡張し、シンク/アンシンク イベントを追加すると、この動作を追加できますが、それが最善の方法であるかどうかはわかりません。

では、GWT サブメニューを自動的に非表示にする最善の方法は何でしょうか?

ありがとうございました。

4

4 に答える 4

2

似たようなことを達成しようとして恐ろしいハッキングをした後、 GWT ポートレット フレームワークの一部として独自のカスケード メニューを作成しました。次のような HTML テンプレートのメニュー項目とサブメニューを表示します。

<a href="#home">Home</a>
<a href="#submenu1()">Sub Menu 1</a>
<a href="#away">Away</a>

<div id="submenu1">
    <a href="#hello_world">Hello World</a>
    <a href="#free_memory">Free Memory</a>
    <a href="#submenu2()">Sub Menu 2</a>
</div>

<div id="submenu2">
    <a href="#command_demo">Command Demo</a>
    <a href="#command1()">Command1</a>
    <a href="#command2(arg1,arg2)">Command2</a>
</div>

メソッド呼び出しのように見える URL は、CommandEvent をブロードキャストします。その他は、通常のように履歴トークンの変更をトリガーします。メニューの動作を確認するには、オンライン デモをご覧ください。

于 2009-09-28T18:53:44.997 に答える
0

サブメニューを含む MenuBar の自動非表示を実現するために、恐ろしいハッキングや Java 内の CSS に依存する必要はありません。他の人が使用できるように、マウスオーバーで開き、mouseOut で閉じる、親 + 子ドロップダウン メニューの完全に機能する例を作成しました。

私が目撃した一般的な問題は、 ((JMenu)e.getSource()).doClick(); を実行することです。on the mouseEntered は、JMenu の親の 1 つへのクリックをシミュレートしますが、MouseListener を JMenu の親だけでなく子の MenuItem にもアタッチする必要があるため、mouseExited メソッドに単純に追加することはできません。(これは MenuBar への通常の割り当てでは行われません - 親 JMenu オブジェクトにアタッチするだけです)。

さらに、マウスが Menu 構造全体 (つまり、Child メニューのドロップダウン) を離れた場合にのみ、MouseExit リスナーに「close」メソッドを起動させようとすると、問題が発生します。

以下は、私のライブアプリから取得した完全に機能する回答です。

マウスアウト時にメニューを閉じる方法は、コンストラクターの上部でブール変数「isMouseOut」を実行して追跡し、複数の MouseIn-MouseOut イベントを追跡するために、よりオブジェクト指向に適した方法で MouseListener を割り当てることでした。ユーザーがメニューを操作するとき。これは、ブール値「isMouseOut」の状態に基づいて動作する別の menuClear メソッドを呼び出します。クラスは MouseListener を実装します。これがそのやり方です。

最初にすべてのメニュー項目をこの配列に追加する ArrayList を作成します。そのようです:

    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);

次に、この段階で arrayList を反復処理し、for() ループを使用して MouseListener を追加します。

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

MenuBar の 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);

次に、ドロップダウン menuItems の子を 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);
        }
    }

子の menuItem 要素はすべて、親の JMenu 要素および MenuBar 自体とは別の独自のリスナーを持っているため、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 を呼び出して、実際の mouseOUT の時点でアクティブだった 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内でアクセスできる値を監視して、少しテストが必要でしたが、うまくいきました!ネストされたメニューでも :) 多くの人がこの完全な例が非常に役立つことを願っています。

于 2015-01-02T01:26:13.357 に答える
0

次のコードを使用します。

public class MenuBarExt extends MenuBar {

public MenuBarExt()
{
    super();
}

@Override
public void onBrowserEvent(Event event)
{
    switch (DOM.eventGetType(event))
    {
        case Event.ONMOUSEOUT:
            closeAllChildren(false);
            break;
        default:
            super.onBrowserEvent(event);
            break;

    } 
    super.onBrowserEvent(event);
}

}
于 2015-03-14T12:35:48.543 に答える