我的出发点如下:
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.canvas.*?>
<?import javafx.scene.shape.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="scalingcanvas.FXMLDocumentController">
<center>
<AnchorPane BorderPane.alignment="CENTER">
<children>
<Canvas fx:id="canvas" height="200.0" width="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</center>
<top>
<Label text="top" BorderPane.alignment="CENTER" />
</top>
<bottom>
<Label text="bottom" BorderPane.alignment="CENTER" />
</bottom>
<left>
<Label text="left" BorderPane.alignment="CENTER" />
</left>
<right>
<Label text="right" BorderPane.alignment="CENTER" />
</right>
</BorderPane>
Java FX控制器:
package scalingcanvas;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
public class FXMLDocumentController implements Initializable {
@FXML
private Canvas canvas;
@Override
public void initialize(URL url, ResourceBundle rb) {
System.out.printf("hi\n");
GraphicsContext g2d = canvas.getGraphicsContext2D();
double w = canvas.getWidth();
double h = canvas.getHeight();
g2d.setFill(Color.ALICEBLUE);
g2d.fillRect(0, 0, w, h);
g2d.setStroke(Color.BLUE);
g2d.strokeOval(0, 0, w, h);
g2d.strokeLine(0, 0, w, h);
g2d.strokeLine(0, h, w, 0);
}
}
package scalingcanvas;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class ScalePanel extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
根据我在这里找到的代码,我最终得出了这个解决方案:
/*
* Based on http://gillius.org/blog/2013/02/javafx-window-scaling-on-resize.html
*/
package dsfxcontrols;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Node;
import javafx.scene.layout.StackPane;
/**
* A StackPane that <i>scales</i> its contents to fit (preserving aspect ratio),
* or fill (scaling independently in X and Y) the available area.
* <p>
* Note <code>AutoScalingStackPane</code> applies to the contents a scaling
* transformation rather than attempting to resize the contents.
* <p>
* If the contents is a Canvas with pixel dimension 50 by 50, after scaling the
* Canvas still will have 50 by 50 pixels and the appearance may be pixelated
* (this might be desired if the application is interfacing a camera and the
* Canvas needs to match in size the camera's CCD size).
* <p>
* If the content contains FX Controls then these get magnified rather than
* resized, that is all text and graphics are scaled (this might be desired for
* Point of Sale full screen applications)
* <p>
* <h3>Known Limitations</h3>
* Rescaling occurs only when the AutoScalingStackPane is resized, it does not
* occur automatically if and when the content changes size.
*
*
* @author michaelellis
*/
public class AutoScalingStackPane extends StackPane {
/**
* Force scale transformation to be recomputed based on the size of this
* <code>AutoScalingStackPane</code> and the size of the contents.
*/
public void rescale() {
if (!getChildren().isEmpty()) {
getChildren().forEach((c) -> {
double xScale = getWidth() / c.getBoundsInLocal().getWidth();
double yScale = getHeight() / c.getBoundsInLocal().getHeight();
if (autoScale.get() == AutoScale.FILL) {
c.setScaleX(xScale);
c.setScaleY(yScale);
} else if (autoScale.get() == AutoScale.FIT) {
double scale = Math.min(xScale, yScale);
c.setScaleX(scale);
c.setScaleY(scale);
} else {
c.setScaleX(1d);
c.setScaleY(1d);
}
});
}
}
private void init() {
widthProperty().addListener((b, o, n) -> rescale());
heightProperty().addListener((b, o, n) -> rescale());
}
/**
* No argument constructor required for Externalizable (need this to work
* with SceneBuilder).
*/
public AutoScalingStackPane() {
super();
init();
}
/**
* Convenience constructor that takes a content Node.
*
* @param content
*/
public AutoScalingStackPane(Node content) {
super(content);
init();
}
/**
* AutoScale scaling options:
* {@link AutoScale#NONE}, {@link AutoScale#FILL}, {@link AutoScale#FIT}
*/
public enum AutoScale {
/**
* No scaling - revert to behaviour of <code>StackPane</code>.
*/
NONE,
/**
* Independently scaling in x and y so content fills whole region.
*/
FILL,
/**
* Scale preserving content aspect ratio and center in available space.
*/
FIT
}
// AutoScale Property
private ObjectProperty<AutoScale> autoScale = new SimpleObjectProperty<AutoScale>(this, "autoScale",
AutoScale.FIT);
/**
* AutoScalingStackPane scaling property
*
* @return AutoScalingStackPane scaling property
* @see AutoScale
*/
public ObjectProperty<AutoScale> autoScaleProperty() {
return autoScale;
}
/**
* Get AutoScale option
*
* @return the AutoScale option
* @see AutoScale
*/
public AutoScale getAutoScale() {
return autoScale.getValue();
}
/**
* Set the AutoScale option
*
* @param newAutoScale
* @see AutoScale
*
*/
public void setAutoScale(AutoScale newAutoScale) {
autoScale.setValue(newAutoScale);
}
}
AutoScalingStackPane应用缩放转换来缩放其内容,以填充或适合StackPane大小(保留纵横比)。我添加了一个AutoScale属性,允许您选择缩放选项(无、适合、缩放)。
如果您编译到一个Jar,它就可以在SceneBuilder中使用(和测试)。下面是我使用它的fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.web.*?>
<?import java.lang.*?>
<?import dsfxcontrols.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.shape.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import scalingcanvas.*?>
<?import javafx.scene.text.*?>
<?language javascript?>
<BorderPane fx:id="root" prefHeight="324.0" prefWidth="318.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<top>
<Label text="top" BorderPane.alignment="CENTER" />
</top>
<bottom>
<Label fx:id="bottom" text="bottom" BorderPane.alignment="CENTER" />
</bottom>
<left>
<Label text="left" BorderPane.alignment="CENTER" />
</left>
<right>
<Label text="right" BorderPane.alignment="CENTER" />
</right>
<center>
<AutoScalingStackPane minHeight="20.0" minWidth="20.0" style="-fx-border-color: blue; -fx-background-color: aliceblue;" BorderPane.alignment="CENTER">
<children>
<Group>
<children>
<Circle fill="#c891c9b2" radius="100.0" stroke="BLACK" strokeType="INSIDE" />
<Circle fill="#ff781f62" layoutX="73.0" layoutY="111.0" radius="79.0" stroke="BLACK" strokeType="INSIDE" />
<Rectangle arcHeight="5.0" arcWidth="5.0" fill="DODGERBLUE" height="129.0" layoutX="-22.0" layoutY="-19.0" opacity="0.24" stroke="#f80000" strokeType="INSIDE" strokeWidth="3.0" width="141.0" />
<Button layoutX="-86.0" layoutY="150.0" mnemonicParsing="false" onAction="bottom.setText(Date());timeLabel.setText(Date());" text="Hello" />
<Label fx:id="timeLabel" alignment="CENTER" layoutX="-86.0" layoutY="-70.0" text="Label" textAlignment="CENTER">
<font>
<Font name="Brush Script MT Italic" size="12.0" />
</font>
</Label>
</children>
</Group>
</children>
</AutoScalingStackPane>
</center>
</BorderPane>
我的JavaFX 8应用程序中有以下代码,用于控制添加到场景中的画布元素的变换比例: 问题是,就像它所说的,附加到转换中,并且由于浮点精度,每次滚动时缩放级别都会略有不同。 由于某些原因,我必须修改图形上下文转换,而不是直接修改画布(换句话说,要进行翻译,我必须使用transform.setTx(…) 而不是画布。setTranslateX(…) 。 解决方案是设置转换的尺度,同时考虑枢轴点(即鼠
缩放画布时,有什么方法可以阻止这种模糊吗?我想这和GPU插值有关。但我这里需要的是一个像素完美的“像素化”变焦。只需使用最近的“真实”相邻像素的颜色。 我在这里看到了解决方案,但在这两个解决方案中,有一个建议工作(#1/#4),#4肯定是CPU扩展,而#1我猜也是。 这种缩放需要快速——我希望能够支持多达20-25层(可能是StackPane中的画布,但我对其他想法持开放态度,只要它们不融化中央处
我想在JavaFX中实现一个linechart,它应该是可缩放/可滚动的。 我使用SceneBuilder创建图表,所有数据都正确显示。我的目标是用户能够放大和滚动到侧面(x轴)。
问题内容: 如何才能平滑地为画布创建缩放动画?GWT提供了一种获取滚轮数量的方法和。 这里的问题是,每个车轮运动都会执行此方法,并且如果我在该方法本身中调用画布重绘,事情会变得很滞后。 因此,我想到了以某种方式制作缩放动画的方法。但是如何? 我考虑过创建一个,但没有真正的主意,因为只有mousewheelevent作为起点,而用户没有完成用滚轮缩放的终点… 问题答案: 这是我用来缩放图像的可伸缩图
除了平移和旋转,HTML5的画布API还提供了缩放画布上下文的手段。本节,我们将使用scale()方法来按比例缩小画布上下文的高度。 图4-5 缩放画布上下文 绘制步骤 按照以下步骤,绘制一个按比例缩小的矩形: 1. 定义画布上下文,及矩形的尺寸: window.onload = function(){ var canvas = document.getElementById("myCan
我一直在尝试使用JavaFX中的缩放转换,但还没有完全理解它。基本上,我有一个窗格包含一个复杂的图形,并希望能够撤销它。缩放部分本身工作得很好,但是,封闭的滚动窗格将不适应图形。 为了简单起见,我将发布一个简短的示例,其中我的图被一个标签替换: null 我错过了什么?如何使滚动窗格适应内容视图? 谢谢你的帮助。