# JPanel und JScrollPane



## MQue (24. Mrz 2009)

Hallo,

ich habe unteres Programm, welches auf einem JPanel, mittels Popup- Menü Buttons auf das JPanel hinzufügt.
Das JPanel ist im Viewport eines JScrollPane,
Ich wollte jetzt das Verhalten erreichen, wenn die scihtbare Fläche des JPanels mit JButtons voll ist, dass dann die Slider der JScrollPane sichtbar werden, 
Das ist mir nicht klar, wie ich das machen kann, 
das JPanel hat ja eine fixe Größe, dieses bekommt ja davon gar nichts mit, sodass sich die Slider der JScrollPane aktivieren könnten.
Wie kann man das realisieren, ich steh da ein bisschen auf der Leitung?
Vielen Dank,




```
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class Main {

    public Main() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JScrollPane sp = new JScrollPane();
        JPanel p = new JPanel();
        p.setPreferredSize(new Dimension(450, 450));
        p.setBackground(Color.RED);
        MyPopupMenu popup = new MyPopupMenu(p, sp, f);
        p.addMouseListener(popup);
        p.add(popup);
        sp.setViewportView(p);
        f.add(sp);
        f.setBounds(10, 10, 450, 450);
        f.setVisible(true);
        } 
    
    public static void main(String[] args) {
        new Main();
        }

    class MyPopupMenu extends PopupMenu implements MouseListener, ActionListener {

        private final MenuItem miAdd;
        private JPanel p;
        private JScrollPane sp;
        private JFrame f;

        public MyPopupMenu(JPanel p, JScrollPane sp, JFrame f) {
            this.p = p;
            this.sp = sp;
            this.f = f;
            miAdd = new MenuItem("Hinzufügen");
            miAdd.addActionListener(this);
            miAdd.setFont(new Font("Arial", 1, 12));
            add(miAdd);
            addSeparator();
            }    

        public void mousePressed(MouseEvent e) {
            if(SwingUtilities.isRightMouseButton(e) && e.getClickCount() == 1) {
                this.show(e.getComponent(), e.getX(), e.getY());
                }
            }

        public void actionPerformed(ActionEvent e) {
            JButton b = new JButton("test");
            b.setPreferredSize(new Dimension(200, 100));
            p.add(b);
            p.repaint();
            p.validate();
            sp.repaint();
            sp.validate();
            f.repaint();
            f.validate();
            }

        public void mouseReleased(MouseEvent e) {}

        public void mouseEntered(MouseEvent e) {}

        public void mouseExited(MouseEvent e) {}

        public void mouseClicked(MouseEvent e) {}
        }
}
```


----------



## diggaa1984 (24. Mrz 2009)

hm also ich vermute das dein Panel egal wieviele Buttons da drauf sollen fix in der Größe ist, so hast es ja auch beschrieben und so stehts ja auch im code (preferredSize). Was ich nun nich weiss, was passiert wenn die Fläche voll ist und neue Buttons drauf sollen.

Weiterhin setzt du dieses fixe Panel als Viewport des ScrollPane. Wenn sich die Größe des Panels nicht ändern kann, so gibts auch nie Bedarf Scrollbalken anzuzeigen, da die ScrollView immer das gesamte Panel anzeigen kann.

Was du vermutlich brauchst ist glaube eine minimale Panelgröße welche initial als ScrollView gesetzt werden kann. Sollte dann durch hinzufügen von Buttons das Panel größer werden, so merkt das das ScrollPane und dann können die ScrollBalken auch sichtbar werden (dazu am besten einfach den Konstruktor für JScrollPane nutzen).

[HIGHLIGHT="Java"]JScrollPane(Component view, int vsbPolicy, int hsbPolicy)
//VERTICAL_SCROLLBAR_AS_NEEDED oder VERTICAL_SCROLLBAR_AS_ALWAYS
//HORIZONTAL_SCROLLBAR_AS_NEEDED oder HORIZONTAL_SCROLLBAR_AS_ALWAYS[/HIGHLIGHT]

EDIT: grad am rumprobieren :d


----------



## max40 (24. Mrz 2009)

1. this.sp.revalidate(); reicht!
2. ich denke mal das man das FlowLayout dafür nicht so wie es ist verwenden kann! Denn wenn du die PreferredSize weglässt, gehen die eingefügten Componenten nur rechts aber nicht in die nächste Zeile! Ich denke das man es über das Layout hinbekommen muss, das das Panel nicht breiter wie das ScrollPane wird aber nach unten uneingeschränkt sich erweitern kann!


----------



## diggaa1984 (24. Mrz 2009)

jop die erkenntnis kann ich bestätigen 

vielleicht kannst du mit dem BoxLayout was erreichen. Könnte jedenfalls ne Fummelei werden sowas umzusetzen.


----------



## MQue (24. Mrz 2009)

max40 hat gesagt.:


> 2. ich denke mal das man das FlowLayout dafür nicht so wie es ist verwenden kann! Denn wenn du die PreferredSize weglässt, gehen die eingefügten Componenten nur rechts aber nicht in die nächste Zeile! Ich denke das man es über das Layout hinbekommen muss, das das Panel nicht breiter wie das ScrollPane wird aber nach unten uneingeschränkt sich erweitern kann!




Kann das jetzt auch bestätigen, da wird mir wohl nichts anderes Übrigbleiben als mir selber einen Layoutmanager zu schreiben, oder hat jemand noch eine besstere Idee mit einem StandardLayoutmanager?

vielen Dank,


----------



## diggaa1984 (24. Mrz 2009)

wie genau willst das panel denn gestalten (1 spalte, 2 spalten für komponenten)?

BoxLayout, senkrechtes FlowLayout, oder mit GridBagLayout rumspielen


----------



## max40 (24. Mrz 2009)

vielleicht nicht schön aber brauchbar! 

[HIGHLIGHT="Java"]import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class Main {

	public Main() {
		JFrame f = new JFrame();
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		final JScrollPane sp = new JScrollPane();
		final JPanel p = new JPanel();

		p.setBackground(Color.RED);
		MyPopupMenu popup = new MyPopupMenu(p, sp, f);
		p.addMouseListener(popup);
		p.add(popup);
		sp.setViewportView(p);

		sp.addComponentListener(new ComponentAdapter(){
			@Override
			public void componentResized(ComponentEvent e) {
				if (p.getComponentCount() > 0)
					Main.changeSize(p, (JComponent)p.getComponent(p.getComponentCount()-1));

			}
		});


		EventQueue.invokeLater(new Runnable(){
			@Override
			public void run() {
				p.setPreferredSize(new Dimension(sp.getWidth(), sp.getHeight()));
			}	
		});

		f.add(sp);
		f.setBounds(10, 10, 450, 450);
		f.setVisible(true);
	}


	/**
	 * Größe anpassen
	 * @param parent
	 * @param child
	 */
	static public void changeSize(JComponent parent, JComponent child){
		parent.setPreferredSize(new Dimension(parent.getParent().getWidth(), child.getY() + child.getHeight())); 
	}


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

	class MyPopupMenu extends PopupMenu implements MouseListener,
			ActionListener {

		private final MenuItem miAdd;
		private JPanel p;
		private JScrollPane sp;
		private JFrame f;

		public MyPopupMenu(JPanel p, JScrollPane sp, JFrame f) {
			this.p = p;
			this.sp = sp;
			this.f = f;
			miAdd = new MenuItem("Hinzufügen");
			miAdd.addActionListener(this);
			miAdd.setFont(new Font("Arial", 1, 12));
			add(miAdd);
			addSeparator();
		}

		public void mousePressed(MouseEvent e) {
			if (SwingUtilities.isRightMouseButton(e) && e.getClickCount() == 1) {
				this.show(e.getComponent(), e.getX(), e.getY());
			}
		}

		public void actionPerformed(ActionEvent e) {
			final JButton b = new JButton("test");
			b.setPreferredSize(new Dimension(200, 100));
			p.add(b);
			p.revalidate();


			EventQueue.invokeLater(new Runnable(){
				@Override
				public void run() {

					changeSize(p, b);

				}
			});

		}

		public void mouseReleased(MouseEvent e) {
		}

		public void mouseEntered(MouseEvent e) {
		}

		public void mouseExited(MouseEvent e) {
		}

		public void mouseClicked(MouseEvent e) {
		}
	}


}[/HIGHLIGHT]


----------



## MQue (25. Mrz 2009)

Hallo,

vielen Dank für den Code, ich hab jetzt das mit dem changeSize eingebaut.
Was jetzt passiert ist, wenn ich ein paar mal das Popupmenü "Hinzufügen" klicke, dann überlappen sich die JPanels,
könnte sich das vielleicht mal jemand ansehen, was da schief läuft (der untere Code ist lauffähig)
Vielen Dank,


```
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class Main {

    public Main() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JScrollPane sp = new JScrollPane();        
        JPanel p = new JPanel();
        p.setLayout( new BoxLayout(p, BoxLayout.PAGE_AXIS));
        p.setBackground(Color.RED);
        MyPopupMenu popup = new MyPopupMenu(p, sp, f);
        p.addMouseListener(popup);
        p.add(popup);
        sp.setViewportView(p);
        f.add(sp);
        f.setBounds(10, 10, 490, 490);
        f.setVisible(true);
        }

    public static void changeSize(JComponent parent, JComponent child) {
        parent.setPreferredSize(new Dimension(parent.getParent().getWidth(), child.getY()+child.getHeight()));
        }

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

    class MyPopupMenu extends PopupMenu implements MouseListener, ActionListener {

        private final MenuItem miAdd;
        private JPanel p;
        private JScrollPane sp;
        private JFrame f;

        public MyPopupMenu(JPanel p, JScrollPane sp, JFrame f) {
            this.p = p;
            this.sp = sp;
            this.f = f;
            miAdd = new MenuItem("Hinzufügen");
            miAdd.addActionListener(this);
            miAdd.setFont(new Font("Arial", 1, 12));
            add(miAdd);
            addSeparator();
            }

        public void mousePressed(MouseEvent e) {
            if(SwingUtilities.isRightMouseButton(e) && e.getClickCount() == 1) {
                this.show(e.getComponent(), e.getX(), e.getY());
                }
            }

        public void actionPerformed(ActionEvent e) {
            final JPanel panel = new JPanel();
            panel.setBorder(BorderFactory.createLineBorder(Color.GREEN));
            panel.setLayout(null);            
            JButton b1 = new JButton("Hallo1");
            b1.setAlignmentX(JButton.CENTER_ALIGNMENT);
            b1.setPreferredSize(new Dimension(40, 40));
            b1.setSize(40, 40);
            b1.setLocation(0, 0);
            JButton b2 = new JButton("Hallo2");
            b2.setAlignmentX(JButton.CENTER_ALIGNMENT);
            b2.setPreferredSize(new Dimension(40, 40));
            b2.setSize(40, 40);
            b2.setLocation(70, 70);
            p.setBackground(Color.GREEN);
            panel.setPreferredSize(new Dimension(100, 100));
            panel.setSize(100, 100);
            panel.setAlignmentX(Component.CENTER_ALIGNMENT);
            p.setAlignmentX(Component.CENTER_ALIGNMENT);
            panel.add(b1);
            panel.add(b2);
            p.revalidate();
                EventQueue.invokeLater(new Runnable(){
                @Override
                public void run() {
                    changeSize(p, panel);
                    }
                });
            sp.revalidate();
            p.add(panel);
            p.repaint();
            p.validate();
            sp.repaint();
            sp.validate();
            f.repaint();
            f.validate();
            }

        public void mouseReleased(MouseEvent e) {}

        public void mouseEntered(MouseEvent e) {}

        public void mouseExited(MouseEvent e) {}

        public void mouseClicked(MouseEvent e) {}
        }
}
```


----------



## max40 (25. Mrz 2009)

1. würde ich sagen das einmal  
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
schult ist und 
2. das dieses Fehlt:
[HIGHLIGHT="Java"]		
		sp.addComponentListener(new ComponentAdapter() {
			@Override
			public void componentResized(final ComponentEvent e) {
				if (p.getComponentCount() > 0) {
					Main.changeSize(p, (JComponent) p.getComponent(p.getComponentCount() - 1));
				}

			}
		});

		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				p.setPreferredSize(new Dimension(sp.getWidth(), sp.getHeight()));
			}
		});
[/HIGHLIGHT]

Du müsstest mal sagen was du eigentlich willst, soll das alles einspaltig oder mehrspaltig sein usw.


----------

