Zum Inhalt springen

Darstellungsprobleme mit Swing


Empfohlene Beiträge

Geschrieben

Hi Leute,

kennt jemand von euch das Problem, dass manche Grafikelemente (javax.swing) nicht richtig dargestellt werden?

Ich komme auch mit exzessivem Googlen nicht weiter. Ein Beispiel von einem Problemszenario: Ich hab mir ein JPanel erstellt und setze ein Jlabel dadrauf - Programmstart, JLabel nicht zu sehen. Witzig wirds jetzt: Wenn ich die Fenstergröße (auch nur minimal) ändere, erscheint das JPanel. Gleiches Problem bei JTables oder JComboBoxen.

Kennt das jemand? Woran liegt das?

Danke vorweg für die Hilfe !

Geschrieben

Also ich versuche mal, das Problem mit Code-Schnipseln konkret zu machen. Vielleicht erkennt jemand, weshalb die grafische Darstellung nicht richtig funktioniert.

Zugegeben, es ist ein wenig viel, daher vielen Dank, wenn sich jemand die Mühe macht und sich da durchkämpft!


public class ProtocolDB 

{

	public static void main (String []args)

	{

		new Controller();

		Controller.getController().createMainWindow();

	}

}
public class Controller 

implements ActionListener, KeyListener, ItemListener 

/**

 * Die Klasse Controller kommuniziert zwischen GUI und Factory. 

 * Alle Events, die z.B. durch Buttons ausgelöst

 * werden, werden hier verarbeitet. Dafür ist das Interface ActionListener

 * implementiert und ein statisches Objekt dieser Klasse als Listener für

 * die jeweiligen Buttons auf den verschiedenen Panels gesetzt.

 *  

 */

{

	private static Controller con;

	MainWindow mainWindow;

	Factory fac  = new Factory();

	JPanel mainPanel;

	JPanel newGroupPanel;

	JPanel groupViewPanel;

	JPanel newPersonPanel;

	JPanel personViewPanel;

	JPanel newProtocolPanel;


	public static Controller getController()

	{

		return con;

	}


	public Controller()

	{

		con = this;

	}


	/**

	* Methode createMainwindow()

	* Diese Methode wird unmittelbar nach dem Erzeugen eines Controller 

	* Objekts beim Programmstart ausgeführt. Sie erstellt zunächst das 

	* Hauptfenster und fügt das mainPanel hinein.

	*/


	public void createMainWindow()

	{

		mainWindow = new MainWindow();

		AppQuitter quit = new AppQuitter (); //für Window-Events, hier nicht wichtig

		mainWindow.addWindowListener( quit );

		mainWindow.setVisible( true );

		mainWindow.validate();


		mainPanel = fac.createMainPanel();

		activateMainPanel();

		mainWindow.repaint();

	}


/*

 * 	activate-Methoden

 * -=================-

 * 

 */


	/**

	* 

	* Methode activateMainPanel()

	* Das Panel mainPanel wird nach dem ersten Erzeugen in einer 

	* Instanzvariable gespeichert und bei jedem Aufruf von activateMainPanel()

	* aufgerufen. Damit wird vermieden, dass zu Lasten der Performance bei

	* jedem Wechsel in das Hauptmenü ein neues Panel erzeugt werden muss.

	* 

	* Dieses Prinzip greift auch bei allen folgenden activate(...) Methoden.

	* 

	*/


	private void activateMainPanel()

	{

		mainWindow.getContentPane().removeAll();

		mainWindow.repaint();

		mainWindow.getContentPane().add( mainPanel );

	}

        /**

	* 

	* Methode activateNewGroupPanel

	* Hier wird zunächst geprüft, ob die Instanzvariable bereits auf ein 

	* vorhandenes Panel verweist. Ist dies nicht der Fall, ruft ein Objekt

	* vom Typ Factory die entsprechende Methode auf und speichert das neu

	* angelegte Panel in einer Instanzvariable. Die ContentPane vom #

	* Hauptfenster wird vollständig geleert, bevor das Panel hinzugefügt wird

	* 

	*/


	private void activateNewGroupPanel()

	{

		if( newGroupPanel == null )

		{

			newGroupPanel = fac.createNewGroupPanel();

			System.out.println( "moin" );

		}

		mainWindow.getContentPane().removeAll();

		mainWindow.repaint();

		mainWindow.getContentPane().add( newGroupPanel );

	}


//...

        public void actionPerformed(ActionEvent evt) 

	{

/*

 * 		Öffnen/Schließen-Events für Buttons

 * -----===================================-----

 * 

 */

		if( evt.getActionCommand().equals( "newGroupPanel.open"     )) {activateNewGroupPanel();}


		if( evt.getActionCommand().equals( "newGroupPanel.close"    )) {activateMainPanel();}

        }

}

Hier der relevante Ausschnitt der Factory-Klasse

public class Factory 

{

	public Factory ()

	{


	}


	public MainPanel createMainPanel()

	{

		MainPanel mainPanel = new MainPanel();

		return mainPanel;

	}



	public NewGroupPanel createNewGroupPanel()

	{

		NewGroupPanel newGroupPanel = new NewGroupPanel ();

		return newGroupPanel;	

	}

}

Folgende Klasse beschreibt einen leeren JFrame.
public class MainWindow 

extends JFrame 

{

	public MainWindow()

	{

		super ("Hauptmenü");

		setLocation (750,70);

		setSize (1000,1000);

		setLayout(null);

		setJMenuBar (new MainMenuBar());//hier auch unwichtig

	}

}

public class MainPanel 

extends JPanel 

implements ActionListener, KeyListener

{

	Factory fac = new Factory ();

	Color c1    = new Color (250, 250, 240);

	Color c2    = new Color (200, 200, 190);

	Color c3    = new Color (150, 150, 140);


	public MainPanel()

	{

		setSize(1000,1000);

		setLayout (null);

		setBackground(c1);

		addComponents();

		repaint();

	}


	public void addComponents()

	{

		//aus Platzgründen hier nur der relevante Button		

		JButton newGroup = new JButton ("Neue Gruppe");

		newGroup.setBounds(20,15,170,40);

		newGroup.setMargin(new Insets(1,1,1,1));

		newGroup.setToolTipText("Eine neue Gruppe anlegen");

		newGroup.setActionCommand("newGroupPanel.open");

		newGroup.addActionListener (Controller.getController());

		add(newGroup);

        }

}

Jetzt zum Problempunkt:
class NewGroupPanel 

extends JPanel 

implements ActionListener, KeyListener

{

	public NewGroupPanel()

 	{

 		super ();

 		setSize( 1000,1000 );

		setLayout( null );

 		Color c1 = new Color( 250, 250, 240 );

 		setBackground( c1 );

 		setLayout( null );

 		addComponents();

 		repaint();

 	}


 	public void addComponents()

	{

		Color c2             = new Color( 200, 200, 190 );

		Color c3             = new Color( 150, 150, 140 );


		JPanel figure1 = new JPanel();

		figure1.setBounds( 90,70, 320, 40 );

		add( figure1 );

		JPanel figure2 = new JPanel();

		figure2.setBounds( 85,65,320,40 );

		figure2.setBackground( c2 );

		add( figure2 );

		JPanel figure3 = new JPanel();

		figure3.setBounds( 95,75,320,40 );

		figure3.setBackground( c3 );

		add( figure3 );


		JLabel headline = new JLabel();

		headline.setText( "Neue Gruppe erstellen" );

		Font f1 = new Font( "Arial", Font.BOLD, 20 );

		headline.setFont( f1 );

		figure1.add( headline );

        }

}

Das JLabel headline wird beim Aufruf des JPanels newGroupPanel nicht angezeigt. Wenn ich die Fenstergröße ändere, hingegen schon. An repaint()-Anweisung sollte es nicht mangeln.

Geschrieben

Ich sag ja:

Komponenten erstellt und diese ausserhalb des Event Dispatcher Threads an andere Komponenten gebunden.
Lies dir ein paar Einführungen zum Thema Swing und Threading durch und gestalte entsprechend deine Applikation um:

- http://java.sun.com/docs/books/tutorial/uiswing/concurrency/

- http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html

- http://www.google.com/search?q=swing%20event%20dispatcher%20thread

- ...

Geschrieben (bearbeitet)

Ich habe glaube ich schonmal erwähnt wie unschön es ist, einen Jframe zu einer eierlegenden Wollmilchsau zu machen, mittels implements ActionListener, MouseListener, WindowListener... etc.

Es gibt auch die Möglichkeit eine Klasse in einer Klasse zu erstellen. Oder eine komplett eigenständige Klasse zu erstellen welche einen ActionListener implementiert. Das ist viel leserlicher und meiner Meinung nach auch Sinnvoller. Denn eine GUI-Componente ist nunmal kein Listener (auch wenns möglich ist).

Außerdem gibts auch die Möglichkeit irgendwie archive online zur Verfügung zu stellen (zip, rar etc...). Ich finde es schon etwas unschön, wenn ich mir die Mühe mache deine Codeschnipsel hier zu Klassen zusammenzufügen um dann festzustellen das immernoch Verweise drin sind zu Methoden oder Klassen die du nicht gepostet hast.

Was dein problem angeht:

Jedes Component verfügt über die methode public void repaint();

Ich bin mir fast 95% sicher, dass sich dein Problem mit dem Aufruf dieser Methode an der richtigen Stelle lösen lässt.

Im übrigens solltest du setVisible() erst machen, nachdem du das Panel eingefügt hast. Dann kannst dir auch den repaint bei activateMainPanel() sparen. Aber es ist ja nicht so, dass ich das bereits erwähnt hätte.

Bearbeitet von speedi
Geschrieben (bearbeitet)

Vielen Dank erstmal für eure Mühe. Ich will nicht unerwähnt lassen, dass ich noch vergleichsweise neu im Bereich der Programmierung bin und mir Themengebiete wie z.B. das von perdian Vorgeschlagene über Event Dispatch Threads selbstständig erarbeiten muss, was die Sache nicht grade erleichtert. Aber da muss ich durch.

Zu dem Problem nochmal und @ speedi:

Ich hab mit repaints wirklich schon um mich geschmissen, aber es hilft alles nichts. Vielleicht hast du Recht und ich übersehe die richtige Stelle immer, aber das Grundsätzliche, was mich dabei so verwirrt ist, dass dies Phänomen nicht immer auftritt. Ich hab noch mehr JPanels in meiner Applikation und bei denen hab ich dies Problem nicht (obwohl der Aufbau nach dem selben Muster erfolgt).

Zu der Sache mit der Wollmilchsau - Mir ist klar, was du sagen willst, aber mein JFrame ist doch so gesehen ein leerer Pappkarton. Die Listener hängen an den Panels und - was das Eventhandling betrifft - so setze ich überall ein Objekt aus der Controller-Klasse als Listener, um Events von der GUI wegzutragen. Oder ist das auch noch nicht der richtige Weg?

Edit: Zur Darstellung der JLabels: Dummer Fehler, hab ihn behoben. Grund war, dass dem JPanel, welches das JLabel draufgesetzt bekam, ein LayoutManager fehlte. Vielleicht hab ich bei den JTables und JComboBoxen einen ähnlichen Fehler gemacht.

Gruß

Bearbeitet von Ulfmann

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...