- ベストアンサー
SwingのJMenuに大量のJMenuItemを配置した場合の表示方法
このカテゴリに初めて質問させて頂きます。使用しているJDKの バージョンは1.4.2です。 今、JavaのSwingを利用してGUIアプリケーションを作成している のですがJMenuに数十個のJMenuItemを配置させる必要があるの ですが、大量のJMenuItemをJMenuに配置すると画面からはみ出 してしまいます。 そこで、JMenuで表示させるJMenuItemの数を制限し、それ以外 のJMenuItemはスクロールのような形で表示できるようにしたい と思っているのですがこのような事は実現可能でしょうか?
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
こんばんは。 とりあえず、タイマーで動かすことにしてみました。 それっぽく、動きます。 ただ、適当に作ったので、表示するメニューの高さを適切に調整するとか、まだまだ作り込む余地があるのですが、ヒントにはなると思います。 それにしても、なんでこの機能が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(); } } }
その他の回答 (4)
- pcbeginner
- ベストアンサー率46% (261/560)
#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)
#3です。 試行錯誤をしていたので、MouseAdapterのクラス名が妙なことになってますね。 すみません。かえって混乱しますね。 最初は#2さんの言われるような方法を考えていたのですが、私の環境(J2SE5.0)でJMenuにJButtonを登録すると、ActionEventがトリガされなかったので、しかたないので、JMenuItemにかえました。 すると、クリックすると(当たり前の話ですが)メニューが消えてしまうので、マウスポインタが上に来ると、Timerをスタートさせて、Timerのイベントハンドラからスクロールさせるメソッドを呼ぶようにしました。 とりあえず、50個のメニューのうち30個を表示するようになっていますが、環境によって、ちょうど言い数は違ってくるので、これを動的に変えるようにしなくてはいけないのですが、めんどくさいのでやっていません。 そこら辺のことをちゃんと考えて、ScrollableMenu みたいなクラスを作っておけば、便利でいいのでしょうが・・・。 がんばってください。
ごく基本的な考え方だけですが。 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で表示非表示を切り替えているだけですが、スクロールした「感じ」にはなると思います。
- pcbeginner
- ベストアンサー率46% (261/560)
直接的な回答にはなっていませんが、 その数十個のメニューは全てバラバラですか? ある程度グループ分けできませんか? グループ分けできるなら、グループのメニューの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の[表示]ー[サイズ]ー[大]みたいなサブメニューみたいになります。 質問者さんの希望には答えられてませんが、いかがでしょう?
補足
pcbegginerさん、レスどうもです。 サブメニュー化は私も考えたのですが結局、サブメニューの中に 数十個のJMenuItemが移動するだけでサブメニューが画面から はみ出してしまうんですよねぇ。 それで何とかならないかなぁと思い、ここに質問した次第です。
お礼
ym2です。 PecoPlusさん、わざわざソースコードまで載せて頂いて感謝 です。こういうときにもTimerが使えるとは思いつきませんでした。 これで上手い具合にMenuItemの表示を制御できるようになりました。