利用JavaFX功能丰富Swing应用程序

6 篇文章 0 订阅

在本章中你将学到如何在单个应用程序中混合Swing表格和JavaFX柱状图。

本章以一个Swing应用程序开始,提供了一个通过添加JavaFX功能来丰富Swing应用程序的样例。

Swing应用程序样例

许多现实世界的项目使用Swing应用程序来处理表格。你可以继续使用已有的代码并好好利用JavaFX APIs。对于本例来说,你可以增加一个JavaFX柱状图,以此为表格数据提供一个彩色插图。本章提供了SwingInterop例子,其中处理了一个Swing表格和一个JavaFX柱状图。当你改变表格里面的数据时,柱状图会立刻更新。

从只包含Swing表格的样例应用程序开始,如图4-1。

图4-1 Swing JTable应用程序窗口

13_4_1 jtable

这个应用程序包含两个类

● SampleTableModel.java

● SwingInterop.java

SampleTableModel.java类继承了AbstractTableModel类并定义了表格。

SwingInterop类继承了JApplet类,是这个应用程序的基础类。其main方法在事件分发线程(EDT)上调用了run方法,其中创建了一个JFrame对象和一个JApplet对象,并用SwingInterop类的实例初始化了JApplet对象。然后调用init方法,创建了表格并将其加入到applet的内容面板中。

整合JavaFX柱状图

为了给柱状图提供数据,修改SampleTableModel类,增加一个新的类变量(bcData)和一个新的方法来返回适合柱状图的数据格式。getBarChartData方法的实现如例4-1所示。

例4-1

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.chart.BarChart;

public class SampleTableModel extends AbstractTableModel {
    private static ObservableList<BarChart.Series> bcData;

    public ObservableList<BarChart.Series> getBarChartData() {
        if (bcData == null) {
            bcData = FXCollections.<BarChart.Series>observableArrayList();
            for (int row = 0; row < getRowCount(); row++) {
                ObservableList<BarChart.Data> series =
FXCollections.<BarChart.Data>observableArrayList();
                for (int column = 0; column < getColumnCount(); column++) {
                    series.add(new BarChart.Data(getColumnName(column),
getValueAt(row, column)));
                }
                bcData.add(new BarChart.Series(series));
            }
        }
        return bcData;
    }
//rest of the SampleTableModel class code
}

SwingInterop类重写了JApplet.init方法,以创建应用程序的内容面板。修改init方法来创建一个保存JavaFX柱状图的JFXPanel对象和一个组织JavaFX图表和表格的JSplitPane对象。Init方法中所需要的修改如例4-2中的加粗代码所示。

4-2

@Override
public void init() {
    tableModel = new SampleTableModel();
    // create javafx panel for charts
    chartFxPanel = new JFXPanel();
    chartFxPanel.setPreferredSize(new Dimension(PANEL_WIDTH_INT, PANEL_HEIGHT_INT));

    //create JTable
    JTable table = new JTable(tableModel);
    table.setAutoCreateRowSorter(true);
    table.setGridColor(Color.DARK_GRAY);
    SwingInterop.DecimalFormatRenderer renderer = 
new SwingInterop.DecimalFormatRenderer();
    renderer.setHorizontalAlignment(JLabel.RIGHT);
    for (int i = 0; i < table.getColumnCount(); i++) {
        table.getColumnModel().getColumn(i).setCellRenderer(renderer);
    }
    JScrollPane tablePanel = new JScrollPane(table);
    tablePanel.setPreferredSize(new Dimension(PANEL_WIDTH_INT, 
TABLE_PANEL_HEIGHT_INT));
    JPanel chartTablePanel = new JPanel();
    chartTablePanel.setLayout(new BorderLayout());

    //Create split pane that holds both the bar chart and table
    JSplitPane jsplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
    jsplitPane.setTopComponent(chartTablePanel);
    jsplitPane.setBottomComponent(tablePanel);
    jsplitPane.setDividerLocation(410);
    chartTablePanel.add(chartFxPanel, BorderLayout.CENTER);

    //Add the split pane to the content pane of the application
    add(jsplitPane, BorderLayout.CENTER);
}

为了避免语法错误,在SwingInterop类中增加一个引入声明和charFxPanel成员变量,如例4-3所示。

例4-3

import javafx.embed.swing.JFXPanel;
import javax.swing.*;

public class SwingInterop extends JApplet {
    private static JFXPanel chartFxPanel;
// rest of the SwingInterop class code here
}

你已经准备好了用来呈现JavaFX数据的Swing应用程序的UI。下一步是创建JavaFX场景。因为JavaFX场景必须由JavaFX应用程序线程创建,将代码封装为一个Runnable对象,如例4-4所示。在init方法的末尾加入这些代码。

4-4

Platform.runLater(new Runnable() {
    @Override
    public void run() {
        createScene();
    }
});


在SwingInterop类中加入如下引入声明,如例4-5所示。

4-5

import javafx.application.Platform;

实现SwingInterop类的createScene方法,如例4-6。增加引入声明并定义chart 成员变量。

例4-6

import javafx.scene.Scene;
import javafx.scene.chart.Chart;

private void createScene() {
    chart = createBarChart();
    chartFxPanel.setScene(new Scene(chart));
}

createBarChart方法创建了图表,并为表格添加了一个的改变监听器。注意所有JavaFX数据的改变都必须发生在JavaFX线程上。因此,将事件处理器中负责更新JavaFX图表的代码封装进一个Runnable对象中,并传入Platform.runLater方法。createBarChart方法的实现如例4-7所示。

4-7

private BarChart createBarChart() {
    CategoryAxis xAxis = new CategoryAxis();
xAxis.setCategories(FXCollections.<String>observableArrayList(tableModel.
getColumnNames()));
    xAxis.setLabel("Year");
    double tickUnit = tableModel.getTickUnit();
    
    NumberAxis yAxis = new NumberAxis();
    yAxis.setTickUnit(tickUnit);
    yAxis.setLabel("Units Sold");

    final BarChart chart = new BarChart(xAxis, yAxis, tableModel.getBarChartData());
    tableModel.addTableModelListener(new TableModelListener() {
    
        public void tableChanged(TableModelEvent e) {
            if (e.getType() == TableModelEvent.UPDATE) {
                final int row = e.getFirstRow();
                final int column = e.getColumn();
                final Object value = 
((SampleTableModel) e.getSource()).getValueAt(row, column);
                
                Platform.runLater(new Runnable() {
                    public void run() {
                        XYChart.Series<String, Number> s = 
(XYChart.Series<String, Number>) chart.getData().get(row);
                        BarChart.Data data = s.getData().get(column);
                        data.setYValue(value);
                    }
                });
             }
         }
    });
    return chart;
}

增加如例4-8所示的引入声明。

例4-8

import javafx.collections.FXCollections;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

重命名框架的标题为“Swing JTable and Bar Chart”并运行SwingInterop程序。

应用程序窗口如图4-2所示。

图4-2 SwingInterop程序窗口

13_4_2 barchart

应用程序文件

源代码

● SampleTableModel.java

● SwingInterop.java

NetBeans工程

● SwingInterop.zip


原文链接:http://www.javafxchina.net/blog/2015/09/doc1304-fx-feature/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值