(Java) Visualizzazione / Scomparsa JLabel in un JPanel scompare solo sul ridimensionamento
Domanda
sto lavorando in Java, e ho un JPanel in un JFrame. In quel JPanel, tra le altre cose, ho un JLabel che voglio fare apparire e scomparire a suo piacimento. Ho provato a installare visibilità al vero / falso, aggiunta e la rimozione dalla JFrame e JPanel, e, dopo aver guardato online, ho provato validate) ING (e prorogare () ing all'infinito. Cosa si può fare qui per risolvere questo problema?
Soluzione
In generale, chiamando il metodo setVisible
è sufficiente per rendere un componente Swing per essere mostrato o nascosto.
Giusto per essere sicuri che funziona, ho provato quanto segue:
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();
}
});
}
}
Il programma di cui sopra è in grado di influenzare la visibilità facendo clic su un JButton
.
Potrebbe essere un problema di threading?
Il mio prossimo sospetto era che forse un Thread
che non è sulla filo evento dispatch (EDT) non possono essere colpendo immediatamente il display, così ho aggiunto il seguente dopo l'inizializzazione del JLabel
e JButton
.
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();
Con la nuova Thread
in esecuzione, è cambiato il commutato la visibilità della JLabel
ogni 100 ms, e anche questo ha funzionato senza problemi.
Chiamare un componente Swing al largo della evento filo spedizione (EDT ) è una brutta cosa, come swing non è thread-safe. Sono rimasto un po 'sorpreso ha funzionato, e il fatto che funziona può essere solo un colpo di fortuna .
ridipingere il JPanel
?
Se la visibilità del JLabel
è solo essere colpiti sul ridimensionamento, probabilmente significa che il JLabel
è in corso di elaborazione solo quando il JPanel
verrà ridipinto.
Una cosa da provare è alla chiamata del JPanel
repaint
metodo per vedere se la visibilità del JLabel
cambierà.
Ma questo metodo sembra essere solo un cerotto ad una situazione, se la causa principale è dovuta ad una discussione fuori dal EDT sta tentando di modificare l'interfaccia grafica. (Proprio come una nota, il metodo repaint
è thread-safe, in modo che possa essere chiamato da fili off-EDT, ma basandosi su repaint
è una soluzione di una soluzione.)
Provare a utilizzare SwingUtilities.invokeLater
Infine, probabilmente la cosa che vorrei provare è il metodo SwingUtilities.invokeLater
, che può essere chiamato (e dovrebbe essere chiamato solo) da un filo conduttore separato dal EDT, se vuole influenzare l'interfaccia grafica.
Quindi, l'esempio Thread
in precedenza dovrebbe essere scritto come:
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();
Se la modifica alla GUI è infatti in corso su un thread separato, quindi mi sento di raccomandare la lettura di Lezione: Concurrency in swing da Java Tutorial al fine di trovare ulteriori informazioni su come scrivere ben comportarsi multi-threaded codice utilizzando swing.
Altri suggerimenti
setVisible () o la rimozione dovrebbe funzionare bene, assicurarsi che si sta facendo dal thread spedizione evento però. Ci sono metodi di utilità in EventQueue per l'esecuzione di blocchi in questo thread.
http: / /helpdesk.objects.com.au/java/how-do-i-update-my-gui-from-any-thread
Si avrebbe bisogno di chiamare revalidate () sulle JPanel genitore se è necessario i suoi componenti di essere ri-definito.
Se è possibile postare un esempio che illustra il problema che può avere uno sguardo esso per voi.