410013796724260
• Webmoney
R335386147728
Z369087728698
Урок 15. Столбчатые и круговые диаграммыВ данном уроке будем заниматься разработкой бандла создания и представления столбчатых и круговых диаграмм в приложениях на платформе JaBricks. Создавать интерфейсный бандл будем не с «нуля». В качестве шаблона используем проект templ-jdialog, наследующего свойства базового модуля base-jdialog. Преимущества использования базового модуля для создания интерфейсного бандла представлены на странице его описания. Структура проекта
Подготовка проекта. Скачаем архив проекта templ-jdialog и «развернем» его. Проект создан в среде разработки IDE
Eclipse. Переименуем директорию проекта в «jfreechart-bar-pie». После этого внесем изменения в наименование проекта
(<name>) в файле «jfreechart-bar-pie/.project». Далее переименуем artifactId проекта в «jfreechart-bar-pie/pom.xml».
На этом все приготовления проекта к «употреблению» на начальном этапе заканчиваются. После этого импортируем проект в IDE
и продолжим структурные преобразования проекта. На скриншоте слева представлен наш проект бандла в IDE Eclipse. Структура проекта включает LessonActivator, играющего роль активатора бандла, ChartForm, формирующего интерфейс диалогового окна, проектный файл pom.xml, включающего все зависимости модуля и определяющего порядок сборки бандла. Кроме этого, в проекте появился дополнительный класс ModuleDAO и поддиректория repo. ModuleDAO будет играть роль хранилища данных и обеспечивать взаимодействие с утилитой формирования диаграмм util-jfreechart. В поддиректории repo создадим внутри проекта репозиторий для графической библиотеки osgi-jfreechart, наличие которой в проекте необходимо для определения соответствующих зависимостей в pom.xml. Описание утилиты формирования диаграмм util-jfreechart и её связь с бандлом osgi-jfreechart, являющегося аналогом графической библиотекой org.jfree.jfreechart, представлено на странице модуля. Кроме этого, Вам необходимо также иметь представление о Maven и OSGi, чтобы разобраться со структурой проекта. Описание проектаОписание файлов проекта начнем с pom.xml, на содержимое которого реагирует среда разработки IDE отображением ошибок и блокированием всплывающих подсказок. Проектный файл, pom.xmlПроектный файл pom.xml включает несколько секций : GAV-параметры, репозиторий, свойства, зависимости и сборка. В секции GAV-параметров определены групповой идентификатор groupId, артифакт artifactId, версия и тип сборки packaging. Секция репозитория определяет путь к внутреннему проектному repo. При выполнении сборки проекта бандл osgi-jfreechart из проектного репозитория будет загружен в локальный репозиторий $(user.home)/.m2/repository/. Следует обратить внимание на секцию зависимостей <dependencies>, включающую описания модулей фреймворка, утилиты управления внешними ресурсами util-resources, модуль компонентов gui-widgets, базовый модуль base-jdialog и модули создания диаграмм (util-jfreechart, osgi-jfreechart). В секции сборки <build> используется плагин создания бандла maven-bundle-plugin, определяющий активатор и импортируемые в модуль пакеты (<Import-Package>).
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.jabricks.lesson</groupId> <artifactId>jfreechart-bar-pie</artifactId> <packaging>bundle</packaging> <version>1.0.0</version> <name>JFreechart example (bar, pie)</name> <url>http://maven.apache.org</url> <repositories> <repository> <id>repo/id> <url>file://${basedir}/repo</url> </repository> </repositories> <properties> <project.build.sourceEncoding>UTF-8 </project.build.sourceEncoding> <maven.test.skip>true</maven.test.skip> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.framework</artifactId> <version>5.6.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.eventadmin</artifactId> <version>1.2.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jabricks.resources</groupId> <artifactId>util-resources</artifactId> <version>1.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jabricks.widgets</groupId> <artifactId>gui-widgets</artifactId> <version>1.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jabricks.jdialog</groupId> <artifactId>base-jdialog</artifactId> <version>1.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jfree</groupId> <artifactId>osgi-jfreechart</artifactId> <version>1.0.19</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jabricks.jfreechart</groupId> <artifactId>util-jfreechart</artifactId> <version>1.0.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> </configuration> </plugin> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>2.3.7</version> <extensions>true</extensions> <configuration> <instructions> <Bundle-SymbolicName> ${project.groupId}.${project.artifactId} </Bundle-SymbolicName> <Bundle-Name>${project.name} </Bundle-Name> <Bundle-Version>${project.version} </Bundle-Version> <Bundle-Activator> ${project.groupId}.LessonActivator </Bundle-Activator> <Import-Package> javax.swing.*, org.osgi.framework.*, org.jfree.ui.*, org.jfree.chart.*, org.jfree.data.*, org.jabricks.jfreechart.*, org.jabricks.widgets.*, org.jabricks.jdialog.*, org.jabricks.resources </Import-Package> </instructions> </configuration> </plugin> </plugins> </build> </project> Класс активатора LessonActivatorНиже представлен листинг активатора LessonActivator. Практически код активатора не изменился за исключением переименования самого класса активатора и класса формы. Метод start вызывается при старте бандла. В данном методе создается интерфейсная форма ChartForm. После открытия формы выполняется подписка на сообщения локализации. В активатора метод stop не переопределяется. При закрытии формы автоматически будет вызван переопределенный метод saveComponentParams. К интерфейсной кнопке btnClose подключается слушатель закрытия формы. Также к форме подключается слушатель закрытия окна.
public class LessonActivator extends JBDialogActivator { private ChartForm form = null; //----------------------------------------------------- @Override public void start(final BundleContext context) throws Exception { super.start(context); JFrame.setDefaultLookAndFeelDecorated(true); IResources resources = new ResourcesImpl(); Locale locale = resources.getLocale(); this.form = new ChartForm(context, locale); form.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we) { form.setVisible(false); try { // Останов бандла context.getBundle().stop(); } catch (Exception e) {} } }); form.btnClose.addActionListener(closeListener); form.repaint(); // Открытие окна form.setVisible(true); // Подключение слушателей createLocaleSubscriber(); } //----------------------------------------------------- @Override public void changeLocale (Locale locale) { form.changeLocale(locale); } //----------------------------------------------------- private void closeForm() { form.setVisible(false); form.dispose(); try { context.getBundle().stop(); } catch (Exception e) {} } //----------------------------------------------------- ActionListener closeListener = new ActionListener() { public void actionPerformed(ActionEvent arg0) { closeForm(); } }; //----------------------------------------------------- public void saveComponentParams() { if (form != null) form.saveComponentParams(); } } Класс формы ChartFormНиже представлен листинг класса формирования интерфейса бандла. Конструктор и первые два метода не изменились. Конструктор вызывает метод createGUI, который сначала восстанавливает регулируемые настройки интерфейса (размер окна и положение сплиттера). После этого createGUI создает интерфейс формы, состоящий из двух частей, разделенных сепаратором split. В левой части сепаратора разместим диаграмму, в правой – компоненты выбора диаграммы. Диаграмма будет формироваться в модуле ModuleDAO. Метод createFormPanel создает правую панель с радио-переключателями для выбора диаграммы. При изменении переключателя вызывается метод selectDiagram, обновляющий диаграмму в интерфейсе.
public class ChartForm extends JBDialog { private static final long serialVersionUID = 1L; private int DEFAULT_WIDTH = 420; private int DEFAULT_HEIGHT = 315; private JSplitPane split; private final int DIVIDER_LOCATION = 300; private final String SPLITPANE = "SPLITPANE"; public JButton btnClose = null; private ResourceBundle rsc = null; private String RESOURCES_btn_close = "btn.close"; private String RESOURCES = "properties/properties"; private final String[][] names = {{"10", "Гистограмма, доходы" }, {"11", "Гистограмма, расходы"}, {"20", "Круговая, расходы" }}; //----------------------------------------------------- public ChartForm(final BundleContext context, final Locale locale) { // без изменений . . . } //----------------------------------------------------- private JPanel createButtons() { // без изменений . . . } //----------------------------------------------------- public void changeLocale (Locale locale) { // без изменений . . . } //----------------------------------------------------- private void createGUI() { // Создание рабочей области super.createDesk(); Border border; border = BorderFactory.createEmptyBorder(2,2,2,2); pnlDesk.setBorder (border); split = new JSplitPane(); split.setName(SPLITPANE); split.setOneTouchExpandable(false); split.setOrientation(JSplitPane.HORIZONTAL_SPLIT); if (cparams.size() == 0) split.setDividerLocation(DIVIDER_LOCATION); else { ComponentParams cp; String cls = JSplitPane.class.getSimpleName(); cp = extractComponentParams(cls, SPLITPANE); if (cp != null) split.setDividerLocation(cp.getLocation()); else split.setDividerLocation(DIVIDER_LOCATION); } pnlDesk.setLayout(new BorderLayout()); pnlDesk.add(split, BorderLayout.CENTER); ChartPanel pnlChart; pnlChart = (new ModuleDAO()).createBarChartIncome(); split.setLeftComponent (pnlChart); split.setRightComponent(createFormPanel()); } //----------------------------------------------------- private JPanel createFormPanel() { JPanel panel = new JPanel(); ActionListener listener = new ActionListener() { @Override public void actionPerformed(ActionEvent event) { JRadioButton radio; radio = (JRadioButton) event.getSource(); selectDiagram(radio.getName()); } }; // Группа связанных радио-переключателей JPanel panelRadio; Border border ; String title = "Диаграммы" panelRadio = new JPanel(new GridLayout(0, 1, 0, 5)); border = BorderFactory.createTitledBorder(title); panelRadio.setBorder(border); ButtonGroup bg = new ButtonGroup(); for (int i = 0; i < names.length; i++) { JRadioButton radio = new JRadioButton(names[i][1]); radio.setName(names[i][0]); radio.setSelected(i == 0); radio.addActionListener(listener); panelRadio.add(radio); bg.add(radio); } panel.add(panelRadio); return panel; } //----------------------------------------------------- private void selectDiagram(final String name) { int location = split.getDividerLocation(); ChartPanel cp = null; if (name.equals(names[0][0])) cp = (new ModuleDAO()).createBarChartIncome(); else if (name.equals(names[1][0])) cp = (new ModuleDAO()).createBarChartOutcome(); else if (name.equals(names[2][0])) cp = (new ModuleDAO()).createPieChartOutcome(); if (cp != null) { split.setLeftComponent (cp); split.setDividerLocation(location); } } При открытии формы в методе createGUI создается столбчатая диаграмма, изображение которой представлено на следующем скриншоте. Класс ModuleDAOКласс ModuleDAO представляет главный интерес в данном примере, поскольку именно он решает вопрос подготовки наборов данных и формирования диаграммы. Рассмотрим эти два вопроса по-отдельности. Подготовка данныхКак мы видели выше, в примере создаются три диаграммы : две столбчатые и одна круговая. Для этих трёх диаграмм будем создавать три набора данных. В ModuleDAO для столбчатых диаграмм определены массивы INCOME и OUTCOME, а для круговой – SECTIONS. Размерности первых двух массивов отличаются от третьего. В целях сокращения нагроможденности в представлении листинга массивы приведены в усеченном виде. Для формирования наборов данных CategoryDataset для столбчатых диаграмм будем использовать методы createIncomeDataset и createOutcomeDataset, а для создания набора данных PieDataset соответственно метод createPieDataset. Поскольку масивы и результирующие наборы данных для столбчатых диаграмм идентичны, то создадим для них общий метод подготовки createDataset, который будет принимать в качестве параметра массив данных. В методах сначала выполняются преобразования массивов в наборы данных List, после чего вызываются методы createCategoryDataset и createPieDataset утилиты util-jfreechart для пребразования наборов List в соответствующие наборы Dataset.
private final String[][] INCOME = { {"52733", "Янв", "Доходы 2018"}, {"51345", "Фев", "Доходы 2018"}, . . . {"57800", "Дек", "Доходы 2019"}}; {"52733", "Янв", "Доходы 2018"}, private final String[][] OUTCOME = { {"50733", "Янв", "Расходы 2018"}, {"49345", "Фев", "Расходы 2018"}, . . . {"58400", "Ноя", "Расходы 2019"}, {"55800", "Дек", "Расходы 2019"}}; private final String[][] SECTIONS = { {"99535" , "Квартира" }, {"520000", "Питание" }, . . . {"58600" , "Автомобиль"}, {"15000" , "Дача" }}; //----------------------------------------------------- private CategoryDataset createIncomeDataset() { return createDataset(INCOME); } //----------------------------------------------------- private CategoryDataset createOutcomeDataset() { return createDataset(OUTCOME); } //----------------------------------------------------- private CategoryDataset createDataset(String[][] data) { List<CategoryDataItem> list; list = new ArrayList<CategoryDataItem>(); for (int i = 0; i < INCOME.length; i++) { CategoryDataItem rc = new CategoryDataItem(); rc.setValue (Double.valueOf(INCOME[i][0])); rc.setColumnKey(INCOME[i][1]); rc.setRowKey (INCOME[i][2]); list.add(rc); } JFreeChartImpl fci = new JFreeChartImpl(); return fci.createCategoryDataset(list); } //----------------------------------------------------- private PieDataset createPieDataset() { List<PieDataItem> data_pie; data_pie = new ArrayList<PieDataItem>(); for (int i = 0; i < SECTIONS.length; i++) { PieDataItem rp; double value = Double.valueOf(SECTIONS[i][0]) .doubleValue(); rp = new PieDataItem(SECTIONS[i][1], value); data_pie.add(rp); } JFreeChartImpl fci = new JFreeChartImpl(); return fci.createPieDataset(data_pie); } Создание диаграммНиже представлены методы ModuleDAO, создающие диаграммы. Условно методы можно разделить на две группы. Первая группа методов без параметров с модификаторами public подготавливает описания диаграмм в виде объектов ChartDescBar и ChartDescPie. Для столбчатых диаграмм используется общий метод с параметрами createBarChart, которому необходимо передать заголовок, подпись оси и dataset. После этого из данных методов вызываются соответствующие закрытые (private) методы с параметром описания диаграммы (createBarChart, createPieChart), где с использованием методов createBarChart и createPieChart утилиты util-jfreechart создаются соответствующие диаграммы.
private ChartPanel createBarChart(final String title, final String y_axis, CategoryDataset dataset) { ChartDescBar cdb; cdb = new ChartDescBar(title, null, y_axis, dataset); cdb.setSubtitle("за 2018-2019 гг"); return createBarChart(cdb); } //--------------------------------------------------------- public ChartPanel createBarChartIncome() { CategoryDataset dataset = createIncomeDataset(); String title = "Диаграмма о доходах"; String y_axis = "Доход"; return createBarChart(title, y_axis, dataset); } //--------------------------------------------------------- public ChartPanel createBarChartOutcome() { CategoryDataset dataset = createOutcomeDataset(); String title = "Диаграмма о расходах"; String y_axis = "Расходы"; return createBarChart(title, y_axis, dataset); } //--------------------------------------------------------- public ChartPanel createPieChartOutcome() { PieDataset dataset = createPieDataset(); ChartDescPie cdp = new ChartDescPie(); cdp.setTitle ("Диаграмма расходов"); cdp.setSubtitle("2018 год"); cdp.setDataset (dataset); cdp.setLegend (false); cdp.setTooltips(true); cdp.setTextTitleAlignment(HorizontalAlignment.LEFT); Font font = new Font("Courier New", Font.PLAIN | Font.ITALIC, 11); cdp.setSubtextTitleFont(font); // cdp.setSubtextTitlePosition(RectangleEdge.BOTTOM); // cdp.setSubtextTitleAlignment(HorizontalAlignment.RIGHT); return createPieChart(cdp); } //--------------------------------------------------------- private ChartPanel createBarChart(ChartDescBar cdb) { // Утилита создания диаграммы JFreeChartImpl fci = new JFreeChartImpl(); // Создание диаграммы JFreeChart chart = fci.createBarChart(cdb); // Скрытие шкал fci.hideAxisLineX (chart.getCategoryPlot()); fci.hideAxisLineY (chart.getCategoryPlot()); return new ChartPanel(chart); } //--------------------------------------------------------- private ChartPanel createPieChart(ChartDescPie cdp) { JFreeChartImpl fci = new JFreeChartImpl(); JFreeChart chart = fci.createPieChart(cdp); PiePlot plot = (PiePlot) chart.getPlot(); // Настройка меток названий секций Font font = new Font("Arial", Font.BOLD, 11); fci.setPiePlotLabels(plot, font, Color.DARK_GRAY, Color.DARK_GRAY); return new ChartPanel(chart); } Конфигурация приложенияПосле сборки бандла необходимо определить конфигурацию приложения. Ниже представлен файл «configuration/bundles.ini», включающий список всех бандлов приложения : bundles=org.apache.felix.eventadmin-1.4.8.jar@start, \ org.apache.felix.log-1.0.1.jar@start, \ util-resources-1.0.0.jar@start, \ util-logger-1.0.0.jar@start, \ base-jframe-1.0.0.jar, \ base-jpanel-1.0.0.jar, \ base-jdialog-1.0.0.jar, \ gui-menu-1.0.0.jar, \ gui-toolbar-1.0.0.jar, \ gui-widgets-1.0.0.jar, \ util-jfreechart-1.0.0.jar, \ osgi-jfreechart-1.0.19.jar, \ jfreechart-bar-pie-1.0.0.jar, \ templ-jframe-1.0.0.jar@main Кроме базового набора бандлов в конфигурацию приложения включены модули создания диаграмм osgi-jfreechart, util-jfreechart и наш бандл jfreechart-bar-pie. На следующем скриншоте представлена круговая диаграмма. Связанные страницыСписок уроковПредыдующий, 14-й урок Следующий, 16-й урок Скачать урокАрхив проекта jfreechart-bar-pie (1.82 Мб) включает бандл библиотеки osgi-jfreechart во внутреннем репозитории проекта. Используемый в уроке бандл util-jfreechart можно скачать на странице описания util-jfreechart. Бандлы, используемые в уроке 15, файлы конфигурации и файл описания инсталлируемых бандлов собраны и упакованы в один архивный файл configuration.lesson15.zip (2.33 Мб). Скачайте и «разверните» архив configuration.lesson15.zip, перенесите файлы в структуру, представленную на странице описания платформы JaBricks. |