# JMenu in Popup mit Navigation links und rechts.



## Romsl (4. Oktober 2006)

Hi,

ich habe schonmal was versucht, aber allerdings funktioniert das nicht ganz. Es sollte wie das JMenu (incl. JMenuItem) werden, das einen Pfeil auf der rechten Seite bekommt wenn dieses KindElemente enthält und bei Mouse Entered die neuen Menu Elemente öffnet. Das selbe brauche ich jetzt auch noch auf der rechten Seite (also beide Seiten).

Hier mal mein Code:


```
package de.tutorials.component;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

/**
 * TODO: document me
 * <p/>
 * <code>BrowseMenuItemExample</code>.
 * <p/>
 * User: Romsl
 * Date: 04.10.2006
 * Time: 12:27:15
 *
 * @author Roman R&auml;dle
 * @version $Revision$
 */
public class BrowseMenuItemExample {

    public static void main(String[] args) {
        final JFrame frame = new JFrame("BrowseMenuItemExample");

        frame.setSize(new Dimension(400, 300));

        final JPopupMenu menu = new JPopupMenu("MenuItem");
        menu.add(new BrowseMenuItem());

        //frame.addMouseListener();
        //frame.add(menu);
        frame.addMouseListener(new MouseAdapter() {
            /**
             * Invoked when the mouse has been clicked on a component.
             */
            public void mouseClicked(MouseEvent e) {

                if (SwingUtilities.isRightMouseButton(e)) {
                    menu.show(frame, e.getX(), e.getY());
                }
            }
        });

        frame.setVisible(true);
    }

    public enum Orientation {
        LEFT, RIGHT
    }

    static class BrowseMenuItem extends JComponent {

    private JCheckBox checkBox = new JCheckBox("Test");

    /**
     * Creates a <code>JMenuItem</code> with no set text or icon.
     */
    public BrowseMenuItem() {
        System.out.println("getLayout() = " + getLayout());

        setLayout(new BorderLayout());

        add(new Arrow(Orientation.LEFT), BorderLayout.WEST);
        add(checkBox, BorderLayout.CENTER);
        add(new Arrow(Orientation.RIGHT), BorderLayout.EAST);
    }

    class Arrow extends JComponent {

        private Polygon triangle;

        public Arrow(Orientation orientation) {

            switch (orientation) {
                case LEFT:
                    triangle = new Polygon(new int[]{0, 10, 10}, new int[]{5, 0, 10}, 3);
                    break;
                case RIGHT:
                    triangle = new Polygon(new int[]{10, 0, 0}, new int[]{5, 0, 10}, 3);
                    break;
            }

            addMouseListener(new MouseAdapter() {
                /**
                 * Invoked when the mouse enters a component.
                 */
                public void mouseEntered(MouseEvent e) {
                    JPopupMenu menu = new JPopupMenu();
                    menu.add(new JCheckBox("Test"));

                    menu.show(Arrow.this, e.getX(), e.getY());
                }
            });
        }

        /**
         * Calls the UI delegate's paint method, if the UI delegate
         * is non-<code>null</code>.  We pass the delegate a copy of the
         * <code>Graphics</code> object to protect the rest of the
         * paint code from irrevocable changes
         * (for example, <code>Graphics.translate</code>).
         * <p/>
         * If you override this in a subclass you should not make permanent
         * changes to the passed in <code>Graphics</code>. For example, you
         * should not alter the clip <code>Rectangle</code> or modify the
         * transform. If you need to do these operations you may find it
         * easier to create a new <code>Graphics</code> from the passed in
         * <code>Graphics</code> and manipulate it. Further, if you do not
         * invoker super's implementation you must honor the opaque property,
         * that is
         * if this component is opaque, you must completely fill in the background
         * in a non-opaque color. If you do not honor the opaque property you
         * will likely see visual artifacts.
         * <p/>
         * The passed in <code>Graphics</code> object might
         * have a transform other than the identify transform
         * installed on it.  In this case, you might get
         * unexpected results if you cumulatively apply
         * another transform.
         *
         * @param g the <code>Graphics</code> object to protect
         * @see #paint
         * @see javax.swing.plaf.ComponentUI
         */
        protected void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.fillPolygon(triangle);
        }

        /**
         * Returns the current width of this component.
         * This method is preferable to writing
         * <code>component.getBounds().width</code>, or
         * <code>component.getSize().width</code> because it doesn't cause any
         * heap allocations.
         *
         * @return the current width of this component
         */
        public int getWidth() {
            return 10;
        }

        /**
         * Returns the current height of this component.
         * This method is preferable to writing
         * <code>component.getBounds().height</code>, or
         * <code>component.getSize().height</code> because it doesn't cause any
         * heap allocations.
         *
         * @return the current height of this component
         */
        public int getHeight() {
            return checkBox.getHeight();
        }

        /**
         * Stores the width/height of this component into "return value"
         * <code>rv</code> and returns <code>rv</code>.
         * If <code>rv</code> is <code>null</code> a new <code>Dimension</code>
         * object is allocated.  This version of <code>getSize</code>
         * is useful if the caller wants to avoid allocating a new
         * <code>Dimension</code> object on the heap.
         *
         * @param rv the return value, modified to the component's size
         * @return <code>rv</code>
         */
        public Dimension getSize(Dimension rv) {
            return new Dimension(20, checkBox.getHeight());
        }

        /**
         * If the <code>preferredSize</code> has been set to a
         * non-<code>null</code> value just returns it.
         * If the UI delegate's <code>getPreferredSize</code>
         * method returns a non <code>null</code> value then return that;
         * otherwise defer to the component's layout manager.
         *
         * @return the value of the <code>preferredSize</code> property
         * @see #setPreferredSize
         * @see javax.swing.plaf.ComponentUI
         */
        public Dimension getPreferredSize() {
            return new Dimension(20, checkBox.getHeight());
        }
    }
}
}
```

Gruß

Romsl


----------



## Thomas Darimont (4. Oktober 2006)

Hallo!

Kleiner Tipp am Rande:

anstatt den Typ/Methoden Doclet-Kommentar zu kopieren solltest du besser die Anweisung:

```
/**
* {@inheritdoc }
*/
```
verwenden. Dadurch wird javadoc angewiesen den Kommentar aus dem in der Verbungshierachie direkt vorgehenden Element zu ziehen.

Gruß Tom


----------



## flashray (4. Oktober 2006)

Hallo Romsl,

was genau funktioniert nicht? Du hast je ein Pfeil auf beiden Seiten wie gewollt. Beide reagieren. Sollen unterschiedliche Untermenüs geöffnet werden wenn links oder rechts aktiviert wird?


Vg Erdal


----------



## Romsl (4. Oktober 2006)

Hi,

ja es sollen unterschiedliche Menüs sein. Das ist aber nicht das Problem, sondern das bereits geöffnete Menü soll auf offen bleiben. So wie man das aus den üblichen Kontextmenüs kennt.

Gruß
  -- Romsl


----------



## flashray (4. Oktober 2006)

Hallo Romsl,

ich habe leider keine vollständige Lösung gefunden. Was ich aber rausgefunden habe ist, das das alte Menu verschwindet weil du kein JMenu sondern ein JComponent einfügst.

Ich habe mich etwas daran versucht, aber nicht ganz geschafft. Man müsste irgendwie das JMenu gescheit überschreiben. Jedoch ist die Klasse JMenu mit seinen 1200 Zeilen Code mit meinen Swing Kenntnissen nicht überschaubar.


```
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.*;

public class JSuperPopupMenuUser extends JFrame {

	private JSuperPopupMenu spm = new JSuperPopupMenu("SuperPopupMenu");

	public JSuperPopupMenuUser() {
		this.setTitle(this.getClass().getCanonicalName());
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setAlwaysOnTop(true);
		this.setLocationByPlatform(true);
		this.setSize(320, 480);

		this.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (SwingUtilities.isRightMouseButton(e)) {
					spm.show(JSuperPopupMenuUser.this, e.getX(), e.getY());
				}
			}
		});

		this.setVisible(true);
	}

	public static void main(String[] args) {
		new JSuperPopupMenuUser();
	}

	class JSuperPopupMenu extends JPopupMenu {

		private JMenu menuA = new JMenu("A");

		private JExtendedMenu menuB = new JExtendedMenu("B", "C");

		private JMenuItem mItem1 = new JMenuItem("1");

		private JMenuItem mItem2 = new JMenuItem("2");

		private JMenuItem mItem3 = new JMenuItem("3");

		private JMenuItem mItem4 = new JMenuItem("4");

		private JMenuItem mItem5 = new JMenuItem("5");

		private JMenuItem mItem6 = new JMenuItem("6");

		public JSuperPopupMenu(String label) {
			super(label);

			this.add(mItem1);
			this.add(menuA);
			this.add(menuB);
			this.add(mItem6);

			menuA.add(mItem2);
			menuA.add(mItem3);

			menuB.addLeft(mItem4);
			menuB.addRight(mItem5);
		}
	}

	class JExtendedMenu extends JMenu {

		private Dimension d;

		private JMenu menuL;

		private JMenu menuR;

		private JLabel label = new JLabel("|");

		public JExtendedMenu(String l, String r) {
			menuL = new JMenu(l);
			menuR = new JMenu(r);
			menuL.setOpaque(true);
			menuR.setOpaque(true);

			this.setLayout(new BorderLayout());
			this.add(menuL, BorderLayout.WEST);
			this.add(label, BorderLayout.CENTER);
			this.add(menuR, BorderLayout.EAST);
			this.doLayout();

			d = new Dimension(80, 20);

			this.setPreferredSize(d);
			this.setMinimumSize(d);
		}

		public void addLeft(JMenuItem mItem) {
			menuL.add(mItem);
		}

		public void addRight(JMenuItem mItem) {
			menuR.add(mItem);
		}
	}
}
```


Vg Erdal


----------



## Romsl (4. Oktober 2006)

Hi flashray.

meiner Meinung nach hat das Schließen nichts mit der JComponent zu tun. Eher liegt es daran, dass der MouseListener ein neues JPopupMenu öffnet und das Alte (wahrscheinlich irgendwo registriert) automatisch geschlossen wird.

Gruß
  -- Romsl


----------



## flashray (4. Oktober 2006)

Hallo Romsl,

eben das ist ja meine Idee. Ein JMenu bzw. ein JMenuItem wird automatisch registriert, und gehört zum ursprünglichen JPopupMenu. Wenn du aber eine gänzlich neue Komponente abgeleitet von JComponent schreibst, musst du das registrieren manuell selbst machen. Ich wüsste aber nicht wie und wo. Wenn du aber eine Klasse schreibst die von JMenu erbt wird die Registrierung überflüssig, da sie automatisch geschieht.

Wie dem auch sei, ist eine komplizierte Angelegenheit, wenn man nicht weiß wie man rangehen soll.

Du könntest ja mal jemanden anschreiben, der professionell mit Swing  zu tun hat. So Leute wie die erweiterte Komponenten zu Swing schreiben oder Look and Feels für Swing implementieren.


Vg Erdal


----------



## flashray (5. Oktober 2006)

Hallo Romsl,

ich habe etwas gebastelt, was nicht genau dem enstpricht was du möchtest, aber schon etwas näher kommt - denke ich.


```
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.*;

public class JExtendedMenuUser extends JFrame {

	private JPopupMenu jpm = new JPopupMenu();

	public JExtendedMenuUser() {
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setSize(480, 640);
		this.setAlwaysOnTop(true);
		this.setLocationByPlatform(true);

		JMenu A = new JMenu("SWT");
		A.add("Dialog");
		A.add("Widget");

		JExtendedMenu B = new JExtendedMenu("Swing", "AWT");

		JMenu D = new JMenu("JTextComponent");
		B.addLeft(new JMenuItem("JFrame"));
		B.addLeft(D);
		B.addLeft(new JMenuItem("JDialog"));
		D.add(new JMenuItem("JTextPane"));
		D.add(new JMenuItem("JTextArea"));
		D.add(new JMenuItem("JTextField"));

		JMenu E = new JMenu("TextComponent");
		B.addRight(new JMenuItem("Frame"));
		B.addRight(new JMenuItem("Dialog"));
		B.addRight(E);
		E.add(new JMenuItem("TextArea"));
		E.add(new JMenuItem("TextField"));

		jpm.add(A);
		jpm.add(B);
		jpm.add(new JMenuItem("SwingWT"));

		this.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (SwingUtilities.isRightMouseButton(e)) {
					jpm.show(JExtendedMenuUser.this, e.getX(), e.getY());
				}
			}
		});

		this.setVisible(true);
	}

	public static void main(String[] args) {
		new JExtendedMenuUser();
	}

	class JExtendedMenu extends JMenu {

		private JMenu menuL;

		private JMenu menuR;

		public JExtendedMenu(String l, String r) {
			super(l + "|" + r);

			menuL = new JMenu(" " + l + " ");
			menuR = new JMenu(" " + r + " ");

			JPopupMenu pm = getPopupMenu();
			pm.setLayout(new BoxLayout(pm, BoxLayout.X_AXIS));
			setMinimumSize(getPreferredSize());
			pm.add(menuL);
			pm.add(new JLabel("|"));
			pm.add(menuR);

			menuL.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
		}

		public void setPopupMenuVisible(boolean b) {
			boolean isVisible = isPopupMenuVisible();
			if (b != isVisible) {
				if ((b == true) && isShowing()) {
					int x = 0;
					int y = 0;
					Container parent = getParent();
					if (parent instanceof JPopupMenu) {
						x = -getWidth() / 2;
						y = 0;
					} else {
						x = - getWidth() / 2;
						y = 0;
					}
					getPopupMenu().show(this, x, y);
				} else {
					getPopupMenu().setVisible(false);
				}
			}
		}

		public void addLeft(JMenuItem mItem) {
			menuL.add(mItem);
		}

		public void addRight(JMenuItem mItem) {
			menuR.add(mItem);
		}

		public void removeLeft(JMenuItem mItem) {
			menuL.remove(mItem);
		}

		public void removeRight(JMenuItem mItem) {
			menuR.remove(mItem);
		}
	}
}
```


Vg Erdal


----------



## flashray (7. Oktober 2006)

Hallo Romsl,

hier nochmal ein anderer Ansatz der aber wieder leider unvollständig ist. Ich glaube ich weiss jetzt warum das alte Menu in deinem Beispiel schließt wenn das linke oder rechte Untermenü geöffnet wird. Weil das neue linke oder rechte eben kein Untermenü ist, sondern einem eigenen JPopupMenu gehört den du im MouseListener extra erzeugst. Somit hat dieser keinen Bezug zum vorherigen. Wenn ein neues anderes JPopupMenu geöffnet wird, dann wird wohl Swing das alte schließen.



```
import java.awt.ComponentOrientation;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;

public class JDoubleMenuUser extends JFrame {

	private JPopupMenu jpm = new JPopupMenu();

	public JDoubleMenuUser() {
		this.setTitle(this.getClass().getCanonicalName());
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setSize(480, 640);
		this.setAlwaysOnTop(true);
		this.setLocationByPlatform(true);

		JMenu A = new JMenu("SWT");
		A.add("Dialog");
		A.add("Widget");

		JDoubleMenu B = new JDoubleMenu(jpm, "Swing", "AWT");

		JMenu D = new JMenu("JTextComponent");
		B.addLeft(new JMenuItem("JFrame"));
		B.addLeft(D);
		B.addLeft(new JMenuItem("JDialog"));
		D.add(new JMenuItem("JTextPane"));
		D.add(new JMenuItem("JTextArea"));
		D.add(new JMenuItem("JTextField"));

		JMenu E = new JMenu("TextComponent");
		B.addRight(new JMenuItem("Frame"));
		B.addRight(new JMenuItem("Dialog"));
		B.addRight(E);
		E.add(new JMenuItem("TextArea"));
		E.add(new JMenuItem("TextField"));

		jpm.add(A);
		jpm.add(B);
		jpm.add(new JMenuItem("SwingWT"));

		this.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (SwingUtilities.isRightMouseButton(e)) {
					jpm.show(JDoubleMenuUser.this, e.getX(), e.getY());
				}
			}
		});

		this.setVisible(true);
	}

	public static void main(String[] args) {
		new JDoubleMenuUser();
	}

	class JDoubleMenu extends JMenu {

		private JMenu jdm = this;

		private List<JMenuItem> left = new ArrayList<JMenuItem>();

		private List<JMenuItem> right = new ArrayList<JMenuItem>();

		private boolean isLeft = true;

		private MouseListener ml;

		public JDoubleMenu(JPopupMenu jpm, String l, String r) {
			super("\u25C4 " + l + "  |  " + r + " \u25BA");

			ml = new MouseAdapter() {
				public void mouseEntered(MouseEvent e) {
					createMenu();
				}
			};
			this.addMouseListener(ml);
		}

		private void createLeftMenu() {
			jdm.removeAll();
			jdm.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
			for (JMenuItem jmi : left) {
				jdm.add(jmi);
			}
		}

		private void createRightMenu() {
			jdm.removeAll();
			jdm.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
			for (JMenuItem jmi : right) {
				jdm.add(jmi);
			}
		}

		private void createMenu() {
			isLeft = isLeft();
			if (isLeft)
				createLeftMenu();
			else
				createRightMenu();
		}

		private boolean isLeft() {
			if (this.getMousePosition().x < this.getWidth() / 2)
				return true;
			else
				return false;
		}

		public void addLeft(JMenuItem mItem) {
			left.add(mItem);
		}

		public void addRight(JMenuItem mItem) {
			right.add(mItem);
		}

		public void removeLeft(JMenuItem mItem) {
			left.remove(mItem);
		}

		public void removeRight(JMenuItem mItem) {
			right.remove(mItem);
		}

		public void addLeft(JMenu menu) {
			left.add(menu);
		}

		public void addRight(JMenu menu) {
			right.add(menu);
		}

		public void removeLeft(JMenu menu) {
			left.remove(menu);
		}

		public void removeRight(JMenu menu) {
			right.remove(menu);
		}
	}
}
```


Vg Erdal


----------



## Romsl (7. Oktober 2006)

Hi,

Danke erstmal für die vielen Beispiele. Aber Du hast das vielleicht nicht richtig verstanden. Es soll nur ein Eintrag pro PopupMenuItem sein. Also nicht eines links und eines rechts. Ich möchte dann, dass dieses eine links und rechts Pfeile hat wobei jedesmal ein Menu erweitert wird (so wie jetzt auch). Es sind aber nicht identische Menüs die geöffnet werden sollen.

Gruß
  -- Romsl


----------



## flashray (7. Oktober 2006)

Hallo Romsl,

wahrlich das ist sehr kreativ  !

Wieso hat das Menu "nach Subkontinenten" auf beiden Seiten Pfeile? Das Menu "nach Ländern" jedoch nur auf einer Seite?


Vg Erdal


//edit


Hallo Romsl,

hab noch zwei Vorschläge. Das waren dann aber die letzten  . 

Die erste Alternative folgt einen etwas anderen Weg, da Swing keine JCheckBoxMenu Komponente bereitstelt, die unbedingt notwendig ist.

Das zweite Beispiel ist sehr sehr nahe an deiner Vorstellung, vielleicht sogar genau so wie du es dir vorgestellt hattest.

Alternative 1:

```
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.*;

public class JModifiedMenuUser extends JFrame {

	private JPopupMenu pm = new JPopupMenu();

	public JModifiedMenuUser() {
		this.setTitle(this.getClass().getSimpleName());
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setSize(480, 640);
		this.setAlwaysOnTop(true);
		this.setLocationByPlatform(true);

		JBothArrowCheckBoxMenuItem bacbm1 = new JBothArrowCheckBoxMenuItem(
				"Afrika");
		JBothArrowCheckBoxMenuItem bacbm2 = new JBothArrowCheckBoxMenuItem(
				"Asien");
		JBothArrowCheckBoxMenuItem bacbm3 = new JBothArrowCheckBoxMenuItem(
				"Europa");

		JBothArrowCheckBoxMenuItem bacbm31 = new JBothArrowCheckBoxMenuItem(
				"Nordeuropa");
		JBothArrowCheckBoxMenuItem bacbm32 = new JBothArrowCheckBoxMenuItem(
				"Osteuropa");
		JBothArrowCheckBoxMenuItem bacbm33 = new JBothArrowCheckBoxMenuItem(
				"Westeuropa");

		JMenu jm1 = new JMenu("Auswahl");
		JMenu jm2 = new JMenu("Auswahl");

		pm.add(new JMenuItem("nach Kontinenten"));
		pm.addSeparator();
		pm.add(new JCheckBoxMenuItem("Check/Uncheck all"));
		pm.addSeparator();
		pm.add(bacbm1);
		pm.add(bacbm2);
		pm.add(bacbm3);
		pm.addSeparator();
		pm.add(jm1);
		pm.addSeparator();
		pm.add(new JButton("Filtern"));

		jm1.add(new JMenuItem("nach Subkontinenten"));
		jm1.addSeparator();
		jm1.add(new JCheckBoxMenuItem("Check/Uncheck all"));
		jm1.addSeparator();
		jm1.add(bacbm31);
		jm1.add(bacbm32);
		jm1.add(bacbm33);
		jm1.addSeparator();
		jm1.add(jm2);
		jm1.addSeparator();
		jm1.add(new JButton("Filtern"));

		jm2.add(new JMenuItem("nach Ländern"));
		jm2.addSeparator();
		jm2.add(new JCheckBoxMenuItem("Check/Uncheck all"));
		jm2.addSeparator();
		jm2.add(new JLeftArrowCheckBoxMenuItem("Dänemark"));
		jm2.add(new JLeftArrowCheckBoxMenuItem("Finnland"));
		jm2.add(new JLeftArrowCheckBoxMenuItem("Island"));
		jm2.add(new JLeftArrowCheckBoxMenuItem("Norwegen"));
		jm2.add(new JLeftArrowCheckBoxMenuItem("Schweden"));
		jm2.addSeparator();
		jm2.add(new JButton("Filtern"));

		this.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (SwingUtilities.isRightMouseButton(e)) {
					pm.show(JModifiedMenuUser.this, e.getX(), e.getY());
				}
			}
		});

		this.setVisible(true);
	}

	public static void main(String[] args) {
		new JModifiedMenuUser();
	}

	class JBothArrowCheckBoxMenuItem extends JCheckBoxMenuItem {

		public JBothArrowCheckBoxMenuItem(String s) {
			super(s);
			this.setBorder(BorderFactory.createEmptyBorder(2, 20, 2, 2));
		}

		public void paint(Graphics g) {
			super.paint(g);
			g.translate(7, 7);
			g.drawLine(4, 0, 4, 7);
			g.drawLine(3, 1, 3, 6);
			g.drawLine(2, 2, 2, 5);
			g.drawLine(1, 3, 1, 4);

			g.translate(this.getWidth() - 21, 0);
			g.drawLine(0, 0, 0, 7);
			g.drawLine(1, 1, 1, 6);
			g.drawLine(2, 2, 2, 5);
			g.drawLine(3, 3, 3, 4);
		}
	}

	class JLeftArrowCheckBoxMenuItem extends JCheckBoxMenuItem {
		public JLeftArrowCheckBoxMenuItem(String s) {
			super(s);
			this.setBorder(BorderFactory.createEmptyBorder(2, 20, 2, 2));
		}

		public void paint(Graphics g) {
			super.paint(g);
			g.translate(7, 7);
			g.drawLine(4, 0, 4, 7);
			g.drawLine(3, 1, 3, 6);
			g.drawLine(2, 2, 2, 5);
			g.drawLine(1, 3, 1, 4);
		}
	}
}
```


Alternative 2:

```
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.*;

public class JCheckBoxMenuUser extends JFrame {

	private JCheckBoxPopupMenu pm = new JCheckBoxPopupMenu();

	public JCheckBoxMenuUser() {
		this.setTitle(this.getClass().getSimpleName());
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setSize(480, 640);
		this.setAlwaysOnTop(true);
		this.setLocationByPlatform(true);

		JCheckBoxMenu cbm1 = new JCheckBoxMenu("Afrika");
		cbm1.add(new JMenuItem("nach Ländern"));
		cbm1.addSeparator();
		cbm1.add(new JCheckBoxMenuItem("Check/Uncheck all"));
		cbm1.addSeparator();
		cbm1.add(new JLeftArrowCheckBoxMenuItem("Guinea"));
		cbm1.add(new JLeftArrowCheckBoxMenuItem("Saudi Arabien"));
		cbm1.add(new JLeftArrowCheckBoxMenuItem("Uganda"));
		cbm1.addSeparator();
		cbm1.add(new JButton("Filtern"));

		JCheckBoxMenu cbm2 = new JCheckBoxMenu("Asien");
		cbm2.add(new JMenuItem("nach Ländern"));
		cbm2.addSeparator();
		cbm2.add(new JCheckBoxMenuItem("Check/Uncheck all"));
		cbm2.addSeparator();
		cbm2.add(new JLeftArrowCheckBoxMenuItem("China"));
		cbm2.add(new JLeftArrowCheckBoxMenuItem("Russland"));
		cbm2.add(new JLeftArrowCheckBoxMenuItem("Türkei"));
		cbm2.addSeparator();
		cbm2.add(new JButton("Filtern"));

		JCheckBoxMenu cbm3 = new JCheckBoxMenu("Europa");
		JCheckBoxMenu cbm31 = new JCheckBoxMenu("Nordeuropa");
		JCheckBoxMenu cbm32 = new JCheckBoxMenu("Osteuropa");
		JCheckBoxMenu cbm33 = new JCheckBoxMenu("Westeuropa");

		cbm3.add(new JMenuItem("nach Subkontinenten"));
		cbm3.addSeparator();
		cbm3.add(new JCheckBoxMenuItem("Check/Uncheck all"));
		cbm3.addSeparator();
		cbm3.addCheckBoxMenu(cbm31);
		cbm3.addCheckBoxMenu(cbm32);
		cbm3.addCheckBoxMenu(cbm33);
		cbm3.addSeparator();
		cbm3.add(new JButton("Filtern"));

		cbm31.add(new JMenuItem("nach Ländern"));
		cbm31.addSeparator();
		cbm31.add(new JCheckBoxMenuItem("Check/Uncheck all"));
		cbm31.addSeparator();
		cbm31.add(new JLeftArrowCheckBoxMenuItem("Dänemark"));
		cbm31.add(new JLeftArrowCheckBoxMenuItem("Finnland"));
		cbm31.add(new JLeftArrowCheckBoxMenuItem("Island"));
		cbm31.add(new JLeftArrowCheckBoxMenuItem("Norwegen"));
		cbm31.add(new JLeftArrowCheckBoxMenuItem("Schweden"));
		cbm31.addSeparator();
		cbm31.add(new JButton("Filtern"));

		cbm32.add(new JMenuItem("nach Ländern"));
		cbm32.addSeparator();
		cbm32.add(new JCheckBoxMenuItem("Check/Uncheck all"));
		cbm32.addSeparator();
		cbm32.add(new JLeftArrowCheckBoxMenuItem("Griechenland"));
		cbm32.add(new JLeftArrowCheckBoxMenuItem("Polen"));
		cbm32.add(new JLeftArrowCheckBoxMenuItem("Türkei"));
		cbm32.addSeparator();
		cbm32.add(new JButton("Filtern"));

		cbm33.add(new JMenuItem("nach Ländern"));
		cbm33.addSeparator();
		cbm33.add(new JCheckBoxMenuItem("Check/Uncheck all"));
		cbm33.addSeparator();
		cbm33.add(new JLeftArrowCheckBoxMenuItem("Deutschland"));
		cbm33.add(new JLeftArrowCheckBoxMenuItem("Frankreich"));
		cbm33.add(new JLeftArrowCheckBoxMenuItem("Spanien"));
		cbm33.addSeparator();
		cbm33.add(new JButton("Filtern"));

		pm.add(new JMenuItem("nach Kontinenten"));
		pm.addSeparator();
		pm.add(new JCheckBoxMenuItem("Check/Uncheck all"));
		pm.addSeparator();
		pm.addCheckBoxMenu(cbm1);
		pm.addCheckBoxMenu(cbm2);
		pm.addCheckBoxMenu(cbm3);
		pm.addSeparator();
		pm.add(new JButton("Filtern"));

		this.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (SwingUtilities.isRightMouseButton(e)) {
					pm.show(JCheckBoxMenuUser.this, e.getX(), e.getY());
				}
			}
		});

		this.setVisible(true);
	}

	public static void main(String[] args) {
		new JCheckBoxMenuUser();
	}

	class JCheckBoxPopupMenu extends JPopupMenu {

		private GridBagConstraints c = new GridBagConstraints();

		private int y = 0;

		public JCheckBoxPopupMenu() {
			this.setLayout(new GridBagLayout());
		}

		public JMenuItem add(JMenuItem mItem) {
			c.gridx = 0;
			c.gridy = y;
			c.gridwidth = 2;
			c.weightx = 1;
			c.weighty = 1;
			c.fill = c.BOTH;
			this.add(mItem, c);
			y++;
			return mItem;
		}

		public Component add(Component comp) {
			c.gridx = 0;
			c.gridy = y;
			c.gridwidth = 2;
			c.weightx = 1;
			c.weighty = 1;
			c.fill = c.NONE;
			this.add(comp, c);
			y++;
			return comp;
		}

		public void addSeparator() {
			c.gridx = 0;
			c.gridy = y;
			c.gridwidth = 2;
			c.weightx = 1;
			c.weighty = 1;
			c.fill = c.BOTH;
			this.add(new JSeparator(JSeparator.HORIZONTAL), c);
			y++;
		}

		public void addCheckBoxMenu(JMenu menu) {
			JCheckBoxMenuItem cbm = new JCheckBoxMenuItem(" ") {
				{
					Dimension d = new Dimension(40, 20);
					this.setPreferredSize(d);
					this.setMinimumSize(d);
					this
							.setBorder(BorderFactory.createEmptyBorder(2, 20,
									2, 2));
				}

				public void paint(Graphics g) {
					super.paint(g);
					g.translate(5, 5);
					g.drawLine(4, 0, 4, 7);
					g.drawLine(3, 1, 3, 6);
					g.drawLine(2, 2, 2, 5);
					g.drawLine(1, 3, 1, 4);
				}
			};
			c.gridx = 0;
			c.gridy = y;
			c.fill = c.VERTICAL;
			c.weightx = 1;
			c.weighty = 1;
			c.gridwidth = 1;
			this.add(cbm, c);
			c.gridx = 1;
			c.gridy = y;
			c.fill = c.BOTH;
			c.weightx = 1;
			c.weighty = 1;
			c.gridwidth = 1;
			y++;
			this.add(menu, c);
		}
	}

	class JCheckBoxMenu extends JMenu {

		private JPopupMenu pm = this.getPopupMenu();

		private GridBagConstraints c = new GridBagConstraints();

		private int y = 0;

		public JCheckBoxMenu(String s) {
			super(s);
			pm.setLayout(new GridBagLayout());
		}

		public JMenuItem add(JMenuItem mItem) {
			c.gridx = 0;
			c.gridy = y;
			c.gridwidth = 2;
			c.weightx = 1;
			c.weighty = 1;
			c.fill = c.BOTH;
			pm.add(mItem, c);
			y++;
			return mItem;
		}

		public Component add(Component comp) {
			c.gridx = 0;
			c.gridy = y;
			c.gridwidth = 2;
			c.weightx = 1;
			c.weighty = 1;
			c.fill = c.NONE;
			pm.add(comp, c);
			y++;
			return comp;
		}

		public void addSeparator() {
			c.gridx = 0;
			c.gridy = y;
			c.gridwidth = 2;
			c.weightx = 1;
			c.weighty = 1;
			c.fill = c.BOTH;
			pm.add(new JSeparator(JSeparator.HORIZONTAL), c);
			y++;
		}

		public void addCheckBoxMenu(JMenu menu) {
			JCheckBoxMenuItem cbm = new JCheckBoxMenuItem(" ") {
				{
					Dimension d = new Dimension(40, 20);
					this.setPreferredSize(d);
					this.setMinimumSize(d);
					this
							.setBorder(BorderFactory.createEmptyBorder(2, 20,
									2, 2));
				}

				public void paint(Graphics g) {
					super.paint(g);
					g.translate(5, 5);
					g.drawLine(4, 0, 4, 7);
					g.drawLine(3, 1, 3, 6);
					g.drawLine(2, 2, 2, 5);
					g.drawLine(1, 3, 1, 4);
				}
			};
			c.gridx = 0;
			c.gridy = y;
			c.fill = c.VERTICAL;
			c.weightx = 1;
			c.weighty = 1;
			c.gridwidth = 1;
			pm.add(cbm, c);
			c.gridx = 1;
			c.gridy = y;
			c.fill = c.BOTH;
			c.weightx = 1;
			c.weighty = 1;
			c.gridwidth = 1;
			y++;
			pm.add(menu, c);
		}
	}

	class JLeftArrowCheckBoxMenuItem extends JCheckBoxMenuItem {
		public JLeftArrowCheckBoxMenuItem(String s) {
			super(s);
			this.setBorder(BorderFactory.createEmptyBorder(2, 20, 2, 2));
		}

		public void paint(Graphics g) {
			super.paint(g);
			g.translate(5, 5);
			g.drawLine(4, 0, 4, 7);
			g.drawLine(3, 1, 3, 6);
			g.drawLine(2, 2, 2, 5);
			g.drawLine(1, 3, 1, 4);
		}
	}
}
```


Vg Erdal


----------



## flashray (12. Oktober 2006)

Hallo Romsl,

hast du dir meine letzten Codebeispiele angeschaut insbesondere das JCheckBoxMenuUser?


Vg Erdal


----------



## Romsl (12. Oktober 2006)

Hi flashray,

Danke für die vielen Beispiele. Die letzten Beiden waren gut, wobei das Aussehen des ersten mit der Funktion des zweiten die Lösung ist 

Gruß
  -- Romsl


----------



## flashray (12. Oktober 2006)

Hallo Romsl,

das i-Tüpfelchen überlass ich dir  !

Darf ich fragen ob du an einer erweiterten Swingkomponente arbeitest? Oder eine (geographische) Anwendung schreibst?


Vg Erdal


----------



## Romsl (12. Oktober 2006)

Hi,

das wird eine, bzw. ist eine im Anfgangsstadium bestehende, Anwendung um OLAP Daten zu explorieren und analysieren.

Gruß
  -- Romsl


----------

