Я работаю на Java, и у меня есть JPanel в JFrame. В этом JPanel, среди прочего, у меня есть JLabel, который я хочу сделать видимым и исчезнуть по своему усмотрению. Я попытался установить видимость на true/false, добавив и удалив его из JFrame и JPanel, и, посмотрев онлайн, я попробовал validate() ing и revalidate() ing ad infinitum. Что можно сделать здесь, чтобы решить эту проблему?(Java) Появляется/исчезает JLabel в JPanel исчезает при изменении размера
ответ
В общем, вызов метода 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
, что не на event dispatch 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 с event dispatch thread (EDT) - это плохо, поскольку Swing не является потокобезопасным. Я был немного удивлен, что это сработало, и факт, что он работает, может быть просто случайностью.
Переконфигурировать JPanel
?
Если JLabel
«s видимость под воздействием только на изменение размера, это, вероятно, означает, что JLabel
втягивается только тогда, когда JPanel
будет перерисовки.
Чтобы узнать, изменится ли видимость JLabel
, необходимо вызвать метод JPanel
repaint
.
Но этот метод, по-видимому, является всего лишь полосой помощи ситуации, если основная причина связана с тем, что поток от EDT пытается внести изменения в GUI. (Так же, как примечание, метод 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();
Если изменения в GUI действительно происходит в отдельном потоке, то я бы рекомендовал чтение Lesson: Concurrency in Swing из The Java Tutorials для того, чтобы узнать больше информацию о том, как писать хорошо управляемый многопоточный код с помощью Swing.
setVisible() или его удаление должно работать нормально, убедитесь, что вы делаете это из потока отправки событий. В EventQueue есть утилиты для запуска блоков в этом потоке.
http://helpdesk.objects.com.au/java/how-do-i-update-my-gui-from-any-thread
Вы должны были бы назвать перепроверить() на родительских JPanel, если вам необходимо его компоненты должны быть повторно изложены.
Если вы можете опубликовать пример, демонстрирующий проблему, я могу взглянуть на него для вас.
Вы пробовали переадресацию() на JLabel или его родительские компоненты? – rodion