首页 > 解决方案 > HBox setMargin错误(HBox类型的静态方法设置边距(节点,昆虫)应该以静态方式访问)用于类分配

问题描述

我有我当前的课堂作业,我无法为我的矩形设置边距。这是一个水果列表,应该计算用户采摘的所需水果的总数。HBox 用于显示窗口的底部,其中有我的结帐按钮以及矩形中心的总标签,到目前为止工作得很好。但是,我正在尝试设置矩形的边距,使其在底部看起来更加居中,并且我一直遇到这个设置边距静态错误。请帮忙,如果有人能告诉我如何为我的总数设置一个例外,如果用户不想从我的水果选项中挑选,其中未挑选的总数 = 0,我会很高兴。另外,请让我知道是否有一些更清洁的编码方式,也很想知道:)

public class Grid_Layout extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }
    
    public void start(Stage primaryStage) 
    {   
        
        BorderPane border = new BorderPane(); // for the title use 
        HBox hbox = new HBox(20); // for the rectangle, checkout button, and the total label         // 20 for spacing      
        
        
        // Calling out GridPane and setting alignments and measurements
        GridPane pane = new GridPane();
        border.setCenter(pane);
        border.setBottom(hbox);
        pane.setAlignment(Pos.CENTER);
        pane.setPadding(new Insets(10,20,10,20)); //top, right, bottom, left space between content and border
        pane.setHgap(10); 
        pane.setVgap(20); 
        pane.setStyle("-fx-background-color: #e6ffb3;");
        
        // Set images as Image
        
        Image apple_img = new Image("File:images/apple.png");
        Image apricot_img = new Image("File:images/apricot.png");
        Image banana_img = new Image("File:images/banana.png");
        Image cherry_img = new Image("File:images/cherry.png");
        Image grape_img = new Image("File:images/grape.png");
        Image lemmon_img = new Image("File:images/lemmon.png");
        Image orange_img = new Image("File:images/orange.png");
        Image pear_img = new Image("File:images/pear.png");
        Image strawberry_img = new Image("File:images/strawberry.png");
        Image watermelon_img = new Image("File:images/watermelon.png");
        
        // To set Image(s) to ImageView in order to display
        
        ImageView apple_iv = new ImageView(apple_img);
        pane.add(apple_iv, 0, 1);
        
        ImageView apricot_iv = new ImageView(apricot_img);
        pane.add(apricot_iv, 3, 1);
        
        ImageView banana_iv = new ImageView(banana_img);
        pane.add(banana_iv, 6, 1);
        
        ImageView cherry_iv = new ImageView(cherry_img);
        pane.add(cherry_iv, 0, 2);
        
        ImageView grape_iv = new ImageView(grape_img);
        pane.add(grape_iv, 3, 2);
        
        ImageView lemmon_iv = new ImageView(lemmon_img);
        pane.add(lemmon_iv, 6, 2);
        
        ImageView orange_iv = new ImageView(orange_img);
        pane.add(orange_iv, 0, 3);
        
        ImageView pear_iv = new ImageView(pear_img);
        pane.add(pear_iv, 3, 3);
        
        ImageView strawberry_iv = new ImageView(strawberry_img);
        pane.add(strawberry_iv, 6, 3);
        
        ImageView watermelon_iv = new ImageView(watermelon_img);
        pane.add(watermelon_iv, 0, 4);
        
        
        
        // To insert all of the textfields for user input
        
        TextField tf1 = new TextField();
        tf1.setMaxWidth(50);
        TextField tf2 = new TextField();
        tf2.setMaxWidth(50);
        TextField tf3 = new TextField();
        tf3.setMaxWidth(50);
        TextField tf4 = new TextField();
        tf4.setMaxWidth(50);
        TextField tf5 = new TextField();
        tf5.setMaxWidth(50);
        TextField tf6 = new TextField();
        tf6.setMaxWidth(50);
        TextField tf7 = new TextField();
        tf7.setMaxWidth(50);
        TextField tf8 = new TextField();
        tf8.setMaxWidth(50);
        TextField tf9 = new TextField();
        tf9.setMaxWidth(50);
        TextField tf10 = new TextField();
        tf10.setMaxWidth(50);
        
        // To insert all of the labels
        
        pane.add(new Label("0.99/lb"), 1, 1);
        pane.add(tf1, 2, 1);
        pane.add(new Label("1.49/lb"), 4, 1);
        pane.add(tf2, 5, 1);
        pane.add(new Label("0.49/lb"), 7, 1);
        pane.add(tf3, 8, 1);
        pane.add(new Label("1.99/lb"), 1, 2);
        pane.add(tf4, 2, 2);
        pane.add(new Label("0.99/lb"), 4, 2);
        pane.add(tf5, 5, 2);
        pane.add(new Label("1.99/lb"), 7, 2);
        pane.add(tf6, 8, 2);
        pane.add(new Label("0.99/lb"), 1, 3);
        pane.add(tf7, 2, 3);
        pane.add(new Label("1.49/lb"), 4, 3);
        pane.add(tf8, 5, 3);
        pane.add(new Label("1.99/lb"), 7, 3);
        pane.add(tf9, 8, 3);
        pane.add(new Label("0.99/lb"), 1, 4);
        pane.add(tf10, 2, 4);
        
        // to lock in prefered window size for the user, it is still resizable
        
        ColumnConstraints col = new ColumnConstraints();
        col.setPercentWidth(10);
        pane.setPrefSize(700, 350);
        pane.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);
        
        
        // Body title
        
        Label titlelbl = new Label("Anna's Fresh Market");
        border.setTop(titlelbl);
        BorderPane.setAlignment(titlelbl, Pos.CENTER);
        titlelbl.setPadding(new Insets(10));
        titlelbl.setStyle("-fx-font-size: 25px; -fx-text-fill: green;-fx-background-color: #e6ffb3;");
        border.setStyle("-fx-background-color: #e6ffb3;");
        
        // Rectangle

        
        Rectangle rect = new Rectangle();
        hbox.setAlignment(Pos.BOTTOM_CENTER);
        
        hbox.setStyle("-fx-border-color: green;");
        rect.setFill(Color.TRANSPARENT);
        
        hbox.setPadding(new Insets(10,10,10,10));
        hbox.setMargin(rect, new Insets(20,30,40,50));
        
        // add result label & checkout button
        
        Label result = new Label("Total: $0.00");
        result.setAlignment(Pos.CENTER);
        Button btAdd = new Button("Checkout");
        hbox.getChildren().addAll(rect, result, btAdd);
        
        
        
        btAdd.setOnAction(e ->{
            Double AppleValue = Double.valueOf(tf1.getText());
            Double AppricotValue = Double.valueOf(tf2.getText());
            Double BananaValue = Double.valueOf(tf3.getText());
            Double CherryValue = Double.valueOf(tf4.getText());
            Double GrapeValue = Double.valueOf(tf5.getText());
            Double LemonValue = Double.valueOf(tf6.getText());
            Double OrangeValue = Double.valueOf(tf7.getText());
            Double PearValue = Double.valueOf(tf8.getText());
            Double StrawberryValue = Double.valueOf(tf9.getText());
            Double WatermelonValue = Double.valueOf(tf10.getText());
            
            
            Double r = (AppleValue * 0.99) + (AppricotValue * 1.49) + (BananaValue * 0.49) + 
                    (CherryValue * 1.99) + (GrapeValue * 0.99)+ (LemonValue * 1.99)+ 
                    (OrangeValue * 0.99)+ (PearValue * 1.49)+ (StrawberryValue * 1.99) + 
                    (WatermelonValue * 0.99);
            result.setText("$ " + r.toString());
            
        });
        
        
        // Window title 
        Scene scene = new Scene(border);
        
        primaryStage.setTitle("Anna's Fresh Market"); 
        primaryStage.setScene(scene);
        primaryStage.setResizable(true);
        primaryStage.show();
        
    }   
}

标签: eclipsejavafxhbox

解决方案


Since you asked about "cleaner coding", I have these suggestions:

  • Don't instantiate variables that you are going to only use once, inline them
  • When you have repeated lines of almost the same code, put it into a method
  • Don't include meaningless comments
  • Use meaningful variable names

I couldn't figure out what rect was for since you created it with no size, but I put the results in an HBox and gave it a border, in case that was what you were going for.

You created ColumnConstraints, but didn't use them.

Just sorting out those issues, cuts your code by nearly 1/2 and makes it a lot easier to follow (I had to change all your images to "flag" since I didn't have your image files):

public class AnnasMarket1 extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }

    public void start(Stage primaryStage) {

        BorderPane border = new BorderPane();
        HBox hbox = new HBox(20);

        GridPane pane = new GridPane();
        border.setCenter(pane);
        border.setBottom(hbox);
        pane.setAlignment(Pos.CENTER);
        pane.setPadding(new Insets(10, 20, 10, 20));
        pane.setHgap(10);
        pane.setVgap(20);
        pane.setStyle("-fx-background-color: #e6ffb3;");

        TextField tfApple = createQuantityTextField();
        TextField tfApricot = createQuantityTextField();
        TextField tfBanana = createQuantityTextField();
        TextField tfCherry = createQuantityTextField();
        TextField tfGrape = createQuantityTextField();
        TextField tfLemon = createQuantityTextField();
        TextField tfOrange = createQuantityTextField();
        TextField tfPear = createQuantityTextField();
        TextField tfStrawberry = createQuantityTextField();
        TextField tfWatermelon = createQuantityTextField();

        addFruit(pane, "/images/flag.png", tfApple, 0, 1, "0.99/lb");
        addFruit(pane, "/images/flag.png", tfApricot, 3, 1, "1.49/lb");
        addFruit(pane, "/images/flag.png", tfBanana, 6, 1, "0.49/lb");
        addFruit(pane, "/images/flag.png", tfCherry, 0, 2, "1.99/lb");
        addFruit(pane, "/images/flag.png", tfGrape, 3, 2, "0.99/lb");
        addFruit(pane, "/images/flag.png", tfLemon, 6, 2, "1.99/lb");
        addFruit(pane, "/images/flag.png", tfOrange, 0, 3, "0.99/lb");
        addFruit(pane, "/images/flag.png", tfPear, 3, 3, "1.49/lb");
        addFruit(pane, "/images/flag.png", tfStrawberry, 6, 3, "1.99/lb");
        addFruit(pane, "/images/flag.png", tfWatermelon, 0, 4, "0.99/lb");

        ColumnConstraints col = new ColumnConstraints();
        col.setPercentWidth(10);
        pane.setPrefSize(700, 350);
        pane.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);


        Label titleLbl = new Label("Anna's Fresh Market");
        border.setTop(titleLbl);
        BorderPane.setAlignment(titleLbl, Pos.CENTER);
        titleLbl.setPadding(new Insets(10));
        titleLbl.setStyle("-fx-font-size: 25px; -fx-text-fill: green;-fx-background-color: #e6ffb3;");
        border.setStyle("-fx-background-color: #e6ffb3;");

        hbox.setAlignment(Pos.BOTTOM_CENTER);

        hbox.setStyle("-fx-border-color: green;");
        hbox.setPadding(new Insets(10, 10, 10, 10));
        Label result = new Label("Total: $0.00");
        result.setAlignment(Pos.CENTER);
        HBox resultBox = new HBox(result);
        resultBox.setFillHeight(false);
        resultBox.setPadding(new Insets(6));
        resultBox.setStyle("-fx-border-color: green;");
        Button btAdd = new Button("Checkout");
        hbox.getChildren().addAll(resultBox, btAdd);


        btAdd.setOnAction(e -> {
            double r =
                    (Double.parseDouble(tfApple.getText()) * 0.99) + (Double.parseDouble(tfApricot.getText()) * 1.49) + (Double.parseDouble(
                            tfBanana.getText()) * 0.49) + (Double.parseDouble(tfCherry.getText()) * 1.99) + (Double.parseDouble(tfGrape.getText()) * 0.99) + (Double
                            .parseDouble(tfLemon.getText()) * 1.99) + (Double.parseDouble(tfOrange.getText()) * 0.99) + (Double.parseDouble(
                            tfPear.getText()) * 1.49) + (Double.parseDouble(tfStrawberry.getText()) * 1.99) + (Double.parseDouble(
                            tfWatermelon.getText()) * 0.99);
            result.setText("Total $" + Double.toString(r));

        });
        primaryStage.setTitle("Anna's Fresh Market");
        primaryStage.setScene(new Scene(border));
        primaryStage.setResizable(true);
        primaryStage.show();

    }

    private void addFruit(GridPane pane, String imageLocation, TextField textField, int baseColumn, int row, String labelText) {
        pane.add(new ImageView(new Image(imageLocation)), baseColumn, row);
        pane.add(new Label(labelText), baseColumn + 1, row);
        pane.add(textField, baseColumn + 2, row);
    }

    private TextField createQuantityTextField() {
        TextField results = new TextField("0");
        results.setMaxWidth(50);
        return results;
    }
}

The biggest issue I see is that you're treating the whole screen like one big monolithic structure. Your GridPane has 30 individual elements in it, but it's actual just 10 smaller structures each with three elements in it. You can avoid a ton of repetition and make the structure much more coherent by creating a custom widget (I used an extension of HBox that I called "FruitBox") to hold the your Image/Label/TextField triplets and then just put those in the pane.

Once you've rethought it from 30 widgets in a GridPane to just 10, you should realize that FlowPane is a better layout container than GridPane. Then you don't need to keep track of rows and columns.

Next, you've got the prices hard-coded as String and Double and mingled up with your layout. I've treated them more like data, and the layout for the FruitBox converts it to a String for the display. FruitBox is the only thing that has a reference to the TextField, and it has a method called getAmount() that will multiply the price times the number in the TextField.

Even though the price/image info is still hard-coded, it's now treated a little more like data now.

Finally, it's easier to see how things go together when you split out all of the setup work for each section of the BorderPane into their own methods. It also makes it easier to get away from the monolithic design when you break it down this way.

If it was me, I'd get rid of all of the in-line styling and create a CSS for the scene and use it.

This is my refactoring into a non-monolithic design. I hope you find it interesting, if not useful:

public class AnnasMarket2 extends Application {
    private ObservableList<FruitBox> fruitBoxes = FXCollections.observableArrayList();

    public static void main(String[] args) {
        Application.launch(args);
    }

    public void start(Stage primaryStage) {
        BorderPane border = new BorderPane();
        border.setTop(setUpTitle());
        border.setBottom(setUpButtonHBox());

        FlowPane flowPane = createFlowPane();
        border.setCenter(flowPane);
        createFruitBoxes();
        flowPane.getChildren().addAll(fruitBoxes);
        border.setStyle("-fx-background-color: #e6ffb3;");
        primaryStage.setTitle("Anna's Fresh Market");
        primaryStage.setScene(new Scene(border));
        primaryStage.setResizable(true);
        primaryStage.show();

    }


    @NotNull
    private FlowPane createFlowPane() {
        FlowPane pane = new FlowPane();
        pane.setAlignment(Pos.CENTER);
        pane.setPadding(new Insets(10, 20, 10, 20));
        pane.setStyle("-fx-background-color: #e6ffb3;");
        return pane;
    }

    private Node setUpTitle() {
        Label results = new Label("Anna's Fresh Market");
        BorderPane.setAlignment(results, Pos.CENTER);
        results.setPadding(new Insets(10));
        results.setStyle("-fx-font-size: 25px; -fx-text-fill: green;-fx-background-color: #e6ffb3;");
        return results;
    }

    private Node setUpButtonHBox() {
        HBox hBox = new HBox(20);
        hBox.setAlignment(Pos.BOTTOM_CENTER);

        hBox.setStyle("-fx-border-color: green;");
        hBox.setPadding(new Insets(10, 10, 10, 10));
        Label result = new Label("Total: $0.00");
        result.setAlignment(Pos.CENTER);
        HBox resultBox = new HBox(result);
        resultBox.setFillHeight(false);
        resultBox.setPadding(new Insets(6));
        resultBox.setStyle("-fx-border-color: green;");
        Button btAdd = new Button("Checkout");
        hBox.getChildren().addAll(resultBox, btAdd);
        btAdd.setOnAction(e -> {
            double r = fruitBoxes.stream().map(FruitBox::getAmount).reduce(0d, (a, b) -> a + b);
            result.setText("Total $" + Double.toString(r));
        });
        return hBox;
    }

    private void createFruitBoxes() {
        fruitBoxes.add(new FruitBox("/images/flag.png", 0.99));
        fruitBoxes.add(new FruitBox("/images/flag.png", 0.99));
        fruitBoxes.add(new FruitBox("/images/flag.png", 1.49));
        fruitBoxes.add(new FruitBox("/images/flag.png", 0.49));
        fruitBoxes.add(new FruitBox("/images/flag.png", 1.99));
        fruitBoxes.add(new FruitBox("/images/flag.png", 0.99));
        fruitBoxes.add(new FruitBox("/images/flag.png", 1.99));
        fruitBoxes.add(new FruitBox("/images/flag.png", 0.99));
        fruitBoxes.add(new FruitBox("/images/flag.png", 1.49));
        fruitBoxes.add(new FruitBox("/images/flag.png", 1.99));
        fruitBoxes.add(new FruitBox("/images/flag.png", 0.99));
    }

    class FruitBox extends HBox {

        private TextField textField = new TextField("0");
        private double price;

        public FruitBox(String imageLocation, double price) {
            this.price = price;
            textField.setMaxWidth(50);

            ImageView imageView = new ImageView(new Image(imageLocation));
            imageView.setFitHeight(70);
            imageView.setFitWidth(70);
            setAlignment(Pos.CENTER_LEFT);
            setSpacing(6);
            setPadding(new Insets(10));
            getChildren().addAll(imageView, new Text("$" + price + "/lb"), textField);
        }

        public double getAmount() {
            return price * Double.parseDouble(textField.getText());
        }

    }
}

推荐阅读