如何在JavaFX初始化期间设置切片宽度?

时间:2018-01-03 20:22:07

标签: java javafx

我需要根据窗口的宽度计算TilePane的prefTileWidth。我为此编写了一个方法,当我打印到控制台时,它显示正确的宽度,但它们不会应用于TilePane。

我发现mainStage的宽度是在Main中的primaryStage.show()之后设置的。如果我尝试在show()之前获取primaryStage.getWidth,则返回NaN。但是TilePane是在show()之前创建的。所以我需要一些方法来获得创建TilePane时的primaryStage的宽度。我已经找到了解决方案,但没有找到任何解决方案。有谁知道如何解决这个问题? 这是我的代码的最小工作示例:

控制器:

html {
    min-height: 100%;
    height: 100%;
}

body{
    min-height: 100%;
    height: 100%;
    background: #7F7F7F;
}

.modalContainer{
    display: flex;
    align-items: center;
    justify-content: center;
    padding-top: 48px;
    padding-bottom: 48px;
    height: calc(100vh - 96px);
    max-height: calc(100vh - 96px);
}

.modalContent{
    height: 100%;
    max-width: 950px;
    vertical-align: middle;
    background-color: #FFF;
    border: 1px solid rgb(201, 201, 209);
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
    overflow-y: hidden;
}

.titleBar {
  display: grid;
  grid-template-columns: auto 22px;
  background-color: gray;
  padding: 0 20px 0 17px;
}

.titleBar i {
  color: white;
  font-size: 22px;
  align-self: center;
}

.modalBody{
  display: grid;
  grid-template-columns: 340px auto;
  height: calc(100vh - 18.5%);
}

.modalBody p{
  margin:3px;
}

.modalBody p:nth-child(even){
  background-color: #cccccc;
}

.modalBody p:nth-child(odd){
  background-color: #f2f2f2;
}

.MBLeft{
  border-right: 2px solid gray;
  height: 100%;
}

.MBRight{
  overflow-y: auto;
}

.rightContent{
  padding: 23px 20px 20px;
}

.sectionTop {
  padding: 23px 20px 20px;
  border-bottom: 2px solid gray;
}

.sectionBottom{
  padding: 23px 20px 20px;
  overflow-y: auto;
  height: 55vh;
}

.sectionBottom p{
  padding-bottom: 7px;
}

主:

public class Controller {
private static LinkedHashMap<String, BigDecimal> mProductMap = new LinkedHashMap<>();
private double prefTileWidth;

@FXML private TilePane fieldContainer = new TilePane();

@FXML
public void initialize() {
    // I tried setting the prefTileWidth here,
    // but at this point I can't get the primaryStage.getWidth() yet, because that will return NaN
    try {
        importFrom(new File("mainMap.txt"));
    } catch (Exception e) {
        e.printStackTrace();
    }
    addButtons();
}

// calculates the prefTileWidth of the TilePane
public void tilePaneSize(double width) {
    fieldContainer.setPrefTileWidth(width / 2 - 10);
    prefTileWidth = fieldContainer.getPrefTileWidth();
    System.out.println("Width of primaryStage = " + width);   // returns 314.3999938964844
    System.out.println("tile width = " + prefTileWidth);   // returns 147.1999969482422
    // Outcomes are correct, but the tiles don't resize to prefTileWidth
    // How do I make this work?
}

// adds products and their prices to the LinkedHashMap mProductMap
public void addProduct(String product, BigDecimal price) {
    mProductMap.put(product, price);
}

// adds buttons to the TilePane
private void addButtons() {
    // clears the TilePane to prevent duplicate buttons
    fieldContainer.getChildren().clear();

    for (Map.Entry<String, BigDecimal> entry : mProductMap.entrySet()) {
        StackPane newField = new StackPane();
        Button main = new Button();
        Button multiply = new Button();
        Button subtract = new Button();

        main.setText(entry.getKey() + "\n" + entry.getValue());
        main.getStyleClass().add("main-btn-bg-color");
        multiply.getStyleClass().add("inner-button");
        multiply.getStyleClass().add("multiply-btn");
        subtract.getStyleClass().add("inner-button");
        subtract.getStyleClass().add("subtract-btn");
        StackPane.setAlignment(multiply, Pos.BOTTOM_LEFT);
        StackPane.setAlignment(subtract, Pos.BOTTOM_CENTER);
        StackPane.setMargin(multiply, new Insets(0, 0, 8, 8));
        StackPane.setMargin(subtract, new Insets(0, 0, 8, 16));

        newField.getChildren().add(main);
        newField.getChildren().add(multiply);
        newField.getChildren().add(subtract);
        fieldContainer.setAlignment(Pos.TOP_LEFT);
        fieldContainer.getChildren().add(newField);
    }
}

// imports the map with products and prices from txt file
public void importFrom(File file) {
    try (
            FileInputStream fis = new FileInputStream(file);
            BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
    ) {
        String line;
        while((line = reader.readLine()) != null) {
            String[] args = line.split("\\|");
            addProduct(new String(args[0]), new BigDecimal(args[1]));
        }
    } catch(IOException ioe) {
        System.out.printf("Problems loading %s %n", file);
        ioe.printStackTrace();
    }
  }
}

FXML:

public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
    Parent root = FXMLLoader.load(getClass().getResource("/fxml/counter.fxml"));
    primaryStage.setScene(new Scene(root, 300, 500));
    // This is one solution I tried. Again it gets the right outcome, but the tiles are not responding to it:
    // Controller ctrl = new Controller();
    // ctrl.tilePaneSize(primaryStage.getScene().getWidth());
    primaryStage.show();

    Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
    primaryStage.setMaxWidth(815);
    primaryStage.setMaxHeight(800);
    Controller ctrl = new Controller();
    ctrl.tilePaneSize(primaryStage.getWidth());

    if (visualBounds.getWidth() <= 800) {
        primaryStage.setFullScreen(true);
    }
}
public static void main(String[] args) {
    launch(args);
}
}

0 个答案:

没有答案