欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-01-31 22:57:22
...

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

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

Swing应用程序样例

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

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

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

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

这个应用程序包含两个类

● 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程序窗口

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

应用程序文件

源代码

● SampleTableModel.java

● SwingInterop.java

NetBeans工程

● SwingInterop.zip


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

相关标签: java Swing javafx