Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > Переместить JLabel d BorderLayout


Автор: Mirkes 5.2.2012, 16:01
Возникла не понятная мне проблема. Создал панель с BorderLayout. На север вставил JToolBar, на восток потомка JPanel по имени leg.
Код

        super(new BorderLayout());
        // Create tool bar
        gtb.setFloatable(false);
        add(gtb, BorderLayout.NORTH);
        // Create legend
        add(leg, BorderLayout.EAST);


Далее вставил эту панель во Frame и запустил.
По нажатию трех кнопок в JToolBar gtb посылаются события с идентификаторами 8, 9 и 10.
Ниже приведен код обработчика событий:

Код

    public void graphHappend(GraphEvent e) {
        switch (e.iD) {
        case 8: //8 - legend to left
            {
                remove(leg);
                repaint();
                add(leg, BorderLayout.WEST);
                repaint();
                break;
            }
        case 9: //9 - remove legend
            {
                remove(leg);
                fireGraphHappend(0);
                repaint();
                break;
            }
        case 10: //10 - legend to right
            {
                remove(leg);
                repaint();
                add(leg, BorderLayout.EAST);
                repaint();
                break;
            }
        }
    }


Проблема состоит в том, что при нажатии кнопок 8 и 10 ничего не происходит, пока не начнешь изменять размер окна.
Если нажать кнопку 9 (убрать легенду) то она исчезает. Если потом нажать кнпку 8 - поместить с левой стороны, то легенда возникает с правой, где и была. Но только до изменения размера окна. При изменении размеров окна - все приходит в норму.
Если идти через отладчик, то тоже все в порядке.
Если я праильно понимаю, то BorderLayout - компоновщик с состоянием. И до тех пор, пока что-то в серьез не изменится (например размер панели) пересчет состояния не производится. 

Внимание вопрос: как заставить BorderLayout пересчитать состояния и отобразить легенду в нужном мне в данный момент месте?

Автор: jk1 5.2.2012, 16:36
Попробуйте принудительно вызвать у контейнера repaint()

Автор: Mirkes 5.2.2012, 17:35
repaint у панели, в которую я помещал легенду вызывается (см код в предыдущем сообщении). У какого контейнера вызвать  repaint?

Автор: Dummy 5.2.2012, 17:39
Простого repaint() недостаточно в случае добавления или удаления элементов. Нужно спарить вызовы revalidate() + repaint() в панели.
Код

    public void graphHappend(GraphEvent e) {
        switch (e.iD) {
        ...
        case 8: //8 - legend to left
            {
                remove(leg);
                add(leg, BorderLayout.WEST);
                revalidate();
                repaint();
                break;
            }
    }


Вызов revalidate() нужен, чтобы сообщить компоновщику вашей панели и компоновщикам родительских контейнеров (вплоть до т. н. Validate Root), что геометрию необходимо пересчитать. Далее revalidate() вызывает validate() на компоненте Validate Root, так что геометрия пересчитывается вплоть до вашей панели.

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

Автор: Mirkes 5.2.2012, 17:45
Спасибо огромное. Выручили. Все заработало.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)