2009-06-03 9 views
0

Ich arbeite in Java, und ich habe ein JPanel in einem JFrame. In diesem JPanel habe ich unter anderem ein JLabel, das ich beliebig erscheinen und verschwinden lassen will. Ich habe versucht, die Sichtbarkeit auf wahr/falsch zu setzen, sie aus dem JFrame und JPanel hinzuzufügen und zu entfernen, und nachdem ich online geschaut habe, habe ich validiert() ing und revalidate() in ad infinitum versucht. Was kann hier getan werden, um dieses Problem zu lösen?(Java) Erscheinen/Verschwinden JLabel in einem JPanel verschwindet nur bei Größenänderung

+0

Haben Sie versucht, repaint() auf dem JLabel oder seinen Elternkomponenten aufzurufen? – rodion

Antwort

6

Im Allgemeinen genügt es, die Methode setVisible aufzurufen, damit eine Swing-Komponente ein- oder ausgeblendet wird.

Nur um sicher zu sein, dass es funktioniert, habe ich versucht, die folgenden:

public class Visibility { 
    private void makeGUI() { 
    JFrame f = new JFrame(); 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    final JLabel l = new JLabel("Hello"); 
    final JButton b = new JButton("Hide Label"); 
    b.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
     l.setVisible(false); 
     } 
    }); 

    f.getContentPane().setLayout(new BorderLayout()); 
    f.getContentPane().add(l, BorderLayout.CENTER); 
    f.getContentPane().add(b, BorderLayout.SOUTH); 
    f.setSize(200, 200); 
    f.setLocation(200, 200); 
    f.validate(); 
    f.setVisible(true); 
    } 

    public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     new Visibility().makeGUI(); 
     } 
    }); 
    } 
} 

Das obige Programm ist in der Lage, die Sichtbarkeit zu beeinflussen, indem sie auf einem JButton klicken.

Könnte es ein Threading-Problem sein?

Mein nächster Verdacht war, dass vielleicht ein Thread, die nicht auf den event dispatch thread (EDT) ist, kann die Anzeige beeinflusst nicht sofort, so dass ich addierte die folgenden nach dem JLabel und JButton initialisiert.

Thread t = new Thread(new Runnable() { 
    public void run() { 
    while (true) { 
     b.setVisible(!b.isVisible()); 

     try { 
     Thread.sleep(100); 
     } catch (InterruptedException e) { /* Handle exception /* } 
    } 
    } 
}); 

t.start(); 

Mit dem neuen Thread Laufen, es änderte sich die die Sichtbarkeit der JLabel alle 100 ms umgeschaltet, und das funktionierte auch ohne ein Problem.

Das Aufrufen einer Swing-Komponente aus der event dispatch thread (EDT) ist eine schlechte Sache, da Swing nicht threadsicher ist. Ich war ein wenig überrascht, es funktionierte, und die Tatsache, dass es funktioniert, kann nur ein Zufall sein.

Die JPanel neu lackieren?

Wenn die JLabel ‚s Sicht auf die Größenänderung nur betroffen wird, bedeutet es wahrscheinlich, dass die JLabel nur wird gezogen wird, wenn die JPanel neu gestrichen wird.

Eine Sache zu versuchen ist, die JPanel 's repaint Methode zu rufen, um zu sehen, ob sich die Sichtbarkeit der JLabel ändert.

Aber diese Methode scheint nur ein Pflaster für eine Situation, wenn die Hauptursache aufgrund eines Threads ist der EDT versucht, Änderungen an der GUI zu machen. (Nur als Hinweis, das repaint Verfahren threadsicher ist, so kann es durch off-EDT Threads aufgerufen werden, aber auf repaint angewiesen ist eine Abhilfe als eine Lösung.)

Versuchen Sie es mit SwingUtilities.invokeLater

Schließlich, wahrscheinlich die Sache, die ich versuchen würde, ist die SwingUtilities.invokeLater Methode, die von einem Thread aufgerufen werden kann (und sollte nur aufgerufen werden) getrennt von der EDT, wenn es die GUI beeinflussen will.

Also, die früher Thread Beispiel sollte wie folgt geschrieben werden: auf die GUI

Thread t = new Thread(new Runnable() { 
    public void run() { 
    while (true) { 
     try { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
      b.setVisible(!b.isVisible()); 
      } 
     }); 
     } catch (Exception e1) { /* Handle exception */ } 

     try { 
     Thread.sleep(100); 
     } catch (InterruptedException e) { /* Handle exception */ } 
    } 
    } 
}); 

t.start(); 

Wenn die Änderung ist in der Tat auf einem separaten Thread auftritt, dann würde ich Lesson: Concurrency in Swing von The Java Tutorials, um das Lesen empfehlen mehr zu erfahren Informationen darüber, wie man mit Swing Multi-Thread-Code mit gutem Verhalten schreibt.

2

setVisible() oder entfernen es sollte funktionieren, stellen Sie sicher, dass Sie es tun, von der Ereignis-Versand-Thread obwohl. Es gibt Dienstprogrammmethoden in EventQueue zum Ausführen von Blöcken in diesem Thread.

http://helpdesk.objects.com.au/java/how-do-i-update-my-gui-from-any-thread

Sie würden rufen müssen() auf der Mutter JPanel revalidate, wenn Sie seine Komponenten müssen neu angelegt werden.

Wenn Sie ein Beispiel veröffentlichen können, das das Problem zeigt, kann ich es für Sie anschauen.