JavaFX dynamic resizing

寵の児 提交于 2020-02-25 05:52:20

问题


Thank you for your help. I've been trying to create a ribbon responsive layout like the one in Word, where the items resize one after another, and so far I haven't had much luck with it.

custom_control.fxml

<fx:root type="javafx.scene.layout.VBox" fx:id="dis" minHeight="-1.0" minWidth="-1.0" prefWidth="350.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
  <GridPane fx:id="grid">
    <children>
      <Button text="Button" GridPane.columnIndex="0" GridPane.rowIndex="0" />
      <RadioButton text="RadioButton" GridPane.columnIndex="1" GridPane.rowIndex="0" />
      <Button onAction="#doSomething" text="Click Me" GridPane.columnIndex="1" GridPane.rowIndex="1" />
      <ComboBox GridPane.columnIndex="0" GridPane.rowIndex="1" />
      <Slider GridPane.columnIndex="0" GridPane.rowIndex="2" />
      <CheckBox text="CheckBox" GridPane.columnIndex="1" GridPane.rowIndex="2" />
      <TextField fx:id="textField" prefWidth="200.0" GridPane.columnIndex="0" GridPane.rowIndex="3" />
      <MenuButton fx:id="mb" mnemonicParsing="false" text="" GridPane.columnIndex="1" GridPane.rowIndex="3">
        <items>
          <MenuItem mnemonicParsing="false" text="Action 1" />
          <MenuItem mnemonicParsing="false" text="Action 2" />
        </items>
      </MenuButton>
    </children>
    <columnConstraints>
      <ColumnConstraints hgrow="NEVER" maxWidth="+Infinity" minWidth="10.0" percentWidth="60.0" prefWidth="100.0" />
      <ColumnConstraints hgrow="NEVER" maxWidth="+Infinity" minWidth="10.0" percentWidth="40.0" prefWidth="100.0" />
    </columnConstraints>
    <rowConstraints>
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    </rowConstraints>
  </GridPane>
</fx:root>

CustomController.java

public class CustomController extends VBox {

    /**
     * Initializes the controller class.
     */

    @FXML private TextField textField;
    @FXML private VBox dis;
    @FXML private GridPane grid;

    //dis.prefWidthProperty().bind(grid.widthProperty());

    public CustomController() {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("custom_control.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    public String getText() {
        return textProperty().get();
    }

    public void setText(String value) {
        textProperty().set(value);
    }

    public StringProperty textProperty() {
        return textField.textProperty();
    }

    public void adaptWidth(double width) {
        /*textField.textProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("textfield changed from " + oldValue + " to " + newValue);
        });*/
    }

    @FXML
    protected void doSomething() {
        System.out.println("The button was clicked!");
    }
 }


**RibbonJavaFX.java**

    public class RibbonJavaFX extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        HBox start = new HBox();
        CustomController rib1= new CustomController();
        rib1.setText("Ribbon 1");
        CustomController rib2 = new CustomController();
        rib2.setText("Ribbon 2");
        CustomController rib3 = new CustomController();
        rib3.setText("Ribbon 3");
        start.getChildren().add(rib1);
        start.getChildren().add(rib2);
        start.getChildren().add(rib3);

        rib3.prefWidthProperty().bind(rib2.widthProperty());
        rib2.prefWidthProperty().bind(rib1.widthProperty());


        Scene scene = new Scene(start,1800,400);

        stage.setScene(scene);
            //scene.getStylesheets().add(getClass().getResource("custom_control.css").toExternalForm());

        stage.setTitle("Custom Control");
        stage.setWidth(300);
        stage.setHeight(200);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }  
}

So this is how my work looks so far. I've been trying to bind the 3 controllers together, but since it has to be made dynamic and for future use, because all controllers are the same, so they have to adapt to each other. My goal is to make them resize one after another, like the Word toolbar. Can somebody please help me with this? I don't expect a full answer, a hint is maybe all I need.


回答1:


Updated answer! This answer uses a SplitPane and an HBox to accomplish the task. It grows the approapitate StackPane depending the position of the SplitPane's divider and the direction the divider is moving. You should be able to make a custom control using these ideas.

Main

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
 *
 * @author blj0011
 */
public class JavaFXApplication232 extends Application
{

    @Override
    public void start(Stage stage) throws Exception
    {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        launch(args);
    }

}

Controller

import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicBoolean;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;

/**
 *
 * @author blj0011
 */
public class FXMLDocumentController implements Initializable
{

    @FXML
    HBox hBox;
    @FXML
    SplitPane splitPane;
    @FXML
    AnchorPane anchorPane2;

    @FXML
    StackPane sp1, sp2, sp3, sp4;

    double orgX, orgY;

    double PANE_MIN_WIDTH = 0;
    double PANE_STARTING_WIDTH = 200;
    double PANES_TOTAL_WIDTH = 800;

    AtomicBoolean initialMove = new AtomicBoolean(true);

    @Override
    public void initialize(URL url, ResourceBundle rb)
    {
        SplitPane.Divider divider = splitPane.getDividers().get(0);

        divider.positionProperty().addListener((obs, oldValue, newValue) -> {
            //System.out.println("oldValue: " + oldValue.doubleValue() + " newValue: " + newValue);
            //System.out.println(anchorPane2.getWidth() + " :: " + (PANES_TOTAL_WIDTH - 2 * PANE_STARTING_WIDTH));

            if (newValue.doubleValue() > oldValue.doubleValue() && !initialMove.get()) {
                if (anchorPane2.getWidth() <= PANES_TOTAL_WIDTH && anchorPane2.getWidth() > PANES_TOTAL_WIDTH - PANE_STARTING_WIDTH) {
                    sp1.setMinWidth(PANE_MIN_WIDTH);
                    sp1.setMaxWidth(anchorPane2.getWidth() - (PANES_TOTAL_WIDTH - PANE_STARTING_WIDTH));
                }
                else if (anchorPane2.getWidth() <= (PANES_TOTAL_WIDTH - PANE_STARTING_WIDTH) && anchorPane2.getWidth() > (PANES_TOTAL_WIDTH - 2 * PANE_STARTING_WIDTH)) {
                    sp2.setMinWidth(PANE_MIN_WIDTH);
                    sp2.setMaxWidth(anchorPane2.getWidth() - (PANES_TOTAL_WIDTH - 2 * PANE_STARTING_WIDTH));
                }
                else if (anchorPane2.getWidth() <= (PANES_TOTAL_WIDTH - 2 * PANE_STARTING_WIDTH) && anchorPane2.getWidth() > (PANES_TOTAL_WIDTH - 3 * PANE_STARTING_WIDTH)) {
                    sp3.setMinWidth(PANE_MIN_WIDTH);
                    sp3.setMaxWidth(anchorPane2.getWidth() - (PANES_TOTAL_WIDTH - 3 * PANE_STARTING_WIDTH));
                }
            }
            else if (newValue.doubleValue() < oldValue.doubleValue()) {
                if (anchorPane2.getWidth() < (PANES_TOTAL_WIDTH - 3 * PANE_STARTING_WIDTH)) {
                    sp4.setMaxWidth(PANE_STARTING_WIDTH);
                    sp4.setMinWidth(anchorPane2.getWidth());
                }
                else if (anchorPane2.getWidth() < (PANES_TOTAL_WIDTH - 2 * PANE_STARTING_WIDTH) && anchorPane2.getWidth() >= (PANES_TOTAL_WIDTH - 3 * PANE_STARTING_WIDTH)) {
                    sp3.setMaxWidth(PANE_STARTING_WIDTH);
                    sp3.setMinWidth(anchorPane2.getWidth() - PANE_STARTING_WIDTH);
                }
                else if (anchorPane2.getWidth() < (PANES_TOTAL_WIDTH - PANE_STARTING_WIDTH) && anchorPane2.getWidth() >= (PANES_TOTAL_WIDTH - 2 * PANE_STARTING_WIDTH)) {
                    sp2.setMaxWidth(PANE_STARTING_WIDTH);
                    sp2.setMinWidth(anchorPane2.getWidth() - 2 * PANE_STARTING_WIDTH);
                }
                else if (anchorPane2.getWidth() <= PANES_TOTAL_WIDTH && anchorPane2.getWidth() >= (PANES_TOTAL_WIDTH - PANE_STARTING_WIDTH)) {
                    sp1.setMaxWidth(PANE_STARTING_WIDTH);
                    sp1.setMinWidth(anchorPane2.getWidth() - 3 * PANE_STARTING_WIDTH);
                }
            }

            initialMove.set(false);//Used becase of the first pass, the AnchorPane's width = 0
        });
    }
}

FXML

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>

<SplitPane fx:id="splitPane" dividerPositions="0.0" prefHeight="160.0" prefWidth="808.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication232.FXMLDocumentController">
   <items>
      <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
      <AnchorPane fx:id="anchorPane2" maxWidth="1.7976931348623157E308" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="800.0">
         <children>
            <HBox fx:id="hBox" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="203.0" prefWidth="800.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
               <children>
                  <StackPane fx:id="sp1" maxWidth="200.0" minWidth="0.0" prefWidth="200.0" style="-fx-background-color: green;" />
                  <StackPane fx:id="sp2" maxWidth="200.0" minWidth="200.0" prefWidth="200.0" style="-fx-background-color: blue;" />
                  <StackPane fx:id="sp3" maxWidth="200.0" minWidth="200.0" prefWidth="200.0" style="-fx-background-color: yellow;" />
                  <StackPane fx:id="sp4" maxWidth="200.0" minWidth="200.0" prefWidth="200.0" style="-fx-background-color: brown;" />
               </children>
            </HBox>
         </children>
      </AnchorPane>
   </items>
</SplitPane>


来源:https://stackoverflow.com/questions/51602566/javafx-dynamic-resizing

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!