【发布时间】:2017-01-16 22:48:57
【问题描述】:
下面是Main.class 和Controller.class,我尽量让它更简单。
黑色是StackPane,名为visualizerStackPane,里面是Canvas,名为visualizerCanvas。 我想要做的是 StackPane 内的 Canvas 相应地调整为 StackPane 大小减法 4 。但是,当您调整窗口大小时,一切都会失败。
你必须尝试什么......
1)最大化窗口,然后将其归一化。
2)增大窗口大小,然后慢慢减小。
为什么会这样?我有这个问题 3 个月了,但我找不到解决方案...
我也看过JavaFX - Resize Canvas when screen is resized,但这里的问题似乎有所不同...
Main.java:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
//Scene
Scene scene = new Scene(new Controller(), 400, 400);
primaryStage.setScene(scene);
//Show
primaryStage.show();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Controller.java:
我已经修改了 Controller 类来绘制 Canvas 并从 Initialize 方法中删除了绑定,它不起作用它会产生以下内容:
如果我不手动设置画布的宽度和高度,它甚至不会被绘制...我不知道为什么。
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
public class Controller extends StackPane {
@FXML
private GridPane container;
@FXML
private GridPane topGridPane;
@FXML
private StackPane visualizerStackPane;
@FXML
private Canvas visualizerCanvas;
@FXML
private VBox topRightVBox;
@FXML
private StackPane mediaFileStackPane;
@FXML
private GridPane bottomGridPane;
// ------------------------------
GraphicsContext gc;
int canvasWidth = 0;
int canvasHeight = 0;
/**
* Constructor
*/
public Controller() {
// ------------------------FXMLLoader ---------------------------------
FXMLLoader loader = new FXMLLoader(getClass().getResource("Controller.fxml"));
loader.setController(this);
loader.setRoot(this);
try {
loader.load();
} catch (IOException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Controller FXML can't be loaded!", ex);
}
}
/**
* Called as soon as FXML FILE has been loaded
*/
@FXML
private void initialize() {
gc = visualizerCanvas.getGraphicsContext2D();
// // VisualizerStackPane inside which visualizerCanvas is
// visualizerCanvas.widthProperty().bind(visualizerStackPane.widthProperty().subtract(4));
// visualizerCanvas.heightProperty().bind(visualizerStackPane.heightProperty().subtract(4));
//
// Add width and height change listeners
visualizerStackPane.widthProperty().addListener((observable, oldValue,
newValue) -> resizeVisualizerCanvas(newValue.doubleValue(), visualizerStackPane.getHeight()));
visualizerStackPane.heightProperty().addListener((observable, oldValue,
newValue) -> resizeVisualizerCanvas(visualizerStackPane.getWidth(), newValue.doubleValue())
);
repaintCanvas();
}
/**
* Repaints the Canvas
*/
public void repaintCanvas() {
//Clear the previous rectangle
gc.clearRect(0, 0, canvasWidth, canvasHeight);
// Draw the
gc.setFill(Color.RED);
gc.fillRect(0, 0, canvasWidth, canvasHeight);
// Draw the Line
gc.setLineWidth(3);
gc.setStroke(Color.WHITE);
gc.strokeLine(0, canvasHeight, canvasWidth, 0);
}
/**
* Resizes the visualizerCanvas to the given values.
*
* @param width
* the width
* @param height
* the height
*/
public void resizeVisualizerCanvas(double width, double height) {
if (width > 0 && height > 0) {
this.canvasWidth = (int) width;
this.canvasHeight = (int) height;
// Print something
System.out.println("Canvas Width is:" + width+" , Canvas Height is:"+height +" Canvas is Resizable: "+visualizerCanvas.isResizable());
// Repaint the Canvas
repaintCanvas();
// ---------------------------Below i have tried several things to
// solve the problem....
// Set the width and height of Canvas
visualizerCanvas.setWidth(width);
visualizerCanvas.setHeight(height);
// Careful with contentBias here
prefWidth(-1);
prefHeight(-1);
// autosize()
// System.out.println("Content Bias is:"+this.getContentBias())
}
}
}
Controller.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.canvas.Canvas?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<fx:root prefHeight="212.0" prefWidth="456.0" type="StackPane" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<padding>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</padding>
<children>
<GridPane fx:id="container">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="50.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="50.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" percentHeight="40.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" percentHeight="60.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<GridPane fx:id="topGridPane" gridLinesVisible="true" GridPane.columnSpan="2">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="50.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="50.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<StackPane fx:id="visualizerStackPane" style="-fx-border-color: white; -fx-border-width: 1.5; -fx-background-color: rgb(0,0,0,0.95);">
<children>
<Canvas fx:id="visualizerCanvas" />
</children>
</StackPane>
<VBox fx:id="topRightVBox" GridPane.columnIndex="1">
<children>
<StackPane prefHeight="150.0" prefWidth="200.0">
<children>
<Region style="-fx-background-color: rgb(255,255,255,0.7);" />
<Label alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" style="-fx-font-weight: bold;" text="text here" />
</children>
</StackPane>
<StackPane fx:id="mediaFileStackPane" maxWidth="1.7976931348623157E308" />
</children>
</VBox>
</children>
</GridPane>
<GridPane fx:id="bottomGridPane" gridLinesVisible="true" GridPane.columnSpan="2" GridPane.rowIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="20.0" prefWidth="35.0" />
<ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" minWidth="10.0" percentWidth="60.0" prefWidth="343.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="20.0" prefWidth="52.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<Region style="-fx-background-color: rgb(255,255,255,0.7);" />
<Label alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" style="-fx-font-weight: bold;" text="text here" textAlignment="CENTER" wrapText="true" StackPane.alignment="CENTER" />
</children>
</StackPane>
<VBox prefHeight="200.0" prefWidth="100.0" spacing="5.0" />
</children>
</GridPane>
</children>
</GridPane>
</children>
</fx:root>
最后:
非常感谢能够解决这个问题的人:)。
【问题讨论】:
-
从
initialize()方法中删除所有行。您正试图自己控制布局操作,这会干扰 StackPane 的工作能力。相反,您可以在 StackPane 上设置一个宽度为 2 的附加边框,或者将 StackPane 的 padding 设置为所有边 0.5,或者将 Canvas 的 StackPane.margin 设置为所有边的 0.5。 -
@VGR 那么我如何获得画布的宽度和高度?画布会自动调整大小吗?每当我将 ChangeListener 添加到
Canvas的widthProperty和heightProperty时,我都会得到-1。感谢您的帮助... :) -
StackPane 已经根据 StackPane 的内容大小(StackPane 的大小减去其 insets)调整每个子项的大小。您无需执行任何操作。
-
@VGR 那么我不知道如何在调整大小时获得 Canvas 的宽度和高度,因为属性确实返回 -1 :(
-
我按照@VGR 的评论做了,它正确调整了大小。为了获得画布的大小,我将监听器切换到堆栈窗格,并打印了
newValue。那应该是正确的尺寸。