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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Зависание приложения при добавлении JTable 
V
    Опции темы
ReFLeXive
Дата 11.5.2010, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: нет
Всего: 1



Здравствуйте!
Пишу курсовую по базам данным. Столкнулся с такой проблемой: программа зависает и валит exception's в stacktrace при добавлении JTable в JScrollPane.
Делал следующим образом: 
1) сперва создал table model на основе AbstractTableModel. В этой модели реализовал методы getRowCount, getColumnCount, getColumnName, getColumnClass, getValueAt. Конструктор получает в качестве аргумента ArrayList  с объектами

2) В JFrame вставил JScrollPane

3) Далее создал таблицу на основе модели и встроил ее в JScrollPane следующим образом:
Код

Container container = this.getContentPane();
container.setLayout( new GridBagLayout);
//
JScrollPane tableScrollPane = new JScrollPane();
CategoryTableModel model = new CategoryTableModel( categoryList );
JTable categoryTable = new JTable( model );
tableScrollPane.setViewportView( categoryTable );
container.add( tableScrollPane, new GridBagConstraints( 0, 2, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, 
                                            GridBagConstraints.BOTH, new Insets( 0, 5, 0, 5 ), 0, 0 ) );


ПРи запуске приложения программа тут же уходит в режим Debug (breakpoint'ы не стоят) и там выдает 4-5 вот таких exception:
Код

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at javax.swing.JTable.prepareRenderer(JTable.java:5729)
    at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2075)
    at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:1977)
    at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1773)
    at javax.swing.plaf.ComponentUI.update(ComponentUI.java:143)
    at javax.swing.JComponent.paintComponent(JComponent.java:763)
    at javax.swing.JComponent.paint(JComponent.java:1029)
    at javax.swing.JComponent.paintChildren(JComponent.java:864)
    at javax.swing.JComponent.paint(JComponent.java:1038)
    at javax.swing.JViewport.paint(JViewport.java:747)
    at javax.swing.JComponent.paintChildren(JComponent.java:864)
    at javax.swing.JComponent.paint(JComponent.java:1038)
    at javax.swing.JComponent.paintChildren(JComponent.java:864)
    at javax.swing.JComponent.paint(JComponent.java:1038)
    at javax.swing.JComponent.paintChildren(JComponent.java:864)
    at javax.swing.JComponent.paint(JComponent.java:1038)
    at javax.swing.JLayeredPane.paint(JLayeredPane.java:567)
    at javax.swing.JComponent.paintChildren(JComponent.java:864)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5131)
    at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:278)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1220)
    at javax.swing.JComponent.paint(JComponent.java:1015)
    at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
    at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
    at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
    at java.awt.Container.paint(Container.java:1780)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714)
    at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:694)
    at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:128)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)


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

PS. Также есть реализация модели таблицы через интерфейс TableModel - результат аналогичный....
PM MAIL   Вверх
_Y_
Дата 11.5.2010, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1651
Регистрация: 27.11.2006

Репутация: 1
Всего: 34



Мне почему-то кажется, что вставлять содержимое в JScrollPane надо при ее создании. Вроде этого:

Код

Container container = this.getContentPane();
container.setLayout( new GridBagLayout);
//
CategoryTableModel model = new CategoryTableModel( categoryList );
JTable categoryTable = new JTable( model );
JScrollPane tableScrollPane = new JScrollPane(categoryTable );
container.add( tableScrollPane, new GridBagConstraints( 0, 2, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, 
                                            GridBagConstraints.BOTH, new Insets( 0, 5, 0, 5 ), 0, 0 ) );



--------------------
Я вот в этом поучаствовал: http://sbor-nik.appspot.com/kick.jsp?id=sbor5737960678883328 (на правах саморекламы:)
PM MAIL WWW   Вверх
ReFLeXive
Дата 11.5.2010, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: нет
Всего: 1



Цитата(_Y_ @  11.5.2010,  22:25 Найти цитируемый пост)
Мне почему-то кажется, что вставлять содержимое в JScrollPane надо при ее создании

Сделал, как вы посоветовали, однако ничего не изменилось. 
Почему то примеры из Интернета ( брал код вот отсюда ) вполне нормально запускаются! Возможно, дело в том, что там использовался renderer для ячеек, но, я думаю,  что просто вывести данные из листа объектов можно гораздо проще...
PM MAIL   Вверх
pathfinder
Дата 12.5.2010, 07:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: 7
Всего: 10



Код

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at javax.swing.JTable.prepareRenderer(JTable.java:5729)
    ...

Означает что отсутствует Renderer для колонки. Это скорее всего из-за того, что в модели
Код

CategoryTableModel model = new CategoryTableModel( categoryList );

метод 
Код

public Class getColumnClass(int columnIndex) { ... }

возвращяет для некоторых колонок классы примитивных типов
Код

int.class, float.class, ...

если это так, то вместо классов примитивных типов нужно возвращать классы оболочек над примитивными типами
Код

Integer.class, Float.class, ...

PM MAIL   Вверх
ReFLeXive
Дата 12.5.2010, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: нет
Всего: 1



pathfinder, Спасибо за ответ!
В модельках у меня в основном String и int, в 2х местах есть BigDecimal и в 3х местах Date.
Вот пример метода из одной модели
Код

public Class< ? > getColumnClass( int columnIndex )
    {
        switch( columnIndex )
        {
            case 0:
            {
                return String.class;
            }
            case 1:
            {
                return Date.class;
            }
            case 2:
            {
                return BigDecimal.class;
            }
            case 3:
            {
                return BigDecimal.class;
            }
            case 4:
            {
                return Integer.TYPE;
            }
            case 5:
            {
                return String.class;
            }
        }
        return null;
    }


Может быть, в самом конце return null во всем виноват? 
PM MAIL   Вверх
jk1
Дата 12.5.2010, 17:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 21
Всего: 75



Возвращать null из метода getColumnClass() совершенно точно не стоит. Хорошей практикой будет такой switch:
Код

switch( columnIndex )
        {
            case 1:
            {
                return Date.class;
            }
            case 2:
            {
                return BigDecimal.class;
            }
            case 3:
            {
                return BigDecimal.class;
            }
            case 4:
            {
                return Integer.TYPE;
            }
            default:
            {
                return String.class;
            }
        }

То есть строкой будет считаться все, для чего класс не указали в явном виде.

Это сообщение отредактировал(а) jk1 - 12.5.2010, 17:35


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
ReFLeXive
Дата 12.5.2010, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: нет
Всего: 1



Подправил модельку как сказал уважаемый jk1, также добавил в остальных методах вариант default у switch. Выложу ее сюда, может быть есть еще какие то косяки:
Код

public class CategoryTableModel 
    extends AbstractTableModel
{
    private List< Category > categoryList;
    
    public CategoryTableModel( List< Category > categoryList )
    {
        this.categoryList = categoryList;
    }
    
    @Override
    public int getColumnCount( )
    {
        return 2;
    }

    @Override
    public int getRowCount( )
    {
        return categoryList.size( );
    }

    @Override
    public Object getValueAt( int rowIndex, int columnIndex )
    {
        Category category = categoryList.get( rowIndex );
        switch( columnIndex )
        {
            case 0:
            {
                return category.getCategoryId( );
            }
            case 1:
            {
                return category.getCategoryTitle( );
            }
            default:
            {
                return 0;
            }
        }
        //return null;
    }

    @Override
    public Class< ? > getColumnClass( int columnIndex )
    {
        switch( columnIndex )
        {
            case 0:
            {
                return Integer.TYPE;
            }
            case 1:
            {
                return String.class;
            }
            default:
            {
                return String.class; 
            }
        }
        //return null;
    }

    @Override
    public String getColumnName( int column )
    {
        switch( column )
        {
            case 0:
            {
                return "ID";
            }
            case 1:
            {
                return "Название категории медикамента";
            }
            default:
            {
                return "неизвестный столбец";
            }
        }
        //return null;
    }    
}


сategoryList заполнил пока ручками для тестов таким образом:
Код

categoryList = new ArrayList< Category >( );
Category category = new Category( );
category.setCategoryId( 1 );
category.setCategoryTitle( "23456789" );
categoryList.add( category );


Ставил breakpoint и смотрел не пустой ли вдруг лист, но все нормально лист не пустой.
Еще такой вопрос: в методе getValueAt() какой вариант возвращать по умолчанию? я написал 0, но не знаю, правильно ли это...
PM MAIL   Вверх
pathfinder
Дата 12.5.2010, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: 7
Всего: 10



Я бы кинул эксепшн, т.к. значение columnIndex в методе getValueAt() никак не может быть больше чем значение возвращаемое методом getColumnCount(). 

Как раз таки именно из-за этого в твоем первоначальном варианте в методе getColumnClass() вместо того что-бы бросить эксепшн, ты возвращал null. Эксепшн сразу бы указал на то, что количество колонок, возвращаемое методом getColumnCount(), больше чем реально используемое в методах getColumnClass(), getValueAt(), setValueAt().
PM MAIL   Вверх
ReFLeXive
Дата 12.5.2010, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: нет
Всего: 1



Цитата(pathfinder @  12.5.2010,  19:09 Найти цитируемый пост)
Я бы кинул эксепшн,

Подсккажите как это правильно сделать? прежде не сталкивался с подобным...
НАписал следующее:
Код

                  default:
            {
                try
                {
                    throw new Exception();
                    return;
                }
                catch ( Exception e )
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }


Но IDE ругается, что нужно что-нибудь вернуть из метода getValueat(), т.к. у него тип возвращаемого значения стоит Object. Т.е. пустой return не срабатывает, а если убрать return, то IDE опять ругается, что нужно вернуть значение из функции...
PM MAIL   Вверх
jk1
Дата 12.5.2010, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 21
Всего: 75



Код

default:
            {
                throw new RuntimeException("wrong column number");
            }



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
ReFLeXive
Дата 13.5.2010, 14:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: нет
Всего: 1



Поменял  Integer.TYPE на Integer.class и (О, чудо!!!!) заработало!!! Таблица нормально показалась и вывела свое содержимое!! Ура, товарищи!
Объясните только, пожалуйста, в чем принципиальное отличие между TYPE и class? И тот и другой вроде возвращают Class<java.lang.Integer>
PM MAIL   Вверх
jk1
Дата 13.5.2010, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 21
Всего: 75



Integer.TYPE - это примитив, int проще говоря. О том, что не стоит возвращать классы примитивов уже говорилось выше.
Integer.class - это класс объектной обертки int'a



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
ReFLeXive
Дата 13.5.2010, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: нет
Всего: 1



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

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

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


 




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


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

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