java - 如何重新绘制集成到 Swing 中的 StackPane (JavaFX)?

标签 java swing javafx repaint

我在 Swing 中使用 JavaFX,因此我有 JFrameJFXPanelJPanel 上有 StackPane 的场景。 框架上也有菜单,它与面板相连。 如何按菜单项重新绘制面板或堆栈面板? (我想更改字体或单击其他内容,例如查看 - E-格式,但什么也没有发生) 我知道JavaFX中没有类似的repaint(),那么我该怎么做呢?

参见 mainClass 中的 set_formatType 和 StackChart 中的 yAxis 格式

MCVE:

mainClass.java

    public abstract class mainClass extends Application {
        public static final int X_NUMBER = 20;
        static StackChart chart;

        // --- MENU
        static JMenuBar mainMenuBar;
        static JMenuBar menuBar;
        static JMenu menuFile;
        static JMenu menuView;
        JMenu menuAbout;
        JMenu menuFontSize;
        JMenu menuFont;
        JMenuItem menuItem;
        JRadioButtonMenuItem rbMenuItem;
        JCheckBoxMenuItem cbMenuItem;

        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    initAndShowGUI();
                }
            });
        }

        private static void initAndShowGUI() {
            // This method is invoked on Swing thread
            JFrame frame = new JFrame("FX");
            final JFXPanel fxPanel = new JFXPanel();
            frame.add(fxPanel);
            frame.setVisible(true);
            frame.setSize((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth(), (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight());

            mainMenuBar = createMenu();
            frame.setJMenuBar(mainMenuBar);

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

        private static void initFX(JFXPanel fxPanel) {
                // This method is invoked on JavaFX thread
                Scene scene = createScene();
                fxPanel.setScene(scene);
            }
        private static Scene createScene()    {
            Group root = new Group();
            Scene scene = new Scene(root, 1024, 600);

            BorderPane borderPane = new BorderPane();

            NumberAxis xAxis = new NumberAxis();
            NumberAxis yAxis = new NumberAxis();

            yAxis.setLabel("Scale 1");
            LineChart baseChart = new LineChart(xAxis, yAxis);
            baseChart.getData().add(prepareSeries("Serie 1", (x) -> (double) x));

            chart = new StackChart(baseChart, Color.RED);
            chart.addSeries(prepareSeries("Serie 2", (x) -> (double) -2*x * x), Color.BLUE);


            borderPane.setCenter(chart);

            borderPane.setPrefSize(800, 600);
            borderPane.setBottom(chart.getLegend());

            root.getChildren().add(borderPane);

            return scene;
        }

        private static XYChart.Series<Number, Number> prepareSeries(String name, Function<Integer, Double> function) {
            XYChart.Series<Number, Number> series = new XYChart.Series<>();
            series.setName(name);
            for (int i = 0; i < X_NUMBER; i++) {
                series.getData().add(new XYChart.Data<>(i, function.apply(i)));
            }
            return series;
        }

        public static JMenuBar createMenu()    {
            menuBar = new JMenuBar();

            // --- VIEW
            menuView = new JMenu("View");
            menuView.setMnemonic(KeyEvent.VK_V);

            JMenuItem axisFormat = new JMenuItem("E-format");
            axisFormat.addMouseListener(new MouseListener() {
                @Override
                public void mouseClicked(MouseEvent e) {

                }

                @Override
                public void mousePressed(MouseEvent e) {
                    chart.set_formatType(2);
                }

                @Override
                public void mouseReleased(MouseEvent e) {

                }

                @Override
                public void mouseEntered(MouseEvent e) {

                }

                @Override
                public void mouseExited(MouseEvent e) {

                }
            });

        menuView.add(axisFormat);

        menuBar.add(menuView);

        return menuBar;
    }
}

StackChart.java

public class StackChart extends StackPane {

    private final LineChart baseChart;
    private final ObservableList<LineChart> backCharts = FXCollections.observableArrayList();

    private final double yAxisWidth = 60;
    private final AnchorPane details;

    private final double yAxisSeparation = 20;
    private double strokeWidth = 0.3;

    public int _formatType = 1;

    public StackChart(LineChart baseChart, Color lineColor) {
        this(baseChart, lineColor, null);
    }

    public StackChart(LineChart baseChart, Color lineColor, Double strokeWidth) {
        if (strokeWidth != null) {
            this.strokeWidth = strokeWidth;
        }
        this.baseChart = baseChart;
        baseChart.setCreateSymbols(false);
        baseChart.setLegendVisible(false);
        baseChart.getXAxis().setAutoRanging(false);
        baseChart.getXAxis().setAnimated(false);
        baseChart.getXAxis().setStyle("-fx-font-size:" + 18);
        baseChart.getYAxis().setAnimated(false);
        baseChart.getYAxis().setStyle("-fx-font-size:" + 18);

        setStyle(baseChart, lineColor);
        setFixedAxisWidth(baseChart);
        setAlignment(Pos.CENTER_LEFT);

        backCharts.addListener((Observable observable) -> rebuildChart());

        details = new AnchorPane();
        bindMouseEvents(baseChart, this.strokeWidth);

        rebuildChart();
    }

    private void bindMouseEvents(LineChart baseChart, Double strokeWidth) {

        getChildren().add(details);

        details.prefHeightProperty().bind(heightProperty());
        details.prefWidthProperty().bind(widthProperty());
        details.setMouseTransparent(true);

        setOnMouseMoved(null);
        setMouseTransparent(false);

        final Axis xAxis = baseChart.getXAxis();
        final Axis yAxis = baseChart.getYAxis();

        final Line xLine = new Line();
        final Line yLine = new Line();
        yLine.setFill(Color.GRAY);
        xLine.setFill(Color.GRAY);
        yLine.setStrokeWidth(strokeWidth/2);
        xLine.setStrokeWidth(strokeWidth/2);
        xLine.setVisible(false);
        yLine.setVisible(false);

        final Node chartBackground = baseChart.lookup(".chart-plot-background");
        for (Node n: chartBackground.getParent().getChildrenUnmodifiable()) {
            if (n != chartBackground && n != xAxis && n != yAxis) {
                n.setMouseTransparent(true);
            }
        }
        chartBackground.setCursor(Cursor.CROSSHAIR);
        chartBackground.setOnMouseEntered((event) -> {
            chartBackground.getOnMouseMoved().handle(event);
            xLine.setVisible(true);
            yLine.setVisible(true);
            details.getChildren().addAll(xLine, yLine);
        });
        chartBackground.setOnMouseExited((event) -> {

            xLine.setVisible(false);
            yLine.setVisible(false);
            details.getChildren().removeAll(xLine, yLine);
        });
        chartBackground.setOnMouseMoved(event -> {
            double x = event.getX() + chartBackground.getLayoutX();
            double y = event.getY() + chartBackground.getLayoutY();

            xLine.setStartX(65);
            xLine.setEndX(details.getWidth()-10);
            xLine.setStartY(y+5);
            xLine.setEndY(y+5);

            yLine.setStartX(x+5);
            yLine.setEndX(x+5);
            yLine.setStartY(12);
            yLine.setEndY(details.getHeight()-28);
        });

    }

    private void setFixedAxisWidth(LineChart chart) {
        chart.getYAxis().setPrefWidth(yAxisWidth);
        chart.getYAxis().setMaxWidth(yAxisWidth);
    }

    private void rebuildChart() {
        getChildren().clear();

        getChildren().add(resizeBaseChart(baseChart));
        for (LineChart lineChart : backCharts) {
            getChildren().add(resizeBackgroundChart(lineChart));
        }
        getChildren().add(details);
    }

    private Node resizeBaseChart(LineChart lineChart) {
        HBox hBox = new HBox(lineChart);
        hBox.setAlignment(Pos.CENTER_LEFT);
        hBox.prefHeightProperty().bind(heightProperty());
        hBox.prefWidthProperty().bind(widthProperty());

        lineChart.minWidthProperty().bind(widthProperty().subtract((yAxisWidth+yAxisSeparation)*backCharts.size()));
        lineChart.prefWidthProperty().bind(widthProperty().subtract((yAxisWidth+yAxisSeparation)*backCharts.size()));
        lineChart.maxWidthProperty().bind(widthProperty().subtract((yAxisWidth+yAxisSeparation)*backCharts.size()));

        return lineChart;
    }

    private Node resizeBackgroundChart(LineChart lineChart) {
        HBox hBox = new HBox(lineChart);
        hBox.setAlignment(Pos.CENTER_LEFT);
        hBox.prefHeightProperty().bind(heightProperty());
        hBox.prefWidthProperty().bind(widthProperty());
        hBox.setMouseTransparent(true);

        lineChart.minWidthProperty().bind(widthProperty().subtract((yAxisWidth + yAxisSeparation) * backCharts.size()));
        lineChart.prefWidthProperty().bind(widthProperty().subtract((yAxisWidth + yAxisSeparation) * backCharts.size()));
        lineChart.maxWidthProperty().bind(widthProperty().subtract((yAxisWidth + yAxisSeparation) * backCharts.size()));

        lineChart.translateXProperty().bind(baseChart.getYAxis().widthProperty());
        lineChart.getYAxis().setTranslateX((yAxisWidth + yAxisSeparation) * backCharts.indexOf(lineChart));

        return hBox;
    }

    public void addSeries(XYChart.Series series, Color lineColor) {
        NumberAxis yAxis = new NumberAxis();
        NumberAxis xAxis = new NumberAxis();

        // xAxis
        xAxis.setAutoRanging(false);
        xAxis.setVisible(false);
        xAxis.setOpacity(0.0);
        xAxis.lowerBoundProperty().bind(((NumberAxis) baseChart.getXAxis()).lowerBoundProperty());
        xAxis.upperBoundProperty().bind(((NumberAxis) baseChart.getXAxis()).upperBoundProperty());
        xAxis.tickUnitProperty().bind(((NumberAxis) baseChart.getXAxis()).tickUnitProperty());

        // yAxis
        yAxis.setSide(Side.RIGHT);
        yAxis.setLabel(series.getName());
        if(_formatType == 2){
            NumberFormat format = new DecimalFormat("#.#E0");
            yAxis.setTickLabelFormatter(new StringConverter<Number>() {

                @Override
                public String toString(Number number) {
                    return format.format(number.doubleValue());
                }

                @Override
                public Number fromString(String string) {
                    try {
                        return format.parse(string);
                    } catch (ParseException e) {
                        e.printStackTrace();
                        return 0 ;
                    }
                }

            });
        }

        // create chart
        LineChart lineChart = new LineChart(xAxis, yAxis);
        lineChart.setAnimated(false);
        lineChart.setLegendVisible(false);
        lineChart.getData().add(series);

        styleBackChart(lineChart, lineColor);
        setFixedAxisWidth(lineChart);

        backCharts.add(lineChart);
    }

    private void styleBackChart(LineChart lineChart, Color lineColor) {
        setStyle(lineChart, lineColor);

        Node contentBackground = lineChart.lookup(".chart-content").lookup(".chart-plot-background");
        contentBackground.setStyle("-fx-background-color: transparent;");

        lineChart.setVerticalZeroLineVisible(false);
        lineChart.setHorizontalZeroLineVisible(false);
        lineChart.setVerticalGridLinesVisible(false);
        lineChart.setHorizontalGridLinesVisible(false);
        lineChart.setCreateSymbols(false);
        lineChart.getXAxis().setStyle("-fx-font-size:" + 18);
        lineChart.getYAxis().setStyle("-fx-font-size:" + 18);
    }

    private String toRGBCode(Color color) {
        return String.format("#%02X%02X%02X",
                (int) (color.getRed() * 255),
                (int) (color.getGreen() * 255),
                (int) (color.getBlue() * 255));
    }

    private void setStyle(LineChart chart, Color lineColor) {
        chart.getYAxis().lookup(".axis-label").setStyle("-fx-text-fill: " + toRGBCode(lineColor) + "; -fx-font-size: 24;");
        Node seriesLine = chart.lookup(".chart-series-line");
        seriesLine.setStyle("-fx-stroke: " + toRGBCode(lineColor) + "; -fx-stroke-width: " + strokeWidth + ";");
    }

    public Node getLegend() {
        HBox hbox = new HBox();

        final CheckBox baseChartCheckBox = new CheckBox(baseChart.getYAxis().getLabel());
        baseChartCheckBox.setSelected(true);
        baseChartCheckBox.setDisable(true);
        baseChartCheckBox.getStyleClass().add("readonly-checkbox");
        baseChartCheckBox.setOnAction(event -> baseChartCheckBox.setSelected(true));
        hbox.getChildren().add(baseChartCheckBox);

        for (final LineChart lineChart : backCharts) {
            CheckBox checkBox = new CheckBox(lineChart.getYAxis().getLabel());
            checkBox.setSelected(true);
            checkBox.setOnAction(event -> {
                if (backCharts.contains(lineChart)) {
                    backCharts.remove(lineChart);
                } else {
                    backCharts.add(lineChart);
                }
            });
            hbox.getChildren().add(checkBox);
        }

        hbox.setAlignment(Pos.CENTER);
        hbox.setSpacing(20);
        hbox.setStyle("-fx-padding: 0 10 20 10");

        return hbox;
    }

    public int is_formatType() {
        return _formatType;
    }

    public void set_formatType(int formatType) {
        this._formatType = formatType;
        this.requestLayout();
    }
}

最佳答案

问题可能是这段代码

chart.set_formatType(2);

尝试修改 Swing 线程上的 JavaFX 节点。这可能会解决它:

Platform.runLater(new Runnable() { 
    @Override
    public void run() {
        chart.set_formatType(2);
    }
});

这在 JavaFX Tutorials 中有介绍。 .

此外,您的 set_formatType 方法不会执行任何操作。您更改了自己的属性之一并调用 requestLayout,这并没有达到您希望的效果。您需要更改图表的属性之一。这将触发“重画”。

关于java - 如何重新绘制集成到 Swing 中的 StackPane (JavaFX)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30431240/

相关文章:

java - 无法找到或加载主类 Eclipse

JavaFX OnDragDropped 未注册

java - 如何使用 OrmLite 连接到受密码保护的 SQLite 数据库?

java - 无法返回数据

java - 在java中使用套接字进行语音聊天或音频通话

java - JLabel 组件中的几个图像快照

java - 检查从 Play 中的模块导入的所有 URI 的权限

java - SWT 为何比 Swing 快?

Javafx 8 对话框额外边框

JavaFX FXML 无效类型