Качели JPanel не будут перекрашивать - PullRequest
8 голосов
/ 28 января 2010

У меня есть простой объект, который расширяет JPanel, когда для этого объекта вызывается метод update(), он подразумевает добавление некоторых меток на панель и затем перерисовку. Однако после вызова метода обновления метки не отображаются, ниже приведен код для обновления:

public void update(){
        GridBagConstraints constraints = new GridBagConstraints();

        if(cardsHidden){
            for(int i = 0; i < 2; i++){
                constraints.gridx = i;
                constraints.gridy = 0;
                JLabel card = new JLabel(PlayingCards.cardImages[PlayingCards.CARD_BACK_INDEX]);
                add(card, constraints);
            }
        }
        else{
            Card[] holeCards = player.getHoleCards();
            for(int i = 0; i < holeCards.length; i++){
                constraints.gridx = i;
                constraints.gridy = 0;
                JLabel card = new JLabel(holeCards[i].getImageIcon());
                add(card, constraints); 
            }
        }

        validate();
        repaint();
    }

есть идеи?

Спасибо

EDIT

решена:

Оказывается, что HoleCardsPanel не добавлялся в родительский фрейм должным образом. Как только это было исправлено, добавление новых JLabel работает нормально. Я также:

  • добавил вызов метода update() в поток отправки событий, используя SwingUtillities.invokeLater
  • пришлось вызвать validate() из самого верхнего компонента (в данном случае JFrame), как предлагает Devon_C_Miller в своем ответе .

Ответы [ 6 ]

22 голосов
/ 28 января 2010

Это зависит от того, что вы хотите, и от того, какие менеджеры макетов используются, но основные правила:

  1. Убедитесь, что на EDT вызывается update. Если это не так (SwingUtilities.isEventDispatchThread() возвращает false), вам нужно будет использовать SwingUtilities.invokeLater, чтобы запланировать обновление EDT. Например:

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            update();
        }});
    
  2. Звоните invalidate(). Большинство вещей, которые меняют компонент, сделают это за вас. Так что вам нужно вызывать это, только если следующее не работает само по себе.

  3. Позвоните validate() на наивысший уязвимый компонент. Это, наверное, самая грязная часть цикла рендеринга в Java. Вызов invalidate помечает компонент и всех его предков как нуждающиеся в макете. Вызов validate выполняет компоновку компонента и всех его потомков . Один работает «вверх», а другой работает «вниз». Вам нужно позвонить validate на самый высокий компонент в дереве, на который будут влиять ваши изменения.

    Кроме того, вызов validate для компонента верхнего уровня (JWindow, JDialog, JFrame) не обязательно изменит размер этого компонента. Чтобы это произошло, вам нужно позвонить pack() или setSize().

  4. Если ваши изменения изменят размер или положение контейнеров, контейнеры с измененным размером перекрасят, но они не сотрут пространство, занимаемое , используемое для . Вызов repaint() на родительском контейнере заставит его перекрашивать фон, исправляя повреждение.

13 голосов
/ 28 января 2010

Попробуйте вызвать revalidate (); перекрасить это не то, что вы хотите.

Согласно:

API Документы

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

revalidate () - это в основном инвалид (), за которым следует validate ().

См. этот вопрос .....

5 голосов
/ 28 января 2010

Должен работать вызов validate(), хотя revalidate() может быть достаточно; repaint() не требуется. Вы можете сравнить, что вы делаете, с этим примером , который делает динамическим GridBagLayout.

2 голосов
/ 28 января 2010

Вы можете попробовать вызвать updateUI() метод.

0 голосов
/ 29 января 2010

Оказывается, что HoleCardsPanel не может правильно добавить к своему родительскому фрейму, как только это было исправлено, добавление нового JLabels работает нормально. Я добавил вызов к методу update() к event dispatch thread, используя SwingUtillities.invokeLater Мне дополнительно пришлось вызвать validate() из самого верхнего компонента (в данном случае JFrame)

0 голосов
/ 28 января 2010

Вы пробовали SetVisible () на ярлыках?

Вы пытались добавить объекты при инициализации без какого-либо обновления? Если они там не появятся, они никогда не появятся.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...