2009-06-03 12 views
0

Я работаю на Java, и у меня есть JPanel в JFrame. В этом JPanel, среди прочего, у меня есть JLabel, который я хочу сделать видимым и исчезнуть по своему усмотрению. Я попытался установить видимость на true/false, добавив и удалив его из JFrame и JPanel, и, посмотрев онлайн, я попробовал validate() ing и revalidate() ing ad infinitum. Что можно сделать здесь, чтобы решить эту проблему?(Java) Появляется/исчезает JLabel в JPanel исчезает при изменении размера

+0

Вы пробовали переадресацию() на JLabel или его родительские компоненты? – rodion

ответ

6

В общем, вызов метода 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, необходимо вызвать метод JPanelrepaint.

Но этот метод, по-видимому, является всего лишь полосой помощи ситуации, если основная причина связана с тем, что поток от 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.

2

setVisible() или его удаление должно работать нормально, убедитесь, что вы делаете это из потока отправки событий. В EventQueue есть утилиты для запуска блоков в этом потоке.

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

Вы должны были бы назвать перепроверить() на родительских JPanel, если вам необходимо его компоненты должны быть повторно изложены.

Если вы можете опубликовать пример, демонстрирующий проблему, я могу взглянуть на него для вас.