Ulfmann Geschrieben 17. Dezember 2008 Teilen Geschrieben 17. Dezember 2008 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 ! Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
speedi Geschrieben 17. Dezember 2008 Teilen Geschrieben 17. Dezember 2008 Das liegt daran, wenn man GUI-Componenten zu einem Zeitpunkt added zu dem die Hauptkomponente schon sichtbar ist (z.B. das JFrame) und danach keinen repaint auslöst. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
perdian Geschrieben 17. Dezember 2008 Teilen Geschrieben 17. Dezember 2008 Woran liegt das?Ohne Quellcode gesehen zu haben eine fundierte Vermutung: Komponenten erstellt und diese ausserhalb des Event Dispatcher Threads an andere Komponenten gebunden. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Ulfmann Geschrieben 19. Dezember 2008 Autor Teilen Geschrieben 19. Dezember 2008 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. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
perdian Geschrieben 19. Dezember 2008 Teilen Geschrieben 19. Dezember 2008 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 - ... Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
speedi Geschrieben 19. Dezember 2008 Teilen Geschrieben 19. Dezember 2008 (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 19. Dezember 2008 von speedi Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Ulfmann Geschrieben 19. Dezember 2008 Autor Teilen Geschrieben 19. Dezember 2008 (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 19. Dezember 2008 von Ulfmann Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
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.