2017-01-16 144 views
1

下面是Main.classController.class,我试图尽可能简化它。JavaFX Canvas在StackPane中没有正确调整大小

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


黑色为StackPane名为visualizerStackPane和内它是一个命名为CanvasvisualizerCanvas我想要做的是在StackPane内部的Canvas相应地调整为StackPane大小减去4。但是,当您调整窗口大小时,一切都会失败。

你有什么尝试...

1)将窗口最大化,然后归回。

2)增加窗口的大小,并慢慢减少它。

为什么发生这种情况?I 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:

我已经从Initialize方法改性Controller类油漆画布和除去绑定,它不起作用它产生的下面:

enter image description here

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

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> 

最后:

非常感谢谁将会设法解决次的人是问题:)。

+0

从你的'初始化()'方法删除所有行。您试图自己控制布局操作,这会干扰StackPane的工作能力。相反,你可以在StackPane上设置一个宽度为2的额外边框,或者将StackPane的填充设置为0.5,或者将Canvas的StackPane.margin设置为0.5。 – VGR

+0

@VGR那么我怎样才能得到宽度和高度的画布呢?画布会自动调整大小吗?每当我将一个ChangeListener添加到'Canvas'的'widthProperty'和'heightProperty'时,我就会得到'-1'。我感谢你的帮助...... :) – GOXR3PLUS

+0

StackPane已经将每个孩子的大小设置为StackPane的内容大小(StackPane的大小减去其内嵌)。你不必做任何事情。 – VGR

回答

1

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


从这个问题的最终答案很高兴:How to make canvas Resizable in javaFX?

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


ResizableCavas.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(); 
    } 
} 

Controller.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); 

    } 
} 
1

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

您声明当您打印和heightCanvas时,它返回-1。而不是这样做,打印容器StackPanewidthheight。由于Canvas毕竟完全包含在StackPane之内,因此如果不相同,则widthheight将几乎相同。

+0

你好Michael我修改了代码,甚至没有工作....我已经改变了'Controller.java'没有绑定,也没有修改'Canvas'的宽度,但它没有被绘制。虽然当我修改宽度和高度Canvas'就像你在第二张图片中看到的那样:) :)感谢您的帮助... – GOXR3PLUS

+0

在宽度和高度属性侦听器中取出resizeVisualizer调用。 –

+0

我需要一种将'canvasWidth'和'canvasHeight'绑定到Canvas的'width'和'height'而不使用绑定的方式..这是出于性能原因,导致我在'Canvas'中绘制动画 – GOXR3PLUS