gpt4 book ai didi

javafx - JavaFX 图表中的缩放选择矩形未显示,但缩放工作正常

转载 作者:行者123 更新时间:2023-12-02 01:30:16 25 4
gpt4 key购买 nike

我编写了一个在 JavaFX 图表上实现缩放功能的示例程序,我从 GitHub 项目中找到了 Zoom 类,我只是重新使用它。我的挑战是,当我拖动鼠标选择某个区域进行缩放时,所选区域矩形在 Windows 7、Linux、Mac OS X 中不显示,但在 Windows 10 中工作正常。我缺少什么,如何让 selectedRectangle 显示以便用户知道他们正在放大哪个区域?

下面是编译和运行该程序所需的所有文件:

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package testlinechartgraphs;

import java.util.ArrayList;
import java.util.Random;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class TestLineChartGraphs extends Application {

final static ObservableList<XYChart.Series<Number, Number>> lineChartData = FXCollections.observableArrayList();

@Override
public void start(Stage stage) {
stage.setTitle("Line Chart Sample");
//defining the axes
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Number of Month");
Random randomNumbers = new Random();
ArrayList<Integer> arrayList = new ArrayList<>();

//creating the chart
final LineChart<Number, Number> lineChart
= new LineChart<Number, Number>(xAxis, yAxis);

lineChart.setTitle("Stock Monitoring, 2010");
lineChart.setLegendSide(Side.RIGHT);

int randomCount = randomNumbers.nextInt(14)+1;
//System.out.println("randomCount = " + randomCount);
for (int i = 0; i < randomCount; i++) {
XYChart.Series series = new XYChart.Series();
series.setName("series_" + i);
for (int k = 0; k < 20; k++) {
int x = randomNumbers.nextInt(50);

series.getData().add(new XYChart.Data(k, x));
}
//seriesList.add(series);
lineChartData.add(series);
}


lineChart.setData(lineChartData);

final StackPane chartContainer = new StackPane();

Zoom zoom = new Zoom(lineChart, chartContainer);

chartContainer.getChildren()
.add(lineChart);

BorderPane borderPane = new BorderPane();

borderPane.setCenter(chartContainer);
//borderPane.setCenter(lineChart);

borderPane.setBottom(getLegend());
////
//Scene scene = new Scene(lineChart, 800, 600);
Scene scene = new Scene(borderPane, 800, 600);
//lineChart.getData().addAll(series, series1);

stage.setScene(scene);
scene.getStylesheets().addAll("file:///C:/Users/siphoh/Documents/NetBeansProjects/WiresharkSeqNum/src/fancychart.css");
//scene.getStylesheets().addAll(getClass().getResource("fancychart.css").toExternalForm());

stage.show();
}

public static Node getLegend() {
HBox hBox = new HBox();

for (final XYChart.Series<Number, Number> series : lineChartData) {
CheckBox checkBox = new CheckBox(series.getName());


checkBox.setSelected(true);
checkBox.setOnAction(event -> {
if (lineChartData.contains(series)) {

lineChartData.remove(series);
} else {
lineChartData.add(series);
}
});

hBox.getChildren().add(checkBox);
}

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

return hBox;
}

public static void main(String[] args) {
launch(args);
}
}

//Zoom.java类:

package testlinechartgraphs;

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/

/**
*
* @author *************
*/
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;

/**
* This class adds a zoom functionality to a given XY chart. Zoom means that a
user can select a region in the chart that should be displayed at a larger
scale.
*
*/
public class Zoom {

private static final String INFO_LABEL_ID = "zoomInfoLabel";
private final Pane pane;
private final XYChart<Number, Number> chart;
private final NumberAxis xAxis;
private final NumberAxis yAxis;
private final SelectionRectangle selectionRectangle;
private Label infoLabel;

private Point2D selectionRectangleStart;
private Point2D selectionRectangleEnd;

/**
* Create a new instance of this class with the given chart and pane
* instances. The {@link Pane} instance is needed as a parent for the
* rectangle that represents the user selection.
*
* @param chart the xy chart to which the zoom support should be added
* @param pane the pane on which the selection rectangle will be drawn.
*/
public Zoom(XYChart<Number, Number> chart, Pane pane) {
this.pane = pane;
this.chart = chart;
this.xAxis = (NumberAxis) chart.getXAxis();
this.yAxis = (NumberAxis) chart.getYAxis();
selectionRectangle = new SelectionRectangle();

pane.getChildren().add(selectionRectangle);
addDragSelectionMechanism();
addInfoLabel();
}

/**
* The info label shows a short info text that tells the user how to unreset
* the zoom level.
*/
private void addInfoLabel() {
infoLabel = new Label("Click ESC to reset the zoom level.");
infoLabel.setId(INFO_LABEL_ID);
pane.getChildren().add(infoLabel);
StackPane.setAlignment(infoLabel, Pos.TOP_RIGHT);
infoLabel.setVisible(false);
}

/**
* Adds a mechanism to select an area in the chart that should be displayed
* at larged scale.
*/
private void addDragSelectionMechanism() {
pane.addEventHandler(MouseEvent.MOUSE_PRESSED, new MousePressedHandler());
pane.addEventHandler(MouseEvent.MOUSE_DRAGGED, new MouseDraggedHandler());
pane.addEventHandler(MouseEvent.MOUSE_RELEASED, new MouseReleasedHandler());
pane.addEventHandler(KeyEvent.KEY_RELEASED, new EscapeKeyHandler());
}

private Point2D computeRectanglePoint(double eventX, double eventY) {
double lowerBoundX = computeOffsetInChart(xAxis, false);
double upperBoundX = lowerBoundX + xAxis.getWidth();
double lowerBoundY = computeOffsetInChart(yAxis, true);
double upperBoundY = lowerBoundY + yAxis.getHeight();
// make sure the rectangle's end point is in the interval defined by the lower and upper bounds for each
// dimension
double x = Math.max(lowerBoundX, Math.min(eventX, upperBoundX));
double y = Math.max(lowerBoundY, Math.min(eventY, upperBoundY));
return new Point2D(x, y);
}

/**
* Computes the pixel offset of the given node inside the chart node.
*
* @param node the node for which to compute the pixel offset
* @param vertical flag that indicates whether the horizontal or the
* vertical dimension should be taken into account
* @return the offset inside the chart node
*/
private double computeOffsetInChart(Node node, boolean vertical) {
double offset = 0;
do {
if (vertical) {
offset += node.getLayoutY();
} else {
offset += node.getLayoutX();
}
node = node.getParent();
} while (node != chart);
return offset;
}

/**
*
*/
private final class MousePressedHandler implements EventHandler<MouseEvent> {

@Override
public void handle(final MouseEvent event) {

// do nothing for a right-click
if (event.isSecondaryButtonDown()) {
return;
}

// store position of initial click
selectionRectangleStart = computeRectanglePoint(event.getX(), event.getY());
event.consume();
}
}

/**
*
*/
private final class MouseDraggedHandler implements EventHandler<MouseEvent> {

@Override
public void handle(final MouseEvent event) {

// do nothing for a right-click
if (event.isSecondaryButtonDown()) {
return;
}

// store current cursor position
selectionRectangleEnd = computeRectanglePoint(event.getX(), event.getY());

double x = Math.min(selectionRectangleStart.getX(), selectionRectangleEnd.getX());
double y = Math.min(selectionRectangleStart.getY(), selectionRectangleEnd.getY());
double width = Math.abs(selectionRectangleStart.getX() - selectionRectangleEnd.getX());
double height = Math.abs(selectionRectangleStart.getY() - selectionRectangleEnd.getY());

drawSelectionRectangle(x, y, width, height);
event.consume();
}

/**
* Draws a selection box in the view.
*
* @param x the x position of the selection box
* @param y the y position of the selection box
* @param width the width of the selection box
* @param height the height of the selection box
*/
private void drawSelectionRectangle(final double x, final double y, final double width, final double height) {
selectionRectangle.setVisible(true);
selectionRectangle.setX(x);
selectionRectangle.setY(y);
selectionRectangle.setWidth(width);
selectionRectangle.setHeight(height);
//selectionRectangle.setFill(Color.LIGHTSEAGREEN.deriveColor(0, 1, 1, 0.5));
//System.out.println("Draw the rectangle ...");
}
}

/**
*
*/
private final class MouseReleasedHandler implements EventHandler<MouseEvent> {

/**
* Defines a minimum width for the selected area. If the selected
* rectangle is not wider than this value, no zooming will take place.
* This helps prevent accidental zooming.
*/
private static final double MIN_RECTANGE_WIDTH = 10;

/**
* Defines a minimum height for the selected area. If the selected
* rectangle is not wider than this value, no zooming will take place.
* This helps prevent accidental zooming.
*/
private static final double MIN_RECTANGLE_HEIGHT = 10;

@Override
public void handle(final MouseEvent event) {
hideSelectionRectangle();

if (selectionRectangleStart == null || selectionRectangleEnd == null) {
return;
}

if (isRectangleSizeTooSmall()) {
return;
}

setAxisBounds();
showInfo();
selectionRectangleStart = null;
selectionRectangleEnd = null;

// needed for the key event handler to receive events
pane.requestFocus();
event.consume();
}

private boolean isRectangleSizeTooSmall() {
double width = Math.abs(selectionRectangleEnd.getX() - selectionRectangleStart.getX());
double height = Math.abs(selectionRectangleEnd.getY() - selectionRectangleStart.getY());
return width < MIN_RECTANGE_WIDTH || height < MIN_RECTANGLE_HEIGHT;
}

/**
* Hides the selection rectangle.
*/
private void hideSelectionRectangle() {
selectionRectangle.setVisible(false);
}

private void setAxisBounds() {
disableAutoRanging();

// compute new bounds for the chart's x and y axes
double selectionMinX = Math.min(selectionRectangleStart.getX(), selectionRectangleEnd.getX());
double selectionMaxX = Math.max(selectionRectangleStart.getX(), selectionRectangleEnd.getX());
double selectionMinY = Math.min(selectionRectangleStart.getY(), selectionRectangleEnd.getY());
double selectionMaxY = Math.max(selectionRectangleStart.getY(), selectionRectangleEnd.getY());

setHorizontalBounds(selectionMinX, selectionMaxX);
setVerticalBounds(selectionMinY, selectionMaxY);
}

private void disableAutoRanging() {
xAxis.setAutoRanging(false);
yAxis.setAutoRanging(false);
}

private void showInfo() {
infoLabel.setVisible(true);
}

/**
* Sets new bounds for the chart's x axis.
*
* @param minPixelPosition the x position of the selection rectangle's
* left edge (in pixels)
* @param maxPixelPosition the x position of the selection rectangle's
* right edge (in pixels)
*/
private void setHorizontalBounds(double minPixelPosition, double maxPixelPosition) {
double currentLowerBound = xAxis.getLowerBound();
double currentUpperBound = xAxis.getUpperBound();
double offset = computeOffsetInChart(xAxis, false);
setLowerBoundX(minPixelPosition, currentLowerBound, currentUpperBound, offset);
setUpperBoundX(maxPixelPosition, currentLowerBound, currentUpperBound, offset);
}

/**
* Sets new bounds for the chart's y axis.
*
* @param minPixelPosition the y position of the selection rectangle's
* upper edge (in pixels)
* @param maxPixelPosition the y position of the selection rectangle's
* lower edge (in pixels)
*/
private void setVerticalBounds(double minPixelPosition, double maxPixelPosition) {
double currentLowerBound = yAxis.getLowerBound();
double currentUpperBound = yAxis.getUpperBound();
double offset = computeOffsetInChart(yAxis, true);
setLowerBoundY(maxPixelPosition, currentLowerBound, currentUpperBound, offset);
setUpperBoundY(minPixelPosition, currentLowerBound, currentUpperBound, offset);
}

private void setLowerBoundX(double pixelPosition, double currentLowerBound, double currentUpperBound,
double offset) {
double newLowerBound = computeBound(pixelPosition, offset, xAxis.getWidth(), currentLowerBound,
currentUpperBound, false);
xAxis.setLowerBound(newLowerBound);
}

private void setUpperBoundX(double pixelPosition, double currentLowerBound, double currentUpperBound,
double offset) {
double newUpperBound = computeBound(pixelPosition, offset, xAxis.getWidth(), currentLowerBound,
currentUpperBound, false);
xAxis.setUpperBound(newUpperBound);
}

private void setLowerBoundY(double pixelPosition, double currentLowerBound, double currentUpperBound,
double offset) {
double newLowerBound = computeBound(pixelPosition, offset, yAxis.getHeight(), currentLowerBound,
currentUpperBound, true);
yAxis.setLowerBound(newLowerBound);
}

private void setUpperBoundY(double pixelPosition, double currentLowerBound, double currentUpperBound,
double offset) {
double newUpperBound = computeBound(pixelPosition, offset, yAxis.getHeight(), currentLowerBound,
currentUpperBound, true);
yAxis.setUpperBound(newUpperBound);
}

private double computeBound(double pixelPosition, double pixelOffset, double pixelLength, double lowerBound,
double upperBound, boolean axisInverted) {
double pixelPositionWithoutOffset = pixelPosition - pixelOffset;
double relativePosition = pixelPositionWithoutOffset / pixelLength;
double axisLength = upperBound - lowerBound;

// The screen's y axis grows from top to bottom, whereas the chart's y axis goes from bottom to top.
// That's
// why we need to have this distinction here.
double offset = 0;
int sign = 0;
if (axisInverted) {
offset = upperBound;
sign = -1;
} else {
offset = lowerBound;
sign = 1;
}

double newBound = offset + sign * relativePosition * axisLength;
return newBound;
}
}

/**
*
*/
private final class EscapeKeyHandler implements EventHandler<KeyEvent> {

@Override
public void handle(KeyEvent event) {

// the ESCAPE key lets the user reset the zoom level
if (KeyCode.ESCAPE.equals(event.getCode())) {
resetAxisBounds();
hideInfo();
}
}

private void resetAxisBounds() {
xAxis.setAutoRanging(true);
yAxis.setAutoRanging(true);
}

private void hideInfo() {
infoLabel.setVisible(false);
}
}

}

//SelectionRectangle.java类

package testlinechartgraphs;

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/

/**
*
* @author **************
*/
import javafx.scene.shape.Rectangle;

/**
* Represents an area on the screen that was selected by a mouse drag operation.
*
*/
public class SelectionRectangle extends Rectangle {

private static final String STYLE_CLASS_SELECTION_BOX = "chart-selection-rectangle";

public SelectionRectangle() {

getStyleClass().addAll(STYLE_CLASS_SELECTION_BOX);
setVisible(false);
setManaged(false);
setMouseTransparent(true);

}
}

//fancychart.css文件

.chart-line-symbol {
-fx-scale-x: 0.5;
-fx-scale-y: 0.5;
}

.chart-popup-label {
-fx-padding: 1 3 1 3;
-fx-border-radius: 1;
-fx-border-width: 1;
-fx-opacity: 0.7;
-fx-effect: dropshadow( two-pass-box , rgba(0,0,0,0.3) , 8, 0.0 , 0 , 3 );
}

.chart-legend-item {
-fx-padding : 1 23 1 23;
}

.chart-legend-item-symbol {
-fx-scale-x: 0.8;
-fx-scale-y: 0.8;
}



.chart-selection-rectangle {
-fx-stroke: rgba(135, 206, 250, 0.8);
-fx-stroke-type: inside;
-fx-fill: rgba(135, 206, 250, 0.2);
}







#zoomInfoLabel {
-fx-background-color: rgba(135, 206, 250, 0.8);
-fx-font-size: 14;
-fx-padding: 3;
-fx-background-radius: 2;
}

如果能解决此问题,我们将不胜感激。

谢谢,

最佳答案

您的订单有误。你有

    final StackPane chartContainer = new StackPane();
Zoom zoom = new Zoom(lineChart, chartContainer);
chartContainer.getChildren().add(lineChart);

这意味着您首先创建容器,然后添加缩放矩形,然后添加图表。所以缩放矩形在图表的背面。

你需要这样:

    final StackPane chartContainer = new StackPane();
chartContainer.getChildren().add(lineChart);
Zoom zoom = new Zoom(lineChart, chartContainer);

关于javafx - JavaFX 图表中的缩放选择矩形未显示,但缩放工作正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34687153/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com