1

我的 VBOX 有一些问题,我寻找其他可以帮助我的问题,但遗憾的是没有任何效果。我有一个带有一堆滑块和按钮的 VBox,发生的事情是我可以随意调整它。所以我可以把它做得小到它里面的按钮会消失,或者我可以把它做得大到它会覆盖我程序的其他部分。我尝试了 vbox.setMaxSize 和 vbox.setMinxSize,但没有发生任何事情。我还应该对其中的按钮和滑块做些什么吗?我虽然因为按钮和滑块是 Vbox childrem,所以我在 Vbox 上所做的更改也适用于它们。我将发布控制器类,然后是 FXML 文件,如果需要其他类,请随意告诉我。非常感谢。

控制器

package fotofinish;

import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Slider;
import javafx.scene.control.ToggleGroup;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;

//TODO: Find a better way to have image be refreshed
public class FXMLDocumentController implements Initializable {

    private static final Logger logger = Logger.getLogger(fotofinish.FXMLDocumentController.class.getName());

    Stage stage;
    private FotoFinishModel model = new FotoFinishModel();
    @FXML
    private Slider brightnessSlider;
    @FXML
    private Slider contrastSlider;
    @FXML
    private ToggleGroup brushTypeRadioGroup;
    @FXML
    private RadioButton brushTypeCircleRadioButton;
    @FXML
    private RadioButton brushTypeSpraypaintRadioButton;
    @FXML
    private RadioButton brushTypeSquareRadioButton;
    @FXML
    private ColorPicker brushColorPicker;
    @FXML
    private NumberFieldFX brushSizeNumberField;
    @FXML
    private ImageView imageViewer;
    @FXML
    private ScrollPane imageScrollPane;
    @FXML
    private VBox vbox; 

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        //TODO: WHAT IS BLOCK INCREMENT?
        this.brightnessSlider.valueProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
            if(model.changeBrightness(newValue.doubleValue())) {
                this.refreshImageViewer();
            }
        });

        //TODO: convert to dragged call
        this.contrastSlider.valueProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
            if (model.changeContrast(newValue.doubleValue())) {
                this.refreshImageViewer();
            }
        });
    }

    @FXML
    private void filterGrayscale(ActionEvent ignored) {
        model.applyGrayscaleFilter();
        this.refreshImageViewer();
        this.resetSliders();
    }

    @FXML
    private void filterSepia(ActionEvent ignored) {
        model.applySepiaFilter();
        this.refreshImageViewer();
        this.resetSliders();
    }

    @FXML
    private void filterInstant(ActionEvent ignored) {
        model.applyInstantFilter();
        this.refreshImageViewer();
        this.resetSliders();
    }

    @FXML
    private void filterCustom(ActionEvent ignored) {
        //TODO: code to create custom filter popup and get arguments for custom filter
        logger.log(Level.INFO, "TODO: custom filter popup launched");
        model.applyCustomFilter();
        this.refreshImageViewer();
        this.resetSliders();
    }

    @FXML
    private void filterNone(ActionEvent ignored) {
        model.resetImageToOriginal();
        this.refreshImageViewer();
        this.resetSliders();
    }

    @FXML
    private void brushTypeCircle(ActionEvent ignored) {
        model.setBrushTypeCircle();
    }

    @FXML
    private void brushTypeSquare(ActionEvent ignored) {
        model.setBrushTypeSquare();
    }

    @FXML
    private void brushTypeSpraypaint(ActionEvent ignored) {
        model.setBrushTypeSpraypaint();
    }

    @FXML
    private void helpDoc(ActionEvent ignored) {
        logger.log(Level.INFO, "TODO: help document launched");
    }

    @FXML
    private void aboutDialog(ActionEvent ignored) {
        logger.log(Level.INFO, "TODO: about dialog created");
    }

    @FXML
    private void brushColor(ActionEvent ignored) {
        model.changeBrushColor(this.brushColorPicker.getValue());
    }

    @FXML
    private void brushSize(ActionEvent ignored) {
        model.changeBrushSize(Integer.parseInt(this.brushSizeNumberField.getText()));
    }

    //TODO: make title setting more intelligent
    @FXML
    private void open(ActionEvent ignored) {
        logger.log(Level.INFO, "open file chooser launched");
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Open Image");
        fileChooser.getExtensionFilters().add(new ExtensionFilter("Image Files", "*.png")); //TODO: add other types
        File selectedFile = fileChooser.showOpenDialog(null); //TODO: needs value in order to block main window
        if (selectedFile != null) {
            logger.log(Level.INFO, "file {0} choosen in open file chooser", selectedFile);
            model.loadImage(selectedFile);
            this.refreshImageViewer();
            this.stage.setTitle("Foto Finish - " + selectedFile);
        } else {
            logger.log(Level.INFO, "no file selected in open file chooser");
        }
    }

    @FXML
    private void galleryButterfly(ActionEvent ignored) {
        model.loadGalleryButterflyImage();
        this.refreshImageViewer();
    }

    @FXML
    private void galleryTeddyBear(ActionEvent ignored) {
        model.loadGalleryTeddyBearImage();
        this.refreshImageViewer();
    }

    @FXML
    private void galleryPrincess(ActionEvent ignored) {
        model.loadGalleryPrincessImage();
        this.refreshImageViewer();
    }

    @FXML
    private void galleryFirefighter(ActionEvent ignored) {
        model.loadGalleryFirefighterImage();
        this.refreshImageViewer();
    }

    @FXML
    private void save(ActionEvent ignored) {
        model.saveImage();
    }

    @FXML
    private void saveAs(ActionEvent ignored) {
        logger.log(Level.INFO, "save as file chooser launched");
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Save Image");
        fileChooser.getExtensionFilters().add(new ExtensionFilter("Image Files", "*.png")); //TODO: add other types
        File selectedFile = fileChooser.showSaveDialog(null); //TODO: needs value in order to block main window
        if (selectedFile != null) {
            logger.log(Level.INFO, "file {0} choosen in save as file chooser", selectedFile);
            model.saveImageAs(selectedFile);
        } else {
            logger.log(Level.INFO, "no file selected in save as file chooser");
        }
    }

    @FXML
    private void quit(ActionEvent ignored) {
        logger.log(Level.INFO, "quitting");
        Platform.exit(); //TODO: make this detect unsaved changes
    }

    @FXML
    private void newFile(ActionEvent ignored) {
        logger.log(Level.INFO, "TODO: new file created");
    }

    private void refreshImageViewer() {
        this.imageViewer.setImage(model.getImage());
        logger.log(Level.INFO, "image refreshed");
    }

    //TODO: make this connect better with FXML default value
    private void resetSliders() {
        this.brightnessSlider.setValue(0);
        this.contrastSlider.setValue(0);
        logger.log(Level.INFO, "brightness and contrast sliders reset");
    }

    public void setStage(Stage stageFromMain) {
        this.stage = stageFromMain;
    }
}

FXML

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

<?import javafx.geometry.*?>
<?import javafx.scene.input.*?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="500.0" minWidth="600.0" prefHeight="700.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fotofinish.FXMLDocumentController">
   <top>
      <MenuBar prefHeight="0.0" prefWidth="1034.0" BorderPane.alignment="CENTER">
        <menus>
          <Menu mnemonicParsing="false" text="File">
            <items>
                  <MenuItem fx:id="menubarFileNew" mnemonicParsing="false" onAction="#newFile" text="New">
                     <accelerator>
                        <KeyCodeCombination alt="UP" code="N" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
                     </accelerator>
                  </MenuItem>
                  <SeparatorMenuItem mnemonicParsing="false" />
                  <MenuItem fx:id="menubarFileOpen" mnemonicParsing="false" onAction="#open" text="Open">
                     <accelerator>
                        <KeyCodeCombination alt="UP" code="O" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
                     </accelerator>
                  </MenuItem>
                  <Menu mnemonicParsing="false" text="Open from Gallery">
                    <items>
                      <MenuItem fx:id="menubarFileGalleryButterfly" mnemonicParsing="false" onAction="#galleryButterfly" text="Butterfly" />
                        <MenuItem fx:id="menubarFileGalleryTeddyBear" mnemonicParsing="false" onAction="#galleryTeddyBear" text="Teddy Bear" />
                        <MenuItem fx:id="menubarFileGalleryPrincess" mnemonicParsing="false" onAction="#galleryPrincess" text="Princess" />
                        <MenuItem fx:id="menubarFileGalleryFirefighter" mnemonicParsing="false" onAction="#galleryFirefighter" text="Firefighter" />
                    </items>
                  </Menu>
                  <SeparatorMenuItem mnemonicParsing="false" />
                  <MenuItem fx:id="menubarFileSave" mnemonicParsing="false" onAction="#save" text="Save">
                     <accelerator>
                        <KeyCodeCombination alt="UP" code="S" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
                     </accelerator>
                  </MenuItem>
                  <MenuItem fx:id="menubarFileSaveAs" mnemonicParsing="false" onAction="#saveAs" text="Save As">
                     <accelerator>
                        <KeyCodeCombination alt="UP" code="S" control="DOWN" meta="UP" shift="DOWN" shortcut="UP" />
                     </accelerator>
                  </MenuItem>
                  <SeparatorMenuItem mnemonicParsing="false" />
              <MenuItem fx:id="menubarFileQuit" mnemonicParsing="false" onAction="#quit" text="Quit">
                     <accelerator>
                        <KeyCodeCombination alt="UP" code="C" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
                     </accelerator></MenuItem>
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Help">
            <items>
              <MenuItem fx:id="menubarHelpFotoFinishHelpMenuItem" mnemonicParsing="false" onAction="#helpDoc" text="Foto Finish Help">
                     <accelerator>
                        <KeyCodeCombination alt="UP" code="F1" control="UP" meta="UP" shift="UP" shortcut="UP" />
                     </accelerator></MenuItem>
                  <MenuItem fx:id="menubarHelpAboutMenuItem" mnemonicParsing="false" onAction="#aboutDialog" text="About" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
   </top>
   <center>
      <SplitPane dividerPositions="0.14941569282136896" minHeight="-Infinity" minWidth="-Infinity" prefHeight="160.0" prefWidth="200.0" BorderPane.alignment="CENTER">
        <items>
          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
               <children>
                  <VBox fx:id="vbox" alignment="TOP_CENTER" layoutX="-11.0" layoutY="25.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="100.0" prefHeight="200.0" prefWidth="100.0" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
                     <children>
                        <Label fx:id="sliderLabel" alignment="TOP_LEFT" text="Sliders">
                           <padding>
                              <Insets left="10.0" />
                           </padding>
                        </Label>
                        <GridPane alignment="CENTER">
                          <columnConstraints>
                            <ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" maxWidth="104.0" minWidth="10.0" prefWidth="84.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 minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                              <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                          </rowConstraints>
                           <children>
                              <Button fx:id="filterGrayscaleButton" contentDisplay="TOP" mnemonicParsing="false" onAction="#filterGrayscale" prefHeight="25.0" prefWidth="84.0" text="Grayscale" textAlignment="CENTER" GridPane.rowIndex="1">
                                 <opaqueInsets>
                                    <Insets top="50.0" />
                                 </opaqueInsets>
                              </Button>
                              <Button fx:id="filterSepiaButton" mnemonicParsing="false" onAction="#filterSepia" prefHeight="25.0" prefWidth="83.0" text="Sepia" GridPane.rowIndex="2" />
                              <Button fx:id="filterInstantButton" mnemonicParsing="false" onAction="#filterInstant" prefHeight="25.0" prefWidth="83.0" text="Instant" GridPane.rowIndex="3" />
                              <Button fx:id="filterCustomButton" mnemonicParsing="false" onAction="#filterCustom" prefHeight="25.0" prefWidth="82.0" text="Custom" GridPane.rowIndex="4" />
                              <Button fx:id="filterNoneButton" mnemonicParsing="false" onAction="#filterNone" prefHeight="25.0" prefWidth="82.0" text="None" GridPane.rowIndex="5" />
                           </children>
                           <padding>
                              <Insets left="10.0" />
                           </padding>
                        </GridPane>
                        <GridPane prefHeight="271.0" prefWidth="176.0">
                          <columnConstraints>
                            <ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                          </columnConstraints>
                          <rowConstraints>
                            <RowConstraints maxHeight="88.0" minHeight="10.0" prefHeight="35.0" vgrow="SOMETIMES" />
                            <RowConstraints maxHeight="290.0" minHeight="26.0" prefHeight="59.0" vgrow="SOMETIMES" />
                              <RowConstraints maxHeight="233.0" minHeight="6.0" prefHeight="40.0" />
                              <RowConstraints maxHeight="127.0" minHeight="28.0" prefHeight="56.0" />
                              <RowConstraints maxHeight="148.0" minHeight="23.0" prefHeight="34.0" />
                              <RowConstraints maxHeight="124.0" minHeight="41.0" prefHeight="51.0" />
                          </rowConstraints>
                           <children>
                              <Label fx:id="brightnessLabel" text="Brightness" />
                              <Label fx:id="contrastLabel" text="Contrast" GridPane.rowIndex="2" />
                              <Slider fx:id="brightnessSlider" max="1.0" min="-1.0" minorTickCount="10" orientation="HORIZONTAL" showTickLabels="true" showTickMarks="true" snapToTicks="true" GridPane.rowIndex="1" />
                              <Slider fx:id="contrastSlider" max="1.0" min="-1.0" minorTickCount="10" orientation="HORIZONTAL" showTickLabels="true" showTickMarks="true" snapToTicks="true" GridPane.rowIndex="3" />
                              <Label text="Saturation" GridPane.rowIndex="4" />
                              <Slider max="1.0" min="-1.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" snapToTicks="true" GridPane.rowIndex="5" />
                           </children>
                           <padding>
                              <Insets left="10.0" right="10.0" />
                           </padding>
                        </GridPane>
                        <Label fx:id="drawingLabel" text="Drawing" />
                        <ColorPicker fx:id="brushColorPicker" onAction="#brushColor" />
                        <Label fx:id="brushTypeLabel" text="Brush Type" />
                        <RadioButton fx:id="brushTypeCircleRadioButton" mnemonicParsing="false" onAction="#brushTypeCircle" selected="true" text="Circle">
                           <toggleGroup>
                              <ToggleGroup fx:id="brushTypeRadioGroup" />
                           </toggleGroup>
                        </RadioButton>
                        <RadioButton fx:id="brushTypeSquareRadioButton" mnemonicParsing="false" onAction="#brushTypeSquare" text="Square" toggleGroup="$brushTypeRadioGroup" />
                        <RadioButton fx:id="brushTypeSpraypaintRadioButton" mnemonicParsing="false" onAction="#brushTypeSpraypaint" text="Spraypaint" toggleGroup="$brushTypeRadioGroup" />
                        <Label fx:id="brushSizeLabel" text="Brush Size" />
                        <fotofinish.NumberFieldFX fx:id="brushSizeTextField" onAction="#brushSize" text="10" />
                        <Label fx:id="filtersLabel" text="Filters" />
                     </children>
                  </VBox>
               </children>
            </AnchorPane>
          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="369.0" prefWidth="465.0">
               <children>
                  <ScrollPane layoutX="145.0" layoutY="111.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                     <content>
                        <ImageView fx:id="imageViewer" fitHeight="577.0" fitWidth="1010.0" pickOnBounds="true" preserveRatio="true" />
                     </content>
                  </ScrollPane>
               </children>
            </AnchorPane>
        </items>
      </SplitPane>
   </center>
</BorderPane>
4

0 回答 0