Java Panel neu zeichnen/aktualisieren

Nebuk

Lieutenant
Registriert
Sep. 2009
Beiträge
892
Hallo zusammen

Ich hab mal wieder eine JAVA Frage und bin mir sicher, dass ihr mir das mit links beantworten könnt. :)

Ich wollte mir ein kleines Programm schreiben, welches mir je nachdem, welchen Knopf ich drücke, eine entsprechende Anzahl Elemente (in diesem Beispiel Buttons) erstellt.

Im Prinzip funktioniert es eigentlich auch fast so, wie ich es gerne hätte. Das heisst, wenn ich es im Code zuweise, ändern sich die Anzahl der Buttons. Führe ich den Code aus (Eclipse), und drücke den dafür vorgesehenen Knopf (--> Im Code wäre es z.B. "Test1"), bleibt das Fenster leer.

Wie bekomme ich es nun hin, dass es mir wie gewünscht das Panel neu zeichnet. Was ich mir bisher gegooglet habe, hat mir nichts geholfen. Versucht habe ich es jeweils mit:
Code:
fenster.repaint();
fenster.validate();
fenster.setVisible();

mainPanel.repaint();
mainPanel.validate();
mainPanel.setVisible();
und allen erdenklichen Variationen...

Da alles nichts geholfen hatte, versuchte ich das Panel zu entfernen (mainPanel.remove();) Dies funktionierte wie gewünscht, das Panel blieb leer. Als nächstes versuchte ich das Panel erst zu löschen und danach wieder zu adden, leider blieb auch hier der Erfolg aus.

Könnte mir jemand vielleicht helfen und sagen wo ich hier einen Fehler mache? Langsam glaube ich nämlich, dass das neuzeichnen eigentlich funktioniert aber ich sonst irgendwo einen Fehler mache...

Zu guter Letzt, hier noch mein Code:
Code:
package ch.fhnw.test;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;



public class View implements ActionListener {

	private final int Test1 = 8;
	private final int Test2 = 18;
	private final int Test3 = 32;
	
	private int einstellung = 0;
	
	private int zeile;
	
	JPanel northPanel = makeNorthPanel();
	
	
	private JButton jb[] = new JButton[einstellung*2+1];
	private JFrame fenster = new JFrame("Neuzeichnen");
	
	// GETTER und SETTER
	public int getEinstellung() {
		return einstellung;
	}

	public void setEinstellung(int einstellung) {
		this.einstellung = einstellung;
	}
	
	public int getZeile() {
		return zeile;
	}

	public void setZeile(int zeile) {
		this.zeile = zeile;
	}
	// GETTER und SETTER
	
	
	// MAIN
	public static void main(String[] args) {
		View viewer = new View();
		viewer.top();
	}
	// MAIN

	private void top()
	{
		
		JPanel mainPanel = makeMainPanel();
		fenster.add(mainPanel, BorderLayout.CENTER);
		
		fenster.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );		// Beendet den Task, beim schliessen des Fensters
		
		fenster.add(mainPanel);
		
		fenster.setSize(500,570);
		Dimension minimumSize = new Dimension(500,570);					// Mindestbreite
		fenster.setMinimumSize(minimumSize);							// für das Fenster
		
		fenster.setVisible(true);
	}
	
	private JPanel makeMainPanel()
	{
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new BorderLayout());
		bestueckeMainPanel(mainPanel);
		
		return mainPanel;
	}
	
	void bestueckeMainPanel(JPanel mainPanel)
	{
		JPanel northPanel = makeNorthPanel();
		mainPanel.add(northPanel, BorderLayout.NORTH);
		
		JPanel southPanel = makeSouthPanel();
		mainPanel.add(southPanel, BorderLayout.SOUTH);
	}

	private JPanel makeSouthPanel() {
		JPanel southPanel = new JPanel();
		southPanel.setLayout(new FlowLayout());
		bestueckeSouthPanel(southPanel);
		
		return southPanel;
	}

	private JPanel makeNorthPanel() {
		JPanel northPanel = new JPanel();
		northPanel.setLayout(new GridBagLayout());
		bestueckeNorthPanel(northPanel);
		
		return northPanel;
	}

	private void bestueckeSouthPanel(JPanel southPanel) {
		southPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));		// Abstand vom Rand
		
		JButton bt1 = new JButton("Test1");
		bt1.addActionListener(this);
		JButton bt2 = new JButton("Test2");
		bt2.addActionListener(this);
		JButton bt3 = new JButton("Test3");
		bt3.addActionListener(this);
		
		southPanel.add(bt1);
		southPanel.add(bt2);
		southPanel.add(bt3);
	}
	
	private void bestueckeNorthPanel(JPanel northPanel) {
		northPanel.setBorder(BorderFactory.createEmptyBorder(50, 5, 5, 5));		// Abstand vom Rand
		
		
		GridBagConstraints c = new GridBagConstraints();
		
		if( 8 == getEinstellung()){setZeile(getEinstellung()/2); }
		if(18 == getEinstellung()){setZeile(getEinstellung()/3); }
		if(32 == getEinstellung()){setZeile(getEinstellung()/4); }
		
		int i = 0;

		for(int j = 0 ;j < getZeile(); j++)
		{
			for(int q = 0; q < getZeile(); q++)
			{
				jb[i] = new JButton(""+(i+1));
				jb[i].addActionListener(this);
				jb[i].setPreferredSize(new Dimension(50,50));		// Breite und Höhe der Buttons definieren!
				c.gridy = j;
				c.gridx = q;
				
				northPanel.add(jb[i], c);
				
				i++;
			}
		}
		
	}

	
	
	
	
	@Override
	public void actionPerformed(ActionEvent e) {
		
		String button = e.getActionCommand();

		if(button.equals("Test1"))
		{
			setEinstellung(Test1);
			fenster.repaint();
			System.out.println("Test1");
		}
		
		if(button.equals("Test2"))
		{
			setEinstellung(Test2);
			System.out.println("Test2");
		}
		
		if(button.equals("Test3"))
		{
			setEinstellung(Test3);
			System.out.println("Test3");
		}
		
		if(!button.equals("Test1") && !button.equals("Test2") && !button.equals("Test3"))
		{
			System.out.println(button);
		}
		
	}

}

Danke und Gruss
Nebuk

PS. Hoffentlich ist der Code einigermassen durchschaubar. :)
 
Uhm... Du rufst die Bestückungsmethoden nicht auf, wenn du auf die Buttons klickst?!
 
hmm ich hab jetzt nicht im kopf, aber muss es keinen Container geben, der deine Neue Buttons auf deinen Panel addiert. Du kannst ins GUI editor gehen und dort einen Button einfügen und danach den Code vergleichen, was alles im Code sich geändert hat!

Dein Button wurde vielleicht erstellt aber dieser wurde keine Panel zugewiesen.
Code:
  int fPushACount = 0;
  int fPushBCount = 0;

  /** Build the interface with two buttons. **/
  public void init () {
    Container content_pane = getContentPane ();
    content_pane.setLayout (new FlowLayout ());

    // Create an instance of JButton
    JButton button_a = new JButton ("A");

    // Create an instance of JButton
    JButton button_b = new JButton ("B");

    // Add this applet to each button's ActionListener list
    button_a.addActionListener (this);
    button_b.addActionListener (this);

    JPanel panel = new JPanel ();

    [COLOR="Red"]// Add the buttons to the content pane.[/COLOR]
    content_pane.add (button_a);
    content_pane.add (button_b);

Da... wird geaddet.... bei dir net!


EDIT

UPS, ich habe den "SPOILER" nicht gesehen!
 
Seh ich das richtig, dass deine Panels, je nachdem, welche Einstellung gewählt ist, unterschiedlich gezeichnet werden sollen? Wenn ja, dann bist du mit deinem Ansatz ziemlich auf dem Holzweg ^^ Wenn du es nicht versuchst, dann hab ich deinen Code net ganz umrissen...
 
@killkrog... meinst du den code was ich vorgelegt habe? Ne der ist einfach herauskopiert aus ne internetseite... Programmiere eigentlich in C# und in Java schon seit nem Jahr net mehr! Da C# den Code von Java ehe extrem viele ähnlichkeiten hat, ist es eigentlich nur Bibliothekssache!
 
@Killkrog: Wenn ich das unten mache kriege ich folgende Meldung: "Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1"

Jein, die Panels werden immer gleich gezeichnet. Das heisst das SüdPanel wird immer mit 3 Buttons bestückt (Test1, Test2 und Test3) das ist immer gleich.

Das NordPanel wird je nachdem welcher Knopf gedrückt wurde (Knopf im SüdPanel) neu gezeichnet. Also wenn ich Test1 drücke, sollten mir 9 neue Knöpfe erstellt werden in einer Anordnung von 3x3 Buttons.
Beim drücken von Test2 wird die Anordnung von 6x6 Buttons zurückgegeben...

Wieso sollte das mit diesem Ansatz nicht möglich sein?

Gruss
Nebuk der für die Hilfe Dankt :)
 
So wie du es machen willst, TE, .. sieht es für mich so aus, als ob du dann erstmal alles verwerfen darfst, ... und komplett neuzeichen... und das mit dem JButtons kann auch gar nicht so klappen, wie du es denkst.. der erste Grund ist schon ganz oben.

Code:
private JButton jb[] = new JButton[einstellung*2+1];
Einstellung ist bei dir 0. -> 2 mal 0 ist 0 ,..+1 = 1.
Somit hast du eh nur ein JButton-.Array von 1 zurverfügung,solange die Klasse existiert, egal, wie du den Wert einstellung ändert.

Da sind noch so ein oder ander knackpunkte, ... geh erstmal logisch den Code durch ; )
 
Ich hab dir mal folgendes zusammengemanscht. Schaut bisschen viel aus, ist es aber nicht ;) Vielleicht kannst du damit was anfangen?

Code:
public class ComponentAdder {

	// ==================================================================================================
	// {[> Initializers and Constructors
	// =================================
	public ComponentAdder() {
		final JFrame f = new JFrame();
		((JPanel) (f.getContentPane())).setBorder(new EmptyBorder(5, 5, 5, 5));
		f.setLayout(new BorderLayout(5, 5));
		f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

		final JPanel p1 = new JPanel();
		final JPanel p2 = new JPanel();
		final JPanel p3 = new JPanel();
		p1.setBorder(new TitledBorder("Panel 1"));
		p2.setBorder(new TitledBorder("Panel 2"));
		p3.setBorder(new TitledBorder("Panel 3"));
		f.add(p1, BorderLayout.CENTER);
		f.add(p2, BorderLayout.SOUTH);
		f.add(p3, BorderLayout.EAST);

		JButton toggleBtn = new JButton("Toggle View");
		toggleBtn.addActionListener(new ActionListener() {

			private int setting = 0;

			public void actionPerformed(ActionEvent e) {
				setting = (setting + 1) % 3;
				refillPanels(setting, p1, p2, p3);
				f.pack();
			}
		});

		f.add(toggleBtn, BorderLayout.NORTH);

		refillPanels(0, p1, p2, p3);

		f.pack();
		f.setVisible(true);
	}



	// ==================================================================================================
	// {[> Static Methods
	// ==================
	public static void main(String[] args) {
		new ComponentAdder();
	}



	// ==================================================================================================
	// {[> Methods
	// ===========
	private void refillPanels(int setting, JPanel p1, JPanel p2, JPanel p3) {
		System.out.println("Filling panels with setting: " + setting);
		p1.removeAll();
		p2.removeAll();
		p3.removeAll();

		if (setting == 0) {
			p1.add(new JButton("p1, btn1"));
			p1.add(new JButton("p1, btn2"));
			p1.add(new JButton("p1, btn3"));

			p2.add(new JButton("p2, btn1"));
			p2.add(new JButton("p2, btn2"));

			p3.add(new JButton("p3, btn1"));
		} else if (setting == 1) {
			p2.add(new JButton("p2, btn1"));
			p2.add(new JButton("p2, btn2"));
			p2.add(new JButton("p2, btn3"));

			p3.add(new JButton("p3, btn1"));
			p3.add(new JButton("p3, btn2"));

			p1.add(new JButton("p1, btn1"));
		} else if (setting == 2) {
			p3.add(new JButton("p3, btn1"));
			p3.add(new JButton("p3, btn2"));
			p3.add(new JButton("p3, btn3"));

			p2.add(new JButton("p2, btn1"));
			p2.add(new JButton("p2, btn2"));

			p1.add(new JButton("p1, btn1"));
		}
	}
}
 
Zuletzt bearbeitet:
@Nebuk, nächstes mal auf den Debugger anwerfen :D

Was ist eigentlich mit Unit Tests? Damit kannst du sicher gehen, dass das oder dies nicht funktioniert und das andere schon
 
@#7
Mir werden die Buttons ja gezeichnet, wenn ich sie zuoberst definiere. Also ich setze
Code:
private int einstellung = Test1
Beim ausführen sehe ich dann gleich 9 (+ 3) Buttons.
Der Grund weshalb ich dort die 0 der Variable "einstellung" zugewiesen habe ist, dass ich erst keine Buttons ausser die 3 im SüdPanel sehen möchte.

Kann aber sein, dass ich dich falsch verstanden habe... dann entschuldige ich mich dafür und würde dich bitten nochmals etwas ausführlicher/konkreter zu werden :)
Ergänzung ()

@Killkrog: Ich werde es mir mal anschauen

@roker002: Den Debugger habe ich schon öfters durchlaufen lassen, doch habe ich nichts gefunden. Das mit den JUnit-Tests habe ich nicht versucht, da ich nämlich nicht genau weiss wie das mit denen funktioniert, bzw. wie ich da vorgehen muss :freaky:
 
Du initialisiert den JButton-Array doch gleich am Anfang der Klasse. Weshalb das überhaupt eine Klassenvariable + Initialiserung sein muss, wenn sie nur im NorthPanel benutzt wird.. ist eh fragwürdig.

Wenn du es beibehalten willst, dann schreibste nur oben in die Klase
Code:
private JButton[] jb;
rein und initialisiert sie erst in der Methode NorthPanel,.. dann hast du auch mehr oder minder eine dynamische größe von dem JButtonArray weil wenn NorthPanel neuerstellt wird, er den aktuellen Wert von einstellung nimmt zur erstellung.

Sei dir der Problematik bewusst, dass ein einmal initialisiertes Array nicht mehr verändert werden kann. Daher wäre es hier sinnig auf etwas anderes umzusteigen, wenn die du dynamik brauchst, .. oder eben NorthPanel immer neu erstellen. Generelle empfehlung, schreibs komplett in NorthPanel ( nur da, wo man es braucht!)

edit:
Dein Southpanel hat doch gar nichts mit dem JButton-Array zutun.
 
Zuletzt bearbeitet:
Zurück
Oben