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,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,2);
        
        ImageView grape_iv = new ImageView(grape_img);
        pane.add(grape_iv,2);
        
        ImageView lemmon_iv = new ImageView(lemmon_img);
        pane.add(lemmon_iv,2);
        
        ImageView orange_iv = new ImageView(orange_img);
        pane.add(orange_iv,3);
        
        ImageView pear_iv = new ImageView(pear_img);
        pane.add(pear_iv,3);
        
        ImageView strawBerry_iv = new ImageView(strawBerry_img);
        pane.add(strawBerry_iv,3);
        
        ImageView watermelon_iv = new ImageView(watermelon_img);
        pane.add(watermelon_iv,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"),2);
        pane.add(tf4,2);
        pane.add(new Label("0.99/lb"),2);
        pane.add(tf5,2);
        pane.add(new Label("1.99/lb"),2);
        pane.add(tf6,3);
        pane.add(tf7,3);
        pane.add(new Label("1.49/lb"),3);
        pane.add(tf8,3);
        pane.add(new Label("1.99/lb"),3);
        pane.add(tf9,3);
        pane.add(new Label("0.99/lb"),4);
        pane.add(tf10,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));
        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();
        
    }   
}

解决方法

既然你问的是“更干净的编码”,我有以下建议:

  • 不要实例化您将只使用一次的变量,而是将它们内联
  • 当你有几乎相同代码的重复行时,把它放到一个方法中
  • 不要包含无意义的评论
  • 使用有意义的变量名

我无法弄清楚 rect 的用途,因为您创建它时没有大小,但我将 results 放在 HBox 中并为其设置了边框,以防万一去。

您创建了 ColumnConstraint,但没有使用它们。

只需解决这些问题,您的代码就减少了近 1/2,并且更容易理解(因为我没有您的图像文件,所以我不得不将您的所有图像更改为“标记”):>

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,1,"0.99/lb");
        addFruit(pane,tfApricot,3,"1.49/lb");
        addFruit(pane,tfBanana,6,"0.49/lb");
        addFruit(pane,tfCherry,2,"1.99/lb");
        addFruit(pane,tfGrape,tfLemon,tfOrange,tfPear,tfStrawberry,tfWatermelon,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));
        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;
    }
}

我看到的最大问题是您将整个屏幕视为一个巨大的整体结构。您的 GridPane 中有 30 个单独的元素,但实际上只有 10 个较小的结构,每个结构中包含三个元素。您可以通过创建自定义小部件(我使用了一个名为“FruitBox”的 HBox 扩展)来保存您的 Image/Label/TextField 三元组,然后将它们放在窗格。

一旦您将 GridPane 中的 30 个小部件重新考虑到只有 10 个,您应该意识到 FlowPane 是比 GridPane 更好的布局容器。这样您就不需要跟踪行和列。

接下来,您将价格硬编码为 String 和 Double 并与您的布局混合在一起。我把它们更像是数据,FruitBox 的布局将它转换为用于显示的字符串。 FruitBox 是唯一引用 TextField 的东西,它有一个名为 getAmount() 的方法,可以将价格乘以 TextField 中的数字。

尽管价格/图片信息仍然是硬编码的,但现在它更像是数据。

最后,当您将 BorderPane 的每个部分的所有设置工作拆分为它们自己的方法时,更容易看到事情是如何进行的。当您以这种方式分解时,它还可以更轻松地摆脱整体设计。

如果是我,我会去掉所有的内嵌样式,为场景创建一个 CSS 并使用它。

这是我重构为非整体设计。我希望你觉得它很有趣,如果没有用的话:

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));
        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));
        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",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));
    }

    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());
        }

    }
}