Обработка таблицы на java

JTable – отображаем данные в виде таблицы

Очень часто возникает необходимость в приложениях показать данные в виде таблицы с определенным количеством строк и столбцов. В Java Swing для отображения табличных данных используется комопнент JTable. JTable внутри себя не содержит данные, а служит только для их отображения.

Рассмотрим простой пример создания и использования таблицы. Для этого мы создадим таблицу, заполним её тестовыми данными и разместим на панели прокрутки. Размещение таблицы на панели прокрутки – это обычная практика, потому что это удобно и красиво.

Существует несколько способов того, как сказать JTable, какие данные и столбцы следует отображать. Здесь мы рассмотрим самый простой способ. Для начала определим, какие стобцы мы хотим показывать в таблице. Для примера я взял столбцы проводника Windows – Name (Имя файла или папки), Last modified (Дата последней модификации), Type (Тип) и Size (Размер). Собираем столбцы в массив строк вот так:

Далее необходимо определить данные, которые мы хотим отображать в таблице. Длеается это тоже при помощи массива строк вот так:

Далее необходимо создать собственно сам JTable и передать ему массив столбцов и массив с данным для показа.

JTable table = new JTable(data, columnNames);

Потом создаем JScrollPane, на котором размещаем таблицу и добавляем панель на JFrame. Внешний вид получившегося приложения можно увидеть на рисунке ниже.

Читайте также:  Полная форма ветвления питон

jtable_sample

Исходный код приложения представлен ниже.

import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; public class TestFrame extends JFrame < public static void createGUI() < JFrame frame = new JFrame("Test frame"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); String[] columnNames = < "Name", "Last modified", "Type", "Size" >; String[][] data = < , , , , , , , , , , , , , , >; JTable table = new JTable(data, columnNames); JScrollPane scrollPane = new JScrollPane(table); frame.getContentPane().add(scrollPane); frame.setPreferredSize(new Dimension(450, 200)); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); > public static void main(String[] args) < javax.swing.SwingUtilities.invokeLater(new Runnable() < public void run() < JFrame.setDefaultLookAndFeelDecorated(true); createGUI(); >>); > >

Источник

Работа с таблицей Excel из Java

Собственно возникла проблема — обработать данные из таблицы и на их основе получить другую таблицу.

  1. Макрос — единственной проблемой является VBA, на изучение которого времени нет совершенно, да и не нравится его синтаксис
  2. Приложение на C# тут вроде все хорошо, но к машине на которой будет выполняться данное приложение сразу предъявляется много дополнительных требований:
    • .NET Framework
    • Установленный офис
    • установленная основная сборка взаимодействия (PIA) для приложения Office

  3. связка Java и библиотека Apache POI—на этом способе я и хочу остановиться подробнее
  1. POI 3.5 beta 5, and Office Open XML Support (2009-02-19)—идет работа над поддержкой формата Office 2007
  2. POI 3.2-FINAL Released (2008-10-19) — последний стабильный релиз

Я расскажу о работе с версией 3.2
Основным классом для работы с таблицей Excel является класс HSSFWorkbook пакета org.apache.poi.hssf.usermodel, представляющий книгу Excel.

Для чтения книги из файла можно применить следующий код:

public static HSSFWorkbook readWorkbook(String filename) < try < POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(filename)); HSSFWorkbook wb = new HSSFWorkbook(fs); return wb; >catch (Exception e) < return null; >>

Метод возвращает объект класса HSSFWorkbook если все удачно и null в другом случае.

Для сохранения изменений можно применить следующий метод:

public static void writeWorkbook(HSSFWorkbook wb, String fileName) < try < FileOutputStream fileOut = new FileOutputStream(fileName); wb.write(fileOut); fileOut.close(); >catch (Exception e) < //Обработка ошибки >>

Метод записывает книгу wb в файл fileName

  • По имени
    HSSFSheet sheet= wb.getSheet(«Лист 3»)
  • По номеру (нумерация начинается с 0)
    HSSFSheet sheet= wb.getSheet(0)
  • Создание нового листа
    HSSFSheet sheet= wb.createSheet([«имя листа»])
  • По индексу (индексация начинается с 0)
    HSSFRow row = sheet.getRow(index)
  • Через итератор

Iterator rowIter = sheet.rowIterator(); while (rowIter.hasNext())

  • По индексу ячейки (индексация начинается с 0)
    HSSFCell cell = row.getCell(0);
  • Через итератор

Iterator cellIter = row.cellIterator(); while (cellIter.hasNext())

  • Логическое значение
    boolean b = cell.getBooleanCellValue();
    cell.setCellValue(b);
  • Дата
    Date date = cell.getDateCellValue();
    cell.setCellValue(date);
  • Числовое значение
    double d = cell.getNumericCellValue();
    cell.setCellValue(d);
  • Строковое значение
    String str = cell.getRichStringCellValue().getString();
    cell.setCellValue(new HSSFRichTextString(str));
  • Формула
    String formula = cell.getCellFormula();
    cell.setCellFormula(formula);

Этих знаний достаточно чтобы обрабатывать простые таблицы.
Библиотека также предоставляет богатые возможности по форматированию ячеек, по их слиянию, заморозке и т.д.
Подробное описание функций можно найти на их сайте.
Данный способ прежде всего ценен тем, что не требует установки самого офиса и пакета PIA.

Источник

JTable и Serializable или таблицы в Java и танцы с бубном при сохранении объектов в файлы

Так получилось, что как дизайнеру, мне необходим простор для творчества при реализации любых зачач в написании программ. Давно я положил глаз на такую платформу как Java, так-как всегда мечтал о кроссплатформенном программном обеспечении. И вот недавно, я решил освоить такой прекрассный компонент в Java, как JTable, ну и по той причине, что всегда любил использовать таблицы в своих программах.

В общем, я поставил перед собой не сложную задачу — создать таблицу, которую мог бы сохранять в файл как объект и паралельно отслеживать введенные пользователем данные подсвечивая ошибки и упрощая общение с таблицей моей программы путем подсвечивания наиболее важных элементов таблицы. Так-как я сторонник программирования по принципу пошаговой отладки при написании кода, наличие готовых кусков стабильного кода в сети Интернет, было для меня очень важным… Но… После тщательных поисков, экспериментально было установлено , что, в сети Интернет есть всего пару нормальных источников для получения более или мение хорошего кода.

Нет-нет, я вас не буду отправлять сюда (Популярная цитата пользователей javatalks.ru и др. — «перед тем как задать тупой вопрос, посмотрите здесь. »).

и сюда. (How to Use Tables — tutorial)

или сюда (Using Swing Components: Examples).

Хотя, я так говорю не с проста, так-как посмотрев там и поняв, что доки Java немного устарели, как по восприятию, так и по наличию вразумительного рабочего кода (я использовал Java версии 7.01). Но все же, не почитав этих справочных материалов, вы никогда не поймете самой сути, логики и психологии таблиц Java.

По этой причине, ниже описанный стабильный пример сериализации таблицы JTable, будет у вас работать так, как вы этого хотите, лишь при условии понимания того, что вы делаете и что хотите получить. На последок добавлю — некоторые куски кода были собраны в Интернет на разных ресурсах (за что им всем огромное спасибо), но их всех объединяет одно — я сам их отлаживал и притирал к своей программе, то есть идеально работающего кода я так и не нашел. Хотя… нет. Я построил свой код, только потому, что взял с одного из англоязычных ресурсов рабочий код программы сериализации, который у меня вылетал при попытке изменения данных в таблице (ссылка на ресурс к сожалению потерялась)…
Но «о драконах» кода по порядку.

О как же ты красноречив, дракон великий Error Log

Ну, теперь самое время сказать мне: «Ты че устраиваешь танцы с бубном? Или не читал этого? Гугли получше и не забивай нам всем мозги бирюльками для дизайна… Мы и без него можем обойтись.» И правда, почитав этот перевод книги «Java 2. Том 2. Тонкости программирования. Автора — Кей Хорстман и Гарри Корнелл» (у меня 8-е печатное издание), я обнаружил отличный код:

//запись в файл FileOutputStream fos = new FileOutputStream("temp.out"); ObjectOutputStream oos = new ObjectOutputStream(fos); SerialTest st = new SerialTest(); oos.writeObject(st); oos.flush(); oos.close(); //чтение из файла FileInputStream fis = new FileInputStream("temp.out"); ObjectInputStream oin = new ObjectInputStream(fis); TestSerial ts = (TestSerial) oin.readObject(); System.out.println("version http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4503845">она. 

И длится бой уж много лет, с версии Java «1.4.0-beta2»

Тут я увидел, что особо просветленные шаманы, вроде Kleopatra, там давненько уже отрубают крылья дракона Error Log простым вызовом:

//это я сам вставил, пусть данные сохраняться перед фиксацией таблицы //иначе значение сбросится до примитивного "", что приводит к потере данных во всей строке table.editingStopped(null); //а вот, что предложили разработчики Java, по ссылке выше /*Цитирую: * * The first issue in the description deals with the improper behavior * of losing edits on focus exit the first time but for not subsequent * attempts. The problem was correctly diagnosed by Kleopatra in bug * report 4518907. java.swing.JTable indeed does need to set 'editorRemover' * to null after calls to * removePropertyChangeListener("focusOwner", editorRemover); * in both removeNotify() and in removeEditor(). * */ //и хоть в английском я не силен, я сделал как они рекомендуют table.removeEditor(); //это можно не писать и без него работает отлично table.removeNotify();

Ну вот и всё, дракон уж вроде побежден…
Ан нет, он в классы с TableCellRenderer был перемещен…

Уроки рисования, или «Нет-нет, мне нужно подсветить строку с ошибкой красненьким»

После не сложных плясок у нового костра разожженного очередными ошибками визуализации таблицы, я обнаружил, что будет уместным реализовать два класса отрисовки таблицы, один для ячеек и второй для названий (ярлыков) колонок:

//Класс отрисовки таблицы class JCTableCellRenderer extends JLabel implements TableCellRenderer, Serializable <> //класс отрисовки ярлыков колонок class JColumnRenderer extends JLabel implements TableCellRenderer, Serializable <>

Теперь это все нужно объявить:

//Грузим наш внешний класс рендера таблицы JCTableCellRenderer table.setDefaultRenderer(Object.class, new JCTableCellRenderer());

В начале метода loadColumn() пишем:

//Используем внешний класс JColumnRenderer для прорисовки TableColumn //используется отдельно от JCTableCellRenderer, так-как это ускоряет вывод и существенно упрощает код TableCellRenderer renderer = new JColumnRenderer();

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

информация очень ценная, но по дизайну скудная и про TableCellRenderer, говорилось мало. Я начал сам эксперементировать с разными способами окраски таблицы и что я узнал в итоге?

//метод внутри класса public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) //для меня как дизайнера означал следующее: //@param: table - глобально применяет окрашивание в указанным строкам, ячейкам, столбцам //@param: value - применяет окрашивание к указанному значению в ячейке //@param: isSelected - это понятно и без объяснений (применяет окрашивание к выделению) //@param: hasFocus - применяет окрашивание к выделенной ячейке //@param: row - применяет окрашивание в указанной по индексу строке //@param: column - применяет окрашивание в указанной по индексу колонке

Примеры окрашивания в таблице JTable:

//раз уж мы наследовались от JLabel, то в начале метода ставим, что-то типа JLabel c = new JLabel(value.toString()); //мы будем тыкать лейблы везде, чтобы отобразить все данные таблицы сразу - value.toString() //если в любой ячейке есть текст "jpg", красим её красивым цветом if(value.equals("jpg")) //первая колонка у нас имеет свой индивидуальный окрас if(column==0) //эта строка у нас будет покрашена в розовый, если в седьмой колонке есть строка со значением "iff" if(table.getValueAt(row, 7).equals("iff")) < c.setOpaque(true); c.setBackground(new Color(255, 105, 180)); c.setForeground(Color.white);>//проверим два целых числа колонок: четыре и пять, и если условие ложно красим строку красным цветом //и. предупреждаем пользователя об ошибке в выбранной колонке нашей таблицы и пишем в модель таблицы //кстати, не конвертируйте значений так: (String)table.getModel().getValueAt(row, 4) //это вызовет ошибку компиляции int a = Integer.parseInt(""+table.getModel().getValueAt(row, 4)); int b = Integer.parseInt(""+table.getModel().getValueAt(row, 5)); if(a > b) < c.setOpaque(true);c.setBackground(Color.red);c.setForeground(Color.yellow); if(column==8) < c.setText("Error this value: colomn - \"Start\", row - " + (row+1)); table.getModel().setValueAt(c.getText(), row, column); >> else < //а это я проверил, вдруг файл на диске не найден, это тоже нужно показать пользователю //и восстановить значение в восьмой колонке, если пользователь исправил ошибку //хотя, указанным способом, можно просто самим исправить значение на нужное сразу после проверки //значений колонок четыре и пять на истинность if(column==8) < java.io.File f = new java.io.File((String) table.getModel().getValueAt(row, 9)); if(f.exists()) < table.getModel().setValueAt("", row, column); > else < table.getModel().setValueAt("", row, column); c.setOpaque(true);c.setBackground(Color.red);c.setForeground(Color.yellow); > > > //этот шикарный код взят с http://skipy-ru.livejournal.com/1577.html //его назначение - в зависимости от темы приложения менять стиль таблицы // using L&F colors if(isSelected) < c.setOpaque(true); c.setForeground(isSelected ? UIManager.getColor("Table.selectionForeground") : UIManager.getColor("Table.foreground")); c.setBackground(isSelected ? UIManager.getColor("Table.selectionBackground") : UIManager.getColor("Table.background")); c.setBorder(hasFocus ? BorderFactory.createLineBorder(UIManager.getColor("Table.selectionForeground"), 1) : BorderFactory.createEmptyBorder(2, 2, 2, 2)); //а здесь, я проверил на указанные значения ячейки и если они истинны //мы изменяем цвет выделенных ячейки на нужный if(value.equals("jpg"))if(value.equals("png")) if(value.equals("iff")) if(column==0) > 

Теперь все работает — сохраняется в файл и раскрашивается в нужный цвет.
Для реализации своего замысла я использовал среду разработки Eclipse v. 3.7

image

Ну и… Если вы дочитали до этого места, то спасибо вам за потраченное время.
Если вы хотите задать вопрос типа: «А как мне это сделать с базой данных?» или «Почему, реализуя циклы типа for при проверке значений в классе JCTableCellRenderer у меня ужасно висит таблица», то пожалуй добавлю, что на базах данных выше указанного кода я не применял (но почему-то уверен, что он работает стабильно), и еще — циклы реализованные в классах рисования, это такое же извращение как и таймеры на таймлайне клипов во Flash. Рекомендую всегда оптимизировать свой код по принципу — «чем проще, тем быстрее».

Нужные внешние классы и код самой программы прилагаются (открывать в Eclipse).

Источник

Оцените статью