/*http://forum.java.sun.com/thread.jsp?forum=57&thread=123183
Re: scrollable JMenu? 
Author: frankm29 
In Reply To: scrollable JMenu?  Apr 30, 2002 6:35 PM   Reply 4 of 5   
 
 
Here's a cl*** I made to make JMenu scrollable, use it if it can help you...Frank
*/import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.*;// This cl*** implements a scrollable JMenu
// This cl*** was hacked out in a couple of hours, and is meant to be used
// such that you create an instance, add all the items you want, and then throw it away and
// create a new one if you want the menu items to change (there is no remove/insertAt functionality)
// Use "addScrollableItems(JMenuItem j)" to add all of the items
// You can change MAX_ITEMS_TO_DISPLAY to whatever you want, I used 10 because it seems to always fit on screen
// I have NOT tested this cl*** very much to see if it loses items, etc, ***USE AT YOUR OWN RISK***
// Feel free to use and modify. I'll probably add a thread on the up & down scrollers to make them scroll automatically (as long as mouse-over),
// let me know if you want it via email ([email protected]).
//
// This cl*** should only be used until SUN makes a real scrollable JMenupublic cl*** ScrollableJMenu extends JMenu implements MouseListener{
ScrollUpOrDownButtonItem scrollUp, scrollDown;
Vector vtrScrollableMenuItems;
static final int MAX_ITEMS_TO_DISPLAY = 10;
int beginIndexIntoVector;public ScrollableJMenu(String strMenuTitle){
setText(strMenuTitle);scrollUp = new ScrollUpOrDownButtonItem("up");
add(scrollUp);
removeAllMouseListeners(scrollUp);
scrollUp.addMouseListener(this);
scrollUp.addMouseListener(scrollUp);scrollDown = new ScrollUpOrDownButtonItem("down");
add(scrollDown);
removeAllMouseListeners(scrollDown);
scrollDown.addMouseListener(this);
scrollDown.addMouseListener(scrollDown);vtrScrollableMenuItems = new Vector();
beginIndexIntoVector = 0;
}public void addScrollableItem(JMenuItem jmiMenuItemToAdd){
vtrScrollableMenuItems.addElement(jmiMenuItemToAdd);
if ( vtrScrollableMenuItems.size() <= MAX_ITEMS_TO_DISPLAY){
insert(jmiMenuItemToAdd, vtrScrollableMenuItems.size());
}
else{
scrollDown.enableScroll(true);
}
}public void removeAllMouseListeners(AbstractButton b){
MouseListener[] allMouseListeners = b.getMouseListeners();
for (int i = 0; i < allMouseListeners.length; i++){
b.removeMouseListener(allMouseListeners);
}
}public void scrollUpClicked(){
if ( (vtrScrollableMenuItems.size() <= MAX_ITEMS_TO_DISPLAY) || (beginIndexIntoVector == 0) ){ // no need to scroll
return;
}
remove(MAX_ITEMS_TO_DISPLAY);
insert((JMenuItem)(vtrScrollableMenuItems.elementAt(--beginIndexIntoVector)), 1);
getPopupMenu().validate();
getPopupMenu().pack();scrollDown.enableScroll(true);
if (beginIndexIntoVector == 0){
scrollUp.enableScroll(false);
}
}public void scrollDownClicked(){
if ( (vtrScrollableMenuItems.size() <= MAX_ITEMS_TO_DISPLAY) ||
(beginIndexIntoVector + MAX_ITEMS_TO_DISPLAY == vtrScrollableMenuItems.size()) ) { // no need to scroll
return;
}
remove(1);
insert((JMenuItem)(vtrScrollableMenuItems.elementAt(beginIndexIntoVector + MAX_ITEMS_TO_DISPLAY)), MAX_ITEMS_TO_DISPLAY);
beginIndexIntoVector++;
getPopupMenu().validate();
getPopupMenu().pack();scrollUp.enableScroll(true);
if ( (beginIndexIntoVector + MAX_ITEMS_TO_DISPLAY == vtrScrollableMenuItems.size())){
scrollDown.enableScroll(false);
}
}public void mouseClicked(MouseEvent me){
Object eventSource = me.getSource();
if (eventSource == scrollUp){
scrollUpClicked();
}
else if (eventSource == scrollDown){
scrollDownClicked();
}
}
public void mousePressed(MouseEvent me){}
public void mouseReleased(MouseEvent me){}
public void mouseEntered(MouseEvent me){}
public void mouseExited(MouseEvent me){}cl*** ScrollUpOrDownButtonItem extends JMenuItem implements MouseListener{
String strDirection;
Polygon directionIndicator;
boolean blnMouseOver;
boolean blnEnableScroll;
public ScrollUpOrDownButtonItem(String strDirection){ // direction can be "up" or "down"
this.strDirection = strDirection;
directionIndicator = new Polygon();
blnMouseOver = false;
setPreferredSize(new Dimension(10, 15));
blnEnableScroll = false;
//addMouseListener(this); // can't do it here because i'm dumping the JRE's mouse listeners (above) and it would get this one too
}public void enableScroll(boolean blnEnableScroll){
this.blnEnableScroll = blnEnableScroll;
repaint();
}public void paintComponent(Graphics g){
super.paintComponent(g);
if (blnMouseOver){
g.setColor(Color.blue);
}
if (! blnEnableScroll){
g.setColor(Color.gray);
}
directionIndicator.reset();
if (strDirection.equals("up")){
directionIndicator.addPoint((int)(getSize().width/2.0 - 7.0 + 0.5), (int)(getSize().height/2.0 + 5.0 + 0.5));
directionIndicator.addPoint((int)(getSize().width/2.0 + 7.0 + 0.5), (int)(getSize().height/2.0 + 5.0 + 0.5));
directionIndicator.addPoint((int)(getSize().width/2.0 + 0.5), (int)(getSize().height/2.0 - 5.0 + 0.5));
}
else{
directionIndicator.addPoint((int)(getSize().width/2.0 - 7.0 + 0.5), (int)(getSize().height/2.0 - 5.0 + 0.5));
directionIndicator.addPoint((int)(getSize().width/2.0 + 7.0 + 0.5), (int)(getSize().height/2.0 - 5.0 + 0.5));
directionIndicator.addPoint((int)(getSize().width/2.0 + 0.5), (int)(getSize().height/2.0 + 5.0 + 0.5));
}
g.fillPolygon(directionIndicator);
}public void mouseEntered(MouseEvent me){
blnMouseOver = true;
repaint();
}
public void mouseExited(MouseEvent me){
blnMouseOver = false;
repaint();
}
public void mousePressed(MouseEvent me){}
public void mouseReleased(MouseEvent me){}
public void mouseClicked(MouseEvent me){}}}  
 

解决方案 »

  1.   

    //http://forum.java.sun.com/thread.jsp?forum=257&thread=114216
    import java.awt.*;
    import java.awt.event.*; 
    import javax.swing.*;
    import javax.swing.event.*; public class PopTest extends JFrame 
    implements ListSelectionListener, MenuListener, AdjustmentListener
    {
    public PopTest()
    {
    addWindowListener(new WindowAdapter() {
    public void windowClosed(WindowEvent e) {
    System.exit(0);
    }
    });
    JMenuBar mbar = new JMenuBar();
    list = new JList(items);
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    list.addListSelectionListener(this);
    scroll = new JScrollPane(list);
    scroll.getVerticalScrollBar().addAdjustmentListener(this);
    fruit = new ZMenu("Fruit");
    fruit.addMenuListener(this);
    fruit.add(scroll);
    mbar.add(fruit);
    setJMenuBar(mbar);
    l = new JLabel("<none>");
    getContentPane().setLayout(new FlowLayout());
    getContentPane().add(l);
    }public void valueChanged(ListSelectionEvent e) 
    {
    int selectedIndex = list.getMaxSelectionIndex();
    selection = (String)(list.getModel().getElementAt(selectedIndex));
    l.setText(selection);
    scrolling = false;
    fruit.fireMenuDeselected();}public void menuCanceled(MenuEvent e){} 
    public void menuDeselected(MenuEvent e)
    {
    if(!scrolling)
    {
    fruit.setPopupMenuVisible(false);
    scrolling = false;
    }
    else
    {
    fruit.setPopupMenuVisible(true);
    scrolling = false;
    }
    } public void menuSelected(MenuEvent e) 
    {
    fruit.setPopupMenuVisible(true);
    } public void adjustmentValueChanged(AdjustmentEvent e)
    {
    scrolling = true;}public static void main(String[] args)
    {
    PopTest p = new PopTest();
    p.setSize(320, 240);
    p.show();
    }JLabel l;
    JList list;
    JScrollPane scroll;
    ZMenu fruit;
    boolean scrolling =false;
    String selection;
    String[] items = {"Apple", "Cherry", "Strawberry", "Peach", "Banana", 
    "Plum", "Orange", "Grape", "Mango", "Raspberry", "Tangerine",
    "Pear", "Blueberry", "Papaya"};
    }
    class ZMenu extends JMenu
    {
    public ZMenu(String s){super(s);}
    public void fireMenuDeselected()
    {super.fireMenuDeselected();}
    }
      

  2.   


    import javax.swing.JMenuItem;
    import javax.swing.JMenu;
    /**http://forum.java.sun.com/thread.jsp?forum=257&thread=118940
     * Recursive JMenu, displays itself in multi menus when its size
    is larger than the 'max' value.
    * author Vincent Dupont
    * version 1.0
    * To do : compliance with other 'add()' methods form JMenu
    (add(Action), add(JMenuItem), etc)
    */
    public class ExtendedJMenu extends JMenu{  private int max=12;
      private int current=0;
      private ExtendedJMenu more =null;  /**Simple constructor*/
      public ExtendedJMenu(String s){
        super(s);
      }
      /**Core method*/
      public JMenuItem add(String s){
        current++;
        if (current>max){
          return getChildMenu().add(s);
        }//if (current>max){
        else {
          return super.add(s);
        }  }  /**Returns the child menu if any. Creates and add the new one if
    none previously set*/
      public ExtendedJMenu getChildMenu(){
        if (more==null) {
          more = new ExtendedJMenu("More...");
          add(more);
        }
        return more;  }
    }
      

  3.   

    Now I realize that it is not a good idea to make menu scrollable. Imaging that there are 1000 menuitems flying over your window.......Possible to modify the menu, such that, when user click or select, if menuitem morethan 15, then a dialog for selection, or combo appear just next to your mouse?
      

  4.   

    you may use tabpane for command selection
      

  5.   

    why not use more submenu to slove this problem?
      

  6.   

    come on masterz(), try to come out with a solution, i can make your reach six stars