Одна ушла, вторая нет.
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. |
