- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我编写了一个在 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/
我找到了 this excellent question and answer它以 x/y(加上 center x/y 和 degrees/radians)开始并计算旋转- 到 x'/y'。这个计算很
全部: 我已经创建了一个 Windows 窗体和一个按钮。在另一个线程中,我试图更改按钮的文本,但它崩溃了;但是如果我尝试更改按钮的颜色,它肯定会成功。我认为如果您更改任何 Windows 窗体控件属
本网站的另一个问题已证实,C 中没有缩写的字面后缀,并且可以执行以下操作: short Number = (short)1; 但是转换它和不这样做有什么区别: short Number = 1; 您使
我有下表: ID (int) EMAIL (varchar(50)) CAMPAIGNID (int) isSubscribe (bit) isActionByUser (bit) 此表存储了用户对事
也就是说,无需触发Javascript事件即可改变的属性,如何保留我手动选中或取消选中的复选框的状态,然后复制到另一个地方? 运行下面的代码片段并选中或取消选中其中的一些,然后点击“复制”: $('#
我在网上找到的所有关于递增指针导致段错误的示例都涉及指针的取消引用 - 如果我只想递增它(例如在 for 循环的末尾)并且我不在乎它是否最终进入无效内存,因为我不会再使用它。例如,在这个程序中,每次迭
我有一个 Spring MVC REST 服务,它使用 XStream 将消息与 XML 相互转换。 有什么方法可以将请求和响应中的 xml(即正文)打印到普通的 log4j 记录器? 在 Contr
做我的任务有一个很大的挑战,那就是做相互依赖的任务我在这张照片中说的。假设我们有两个任务 A 和 B,执行子任务 A1、A2 和 B1、B2,假设任务 B 依赖于 A。 要理想地执行任务 B,您应该执
通过阅读该网站上的几个答案,我了解到 CoInitialize(Ex) should be called by the creator of a thread 。然后,在该线程中运行的任何代码都可以使
这个问题已经困扰我一段时间了。我以前从未真正使用过 ListViews,也没有使用过 FirebaseListAdapters。我想做的就是通过显示 id 和用户位置来启动列表的基础,但由于某种原因,
我很难解释这两个(看似简单)句子的含义: “受检异常由编译器在编译时检查” 这是什么意思?编译器检查是否捕获了所有已检查的异常(在代码中抛出)? “未经检查的异常在运行时检查,而不是编译时” 这句话中
我有一个包含排除子字符串的文本文件,我想迭代该文件以检查并返回不带排除子字符串的输入项。 这里我使用 python 2.4,因此下面的代码可以实现此目的,因为 with open 和 any 不起作用
Spring 的缓存框架能否了解请求上下文的身份验证状态,或者更容易推出自己的缓存解决方案? 最佳答案 尽管我发现这个用例 super 奇怪,但您可以为几乎任何与 SpEL 配合使用的内容设置缓存条件
我有以下函数模板: template HeldAs* duplicate(MostDerived *original, HeldAs *held) { // error checking omi
如果我的应用程序具有设备管理员/设备所有者权限(未获得 root 权限),我如何才能从我的应用程序中终止(或阻止启动)另一个应用程序? 最佳答案 设备所有者可以阻止应用程序: DevicePolicy
非常简单的问题,但我似乎无法让它正常工作。 我有一个组件,其中有一些 XSLT(用于导航)。它通过 XSLT TBB 使用 XSLT Mediator 发布。 发布后
我正在将一个对象拖动到一个可拖放的对象内,该对象也是可拖动的。放置对象后,它会嵌套在可放置对象内。同样,如果我将对象拖到可放置的外部,它就不再嵌套。 但是,如果我经常拖入和拖出可放置对象,则可拖动对象
我正在尝试为按钮和弹出窗口等多个指令实现“取消选择”功能。也就是说,我希望当用户单击不属于指令模板一部分的元素时触发我的函数。目前,我正在使用以下 JQuery 代码: $('body').click
我从 this question 得到了下面的代码,该脚本用于在 Google tasks 上更改 iframe[src="about:blank"] 内的 CSS使用 Chrome 扩展 Tempe
我有一些 @Mock 对象,但没有指定在该对象上调用方法的返回值。该方法返回 int (不是 Integer)。我很惊讶地发现 Mockito 没有抛出 NPE 并返回 0。这是预期的行为吗? 例如:
我是一名优秀的程序员,十分优秀!