有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JavaFX画布在StackPane内未正确调整大小

下面是Main.classController.class,我试图使它尽可能简单

程序输出以下窗口: enter image description here


黑色是一个名为visualizerStackPaneStackPane,里面是一个名为visualizerCanvasCanvas我想做的是Canvas内的StackPane将根据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);
    }
}

控制器。java:

我已经修改了控制器类来绘制画布,并从Initialize方法中删除了绑定,但它不起作用,它会产生以下结果:

enter image description here

如果我不手动设置画布的宽度和高度,它甚至不会被绘制。。。我不知道为什么

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())

        }
    }
}

控制器。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>

最后:

A big thanks to the person who will manage to solve this problem :).


共 (2) 个答案

  1. # 1 楼答案

    经过研究,我找到了解决办法。从Canvas创建自定义Canvas类和@Overriding方法:


    🌾非常高兴从这个问题的最后答案:How to make canvas Resizable in javaFX?

    🌾给了我这个想法的链接:http://dlsc.com/2014/04/10/javafx-tip-1-resizable-canvas/


    可调整大小的莱卡瓦斯。java:

    import javafx.scene.canvas.Canvas;
    import javafx.scene.canvas.GraphicsContext;
    import javafx.scene.paint.Color;
    
    class ResizableCanvas extends Canvas {
    
        GraphicsContext gc                  = getGraphicsContext2D();
        int             canvasWidth         = 0;
        int             canvasHeight        = 0;
        int             halfCanvasHeight    = 0;
    
        /**
         * Constructor
         */
        public ResizableCanvas() {
    
            // if i didn't add the draw to the @Override resize(double width, double
            // height) then it must be into the below listeners
    
            // Redraw canvas when size changes.
            widthProperty().addListener((observable, oldValue, newValue) -> {
                System.out.println("Entered WIDTH property");
                canvasWidth = (int) widthProperty().get();
            });
            heightProperty().addListener((observable, oldValue, newValue) -> {
                System.out.println("Entered HEIGHT property");
    
                canvasHeight = (int) heightProperty().get();
                halfCanvasHeight = canvasHeight >> 1;
            });
    
        }
    
        /**
         * Redraw the Canvas
         */
        private void draw() {
    
            System.out.println(" Real Canvas Width is:" + getWidth() + " , Real Canvas Height is:" + getHeight() + "\n");
    
            gc.clearRect(0, 0, canvasWidth, canvasHeight);
    
            gc.setStroke(Color.RED);
            gc.strokeLine(0, 0, canvasWidth, canvasHeight);
            gc.strokeLine(0, canvasHeight, canvasWidth, 0);
        }
    
        @Override
        public double minHeight(double width) {
            return 1;
        }
    
        @Override
        public double maxHeight(double width) {
            return Double.MAX_VALUE;
        }
    
        @Override
        public double prefHeight(double width) {
            return minHeight(width);
        }
    
        @Override
        public double minWidth(double height) {
            return 1;
        }
    
        @Override
        public double maxWidth(double height) {
            return Double.MAX_VALUE;
        }
    
        @Override
        public boolean isResizable() {
            return true;
        }
    
        @Override
        public void resize(double width, double height) {
            super.setWidth(width);
            super.setHeight(height);
            draw();
        }
    }
    

    控制器。java:

    import java.io.IOException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    import javafx.beans.property.SimpleIntegerProperty;
    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 VBox topRightVBox;
    
        @FXML
        private StackPane mediaFileStackPane;
    
        @FXML
        private GridPane bottomGridPane;
    
        //                
    
        ResizableCanvas visualizerCanvas = new ResizableCanvas();
    
        /**
         * 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() {
    
            visualizerStackPane.getChildren().add(visualizerCanvas);
    
        }
    }
    
  2. # 2 楼答案

    initialize()方法中删除绑定。您正试图自己控制布局操作,这会阻止StackPane执行它应该执行的操作。这将适当地调整Canvas的大小

    您声明当您打印widthheightCanvas时,它返回-1。不要这样做,而是打印容器widthheightStackPane。毕竟,由于Canvas完全包含在StackPane中,因此widthheight如果不完全相同,则几乎是相同的