• ベストアンサー

SwingのJMenuに大量のJMenuItemを配置した場合の表示方法

このカテゴリに初めて質問させて頂きます。使用しているJDKの バージョンは1.4.2です。 今、JavaのSwingを利用してGUIアプリケーションを作成している のですがJMenuに数十個のJMenuItemを配置させる必要があるの ですが、大量のJMenuItemをJMenuに配置すると画面からはみ出 してしまいます。 そこで、JMenuで表示させるJMenuItemの数を制限し、それ以外 のJMenuItemはスクロールのような形で表示できるようにしたい と思っているのですがこのような事は実現可能でしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.3

 こんばんは。  とりあえず、タイマーで動かすことにしてみました。  それっぽく、動きます。  ただ、適当に作ったので、表示するメニューの高さを適切に調整するとか、まだまだ作り込む余地があるのですが、ヒントにはなると思います。  それにしても、なんでこの機能がSwingにないのでしょうねぇ。  不便です。 (コンパイルするときは全角スペースを半角スペースに変換してからにしてください) import javax.swing.*; import java.awt.event.*; public class Test extends JFrame {   JMenuBar menubar;   JMenu menuFile;   JMenuItem upButton;   JMenuItem downButton;   Timer timer;   boolean up;      public static void main(String[] args) {     Test frame = new Test();     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     frame.setSize(300, 200);     frame.setVisible(true);   }      public Test() {     timer = new Timer(500, new Timer_Action());     menubar = new JMenuBar();     menuFile = new JMenu("ファイル(F)");     upButton = new JMenuItem("▲");     Scroll_Clicked sc = new Scroll_Clicked();     upButton.addMouseListener(sc);          downButton = new JMenuItem("▼");     downButton.addMouseListener(sc);          setJMenuBar(menubar);     menubar.add(menuFile);     menuFile.add(upButton);     for (int i = 0; i < 50; i++) {       JMenuItem item = new JMenuItem("メニュー" + Integer.toString(i));       if (i > 30)         item.setVisible(false);       menuFile.add(item);     }     menuFile.add(downButton);   }      private void scrollUp() {     for (int i = 1; i < menuFile.getItemCount() - 30; i++) {       if (menuFile.getItem(i).isVisible()) {         menuFile.getItem(i).setVisible(false);         menuFile.getItem(i + 30).setVisible(true);         return;       }     }     timer.stop();   }      private void scrollDown() {     for (int i = menuFile.getItemCount() - 2; i > 30; i--) {       if (menuFile.getItem(i).isVisible()) {         menuFile.getItem(i).setVisible(false);         menuFile.getItem(i - 30).setVisible(true);         return;       }     }     timer.stop();   }      private class Scroll_Clicked extends MouseAdapter {     public void mouseEntered(MouseEvent e) {       Object source = e.getSource();       if (source == upButton)         up = true;       else         up = false;                timer.start();     }          public void mouseExited(MouseEvent e) {       timer.stop();     }   }      private class Timer_Action implements ActionListener {     public void actionPerformed(ActionEvent e) {       if (up)         scrollUp();       else         scrollDown();     }   } }

ym2
質問者

お礼

ym2です。 PecoPlusさん、わざわざソースコードまで載せて頂いて感謝 です。こういうときにもTimerが使えるとは思いつきませんでした。 これで上手い具合にMenuItemの表示を制御できるようになりました。

その他の回答 (4)

回答No.5

#1です。 #2さんの方法が自分には衝撃的だったので、試しました。 うまくいきました。感動しました。 #2さん、ありがとうございます。勉強になりました。 自分の環境は1.3.0_01と古い?ので、他の方とバージョンが違うのでもしかしたら動かないかもしれません。 稚拙なコードですが、いちおう貼り付けておきます。 (って全部表示できるかな…) import javax.swing.*; import java.awt.*; import java.awt.event.*; public class MenuTest extends JFrame implements ActionListener{ private int begin = 0; private int end = 4; private JButton up = new JButton("▲"); private JButton down = new JButton("▼"); private JMenuItem[] items = new JMenuItem[10]; public MenuTest(){ super(); JMenu menu = new JMenu("hoge"); JMenuBar menubar = new JMenuBar(); menubar.add(menu); up.addActionListener(this); down.addActionListener(this); menu.add(up); for(int i = 0;i < items.length;i++){ items[i] = new JMenuItem(""+i); items[i].addActionListener(this); menu.add(items[i]); } menu.add(down); setJMenuBar(menubar); setSize(200,200); setVisible(true); items[0].setVisible(true); items[1].setVisible(true); items[2].setVisible(true); items[3].setVisible(true); items[4].setVisible(true); items[5].setVisible(false); items[6].setVisible(false); items[7].setVisible(false); items[8].setVisible(false); items[9].setVisible(false); } public void actionPerformed(ActionEvent e){ String command = e.getActionCommand(); System.out.println("アクションコマンド:"+command); if(command.equals("▲")){ if(begin != 0){ items[begin-1].setVisible(true); items[end].setVisible(false); begin = begin-1; end = end-1; } }else if(command.equals("▼")){ if(end != 9){ items[begin].setVisible(false); items[end+1].setVisible(true); begin = begin+1; end = end+1; } }else{ System.out.println("なにもしない"); } } public static void main(String[] args){ MenuTest mt = new MenuTest(); } }

  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.4

 #3です。  試行錯誤をしていたので、MouseAdapterのクラス名が妙なことになってますね。  すみません。かえって混乱しますね。  最初は#2さんの言われるような方法を考えていたのですが、私の環境(J2SE5.0)でJMenuにJButtonを登録すると、ActionEventがトリガされなかったので、しかたないので、JMenuItemにかえました。  すると、クリックすると(当たり前の話ですが)メニューが消えてしまうので、マウスポインタが上に来ると、Timerをスタートさせて、Timerのイベントハンドラからスクロールさせるメソッドを呼ぶようにしました。  とりあえず、50個のメニューのうち30個を表示するようになっていますが、環境によって、ちょうど言い数は違ってくるので、これを動的に変えるようにしなくてはいけないのですが、めんどくさいのでやっていません。  そこら辺のことをちゃんと考えて、ScrollableMenu みたいなクラスを作っておけば、便利でいいのでしょうが・・・。  がんばってください。

noname#49664
noname#49664
回答No.2

ごく基本的な考え方だけですが。 1.JButtonを2つ用意します。上向きのスクロール用、下向きのスクロール用です。 2.JMenuを作成し、上向きスクロールのJButton、続いてJMenuItemを必要なだけ、最後に下向きスクロールのJButtonをaddします。つまり、2つのJButtonの間にJMenuItemがずら~っと並ぶようにするわけです。 3.一番最初のJMenuItemから、表示させる数だけのJMenuItemをsetVisible(true)し、それ以後のものをすべてsetVisible(false)します。 4.上向きのJButtonのactionPerformedでは、表示されている一番下のJMenuItemを非表示にし、一番上のJMenuItemの1つ上のものを表示させます。 5.下向きのJButtonでは、反対に表示されている一番上のものを非表示にし、一番下の更に1つ下のものを表示させます。 ざっとこんな感じで上下にスクロールするメニューができると思います。 要するにsetVisibleで表示非表示を切り替えているだけですが、スクロールした「感じ」にはなると思います。

回答No.1

直接的な回答にはなっていませんが、 その数十個のメニューは全てバラバラですか? ある程度グループ分けできませんか? グループ分けできるなら、グループのメニューのJMenuクラスを生成して、 JMenuクラスのadd(JMenuItem menuItem)メソッドで追加すればいいのでは? JMenuクラスはJMenuItemクラスのサブクラスなのでaddできますよ。 例 JMenu view = new JMenu("表示"); JMenu size = new JMenu("サイズ"); JMenuItem l = new JMenuItem("大"); JMenuItem m = new JMenuItem("中"); JMenuItem s = new JMneuItem("小"); size.add(l); size.add(m); size.add(s); view.add(size); これで例えばIEの[表示]ー[サイズ]ー[大]みたいなサブメニューみたいになります。 質問者さんの希望には答えられてませんが、いかがでしょう?

ym2
質問者

補足

pcbegginerさん、レスどうもです。 サブメニュー化は私も考えたのですが結局、サブメニューの中に 数十個のJMenuItemが移動するだけでサブメニューが画面から はみ出してしまうんですよねぇ。 それで何とかならないかなぁと思い、ここに質問した次第です。