Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Пересчет ширин столбцов в JTable после полной, смены модели 
V
    Опции темы
Mirkes
Дата 10.7.2013, 02:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Вечер добрый.
Есть JTable. Время от времени в ее модели происходит полная смена данных. При этом хорошо бы пересчитать и настроить ширины колонок. Делать это я умею, но есть одно большое НО.
Посадил обработчика на события модели и поставил вот такую обработку:
Код

    @Override
    public void tableChanged(TableModelEvent e) {
        if (e.getType() == TableModelEvent.UPDATE && e.getFirstRow() == TableModelEvent.HEADER_ROW &&
            e.getLastRow() == TableModelEvent.HEADER_ROW){
                packColumns(maxWidth); //Пересчет ширин столбцов.
            }
    }


Все было бы нормально, если бы не одно но: модель уже поменялась, а вот таблица поменялась частично:
число строк уже новое, а число столбцов еще старое. До данных через модель добраться конечно можно, а вот не созданные столбцы настроить не получается. Как получить событие когда JTable уже обработала смену модели?


--------------------
Mirkes
PM MAIL   Вверх
Mirkes
Дата 10.7.2013, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Немного поэкспериментировал.
После вызова события смены модели, послал вдогонку событие с собственным кодом события (-5).
Код

        fireTableStructureChanged();
        TableModelEvent e = new TableModelEvent(this,-1,-1,-1,-5);
        fireTableChanged(e);


При обработке события число столбцов и строк в JTable было правильным (соответствовало модели). На радостях перенастроил ширину всех колонок - на экране никакого результата. Начал устанавливать все ширины, какие только мог (data - JTable):
Код

    public void packColumns(int maxWidths) {
        if (data.getRowCount() == 0)
            return;
        int maxWidth = 0;
        int width;
        TableCellRenderer renderer;
        Component component;
        char[] ch;
        FontMetrics fc = data.getFontMetrics(data.getFont());
        TableColumn column;
        int columnCount = data.getColumnCount();
        int rowCount = data.getRowCount();
        for (int i = 0; i < columnCount; i++) {
            renderer = data.getDefaultRenderer(data.getModel().getColumnClass(i));
            maxWidth = 0;
            for (int j = 0; j < rowCount; j++) {
                component = renderer.getTableCellRendererComponent(data, data.getValueAt(j, i), true, true, j, i);
                maxWidth = Math.max(maxWidth, component.getPreferredSize().width);
            }
            ch = data.getColumnName(i).toCharArray();
            width = fc.charsWidth(ch, 0, ch.length) + 10;
            if (width > maxWidth)
                maxWidth = width;
            maxWidth += data.getIntercellSpacing().width;
            if (maxWidth > maxWidths)
                maxWidth = maxWidths;
            column = data.getColumnModel().getColumn(i);
            column.setMaxWidth(maxWidth+5);
            column.setPreferredWidth(maxWidth);
            column.setMinWidth(maxWidth);
            column.setWidth(maxWidth);
            column.addPropertyChangeListener(new PropertyChangeListener(){

                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        System.out.println("new value\t"+evt.getNewValue()+
                                           "\told value\t"+evt.getOldValue()+
                                           "\tpropag id\t"+evt.getPropagationId()+
                                           "\tprop name\t"+evt.getPropertyName()+
                                           "\twho\t"+evt.getSource()
                                           );
                    }
                });
            
            System.out.println("column\t"+i+"\tSetted width\t"+maxWidth+"\tmin\t"+column.getMinWidth()+
                               "\tPreffered\t"+column.getPreferredWidth()+"\tMax\t"+column.getMaxWidth()+
                               "\tReal\t"+column.getWidth());
        }
        data.revalidate();
        data.repaint();
        for (int i = 0; i < columnCount; i++) {
            column = data.getColumnModel().getColumn(i);
        //            column.setMinWidth(maxWidth);
//            column.setPreferredWidth(maxWidth);
            
            System.out.println("column\t"+i+"\tSetted width\t"+""+"\tmin\t"+column.getMinWidth()+
                               "\tPreffered\t"+column.getPreferredWidth()+"\tMax\t"+column.getMaxWidth()+
                               "\tReal\t"+column.getWidth());
        }
        
    }


В консоли вижу изменение ширины колонок, на экране - нет. Добавил на всякий случай revalidate и repaint - никакого эффекта.
Посадил слушателя на изменение параметров колонки.
После чего начал мышкой менять ширину колонок - никакого отклика. Такое впечатление, что после всех моих настроек JTable просто удалила все колонки и создала их по новой. После чего все мои настройки естественно испарились.

Вопрос, как поймать момент, когда JTable наконец сформировала все колонки, что бы настроить их ширину?



--------------------
Mirkes
PM MAIL   Вверх
Mirkes
Дата 10.7.2013, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Таки удалось найти решение.  smile Выяснилось, что в JTable type события смотрят "иногда" и в очень специальных случаях. Поэтому предыдущий код вызывал повторную смену всех столбцов и все мои изменения исчезали  smile 
Следующий код дает нормальный результат:
После всех операций по смене модели из нее (модели) вызываем два события:
Код

        fireTableStructureChanged();
        fireTableChanged(new TableModelEvent(this,0,0,0,-5));

Первое вызывает полную смену всех столбцов и прочей внутренней лабуды JTable.
Второе вызывает в JTable перерисовку 0-го столбца 0-й строки. Код -5 JTable просто игнорирует (я надеялся сначала, что JTable увидев странный код просто не станет его обрабатывать, но команда "Обломись" JTable все, что не есть -1 (Delete) или 1 (Add) считает за 0 (Update).

В основной программе нужно повесить слушателя событий модели.
Так случилось, что в моей программе JTable зовут data.
Код

        data.getModel().addTableModelListener(new TableModelListener(){
             @Override
             public void tableChanged(TableModelEvent e) {
                 if (e.getType() == -5) {
                     packColumns(maxWidth);
                 }
             }

        });

maxWidth - максимально допустимая ширина столбца.
После чего следующий метод прекрасно устанавливает ширину столбца, подогнанную под содержимое таблицы
Код

    public void packColumns(int maxWidths) {
        if (data.getRowCount() == 0)
            return;
        int maxWidth = 0;
        int width;
        TableCellRenderer renderer;
        Component component;
        char[] ch;
        FontMetrics fc = data.getFontMetrics(data.getFont());
        TableColumn column;
        int columnCount = data.getColumnCount();
        int rowCount = data.getRowCount();
        for (int i = 0; i < columnCount; i++) {
            renderer = data.getDefaultRenderer(data.getModel().getColumnClass(i));
            maxWidth = 0;
            for (int j = 0; j < rowCount; j++) {
                component = renderer.getTableCellRendererComponent(data, data.getValueAt(j, i), true, true, j, i);
                maxWidth = Math.max(maxWidth, component.getPreferredSize().width);
            }
            ch = data.getColumnName(i).toCharArray();
            width = fc.charsWidth(ch, 0, ch.length) + 10;
            if (width > maxWidth)
                maxWidth = width;
            maxWidth += data.getIntercellSpacing().width;
            if (maxWidth > maxWidths)
                maxWidth = maxWidths;
            column = data.getColumnModel().getColumn(i);
            column.setPreferredWidth(maxWidth);
        }
    }


Собственно и все. 


--------------------
Mirkes
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   jk1
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, jk1.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: GUI и Java FX приложения | Следующая тема »


 




[ Время генерации скрипта: 0.0427 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.