我需要根据窗口的宽度计算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);
}
}