Я работаю на Java, и у меня есть JPanel в JFrame. В этом JPanel, среди прочего, у меня есть JLabel, который я хочу заставить появляться и исчезать по желанию. Я пытался установить видимость в значение true/false, добавляя и удаляя его из JFrame и JPanel, и, посмотрев в Интернете, я пробовал проверять() и повторно проверять() до бесконечности. Что здесь можно сделать, чтобы решить эту проблему?
(Java) Появление/исчезновение JLabel в JPanel исчезает только при изменении размера
Ответы (2)
Как правило, вызова метода setVisible
достаточно, чтобы показать или скрыть компонент Swing.
Чтобы убедиться, что это работает, я попробовал следующее:
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();
}
});
}
}
Вышеупомянутая программа может влиять на видимость, нажав на значок JButton
.
Может ли это быть проблема с потоками?
Мое следующее подозрение заключалось в том, что, возможно, Thread
отсутствует в событии поток отправки (EDT) может не влиять на отображение немедленно, поэтому я добавил следующее после инициализации JLabel
и 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();
С новым запущенным Thread
он менял видимость JLabel
каждые 100 мс, и это также работало без проблем.
Вызов компонента Swing из потока диспетчеризации событий (EDT) — это плохо, поскольку Swing не является потокобезопасным. Я был немного удивлен, что это работает, и то, что это работает, может быть просто случайностью.
Перекрасить JPanel
?
Если видимость JLabel
изменяется только при изменении размера, это, вероятно, означает, что JLabel
рисуется только тогда, когда JPanel
перерисовывается.
Одна вещь, которую можно попробовать, это вызвать функцию JPanel
repaint
, чтобы увидеть, изменится ли видимость JLabel
.
Но этот метод кажется просто бинтом в ситуации, если основная причина связана с тем, что поток вне EDT пытается внести изменения в графический интерфейс. (Как примечание, метод repaint
является потокобезопасным, поэтому его можно вызывать из потоков вне EDT, но полагаться на repaint
— это обходной путь, а не решение.)
Попробуйте использовать SwingUtilities.invokeLater
Наконец, вероятно, я бы попробовал SwingUtilities.invokeLater
, который можно вызывать (и следует вызывать только) из потока, работающего отдельно от EDT, если он хочет повлиять на графический интерфейс.
Таким образом, предыдущий пример Thread
следует записать так:
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();
Если изменение графического интерфейса действительно происходит в отдельном потоке, я бы рекомендовал прочитать Урок: Параллелизм в Swing из Руководства по Java чтобы узнать больше информации о том, как писать хорошо работающий многопоточный код с помощью Swing.
setVisible() или его удаление должно работать нормально, однако убедитесь, что вы делаете это из потока отправки событий. В EventQueue есть служебные методы для запуска блоков в этом потоке.
http://helpdesk.objects.com.au/java/how-do-i-update-my-gui-from-any-thread
Вам нужно будет вызвать revalidate() на родительской панели JPanel, если вам нужно перекомпоновать ее компоненты.
Если вы можете опубликовать пример, демонстрирующий проблему, я могу взглянуть на нее для вас.