JavaFX课程作业HBox.setMargin静态调用错误及功能优化求助
解决方案
问题1:HBox.setMargin静态访问错误修复
该报错是因为setMargin是HBox类的静态方法,不能通过HBox的实例对象调用,修改方式如下:
将原代码中的
hbox.setMargin(rect, new Insets(20,30,40,50));
替换为
HBox.setMargin(rect, new Insets(20,30,40,50));
即可解决报错。
问题2:空输入/非法输入异常处理
新增输入转换工具方法,空输入、非数字输入统一返回0,避免抛出NumberFormatException,同时补充总价小数格式化逻辑,保留两位小数符合金额显示规范:
private double parseInput(TextField tf) { try { String text = tf.getText().trim(); return text.isEmpty() ? 0 : Double.parseDouble(text); } catch (NumberFormatException e) { return 0; } }
在结算点击事件中调用该方法读取每个输入框的值即可。
问题3:代码精简优化方案
原代码存在大量重复的控件创建逻辑,我们可以把水果的元数据(图片路径、单价、网格位置)封装为结构,循环批量创建控件,大幅减少重复代码,同时提升可维护性,后续新增水果仅需要补充元数据即可。
优化后的完整代码
import javafx.application.Application; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; import java.text.DecimalFormat; // 水果元数据类,存储每个水果的基础属性 class Fruit { String imgPath; double price; int col; int row; public Fruit(String imgPath, double price, int col, int row) { this.imgPath = imgPath; this.price = price; this.col = col; this.row = row; } } public class Grid_Layout extends Application { private static final DecimalFormat PRICE_FORMAT = new DecimalFormat("0.00"); public static void main(String[] args) { Application.launch(args); } // 输入转换工具方法,处理空/非法输入 private double parseInput(TextField tf) { try { String text = tf.getText().trim(); return text.isEmpty() ? 0 : Double.parseDouble(text); } catch (NumberFormatException e) { return 0; } } public void start(Stage primaryStage) { BorderPane border = new BorderPane(); HBox hbox = new HBox(20); GridPane pane = new GridPane(); border.setCenter(pane); border.setBottom(hbox); // GridPane基础配置 pane.setAlignment(Pos.CENTER); pane.setPadding(new Insets(10,20,10,20)); pane.setHgap(10); pane.setVgap(20); pane.setStyle("-fx-background-color: #e6ffb3;"); // 批量定义所有水果的元数据,后续新增水果只需要在这里加条目即可 Fruit[] fruits = new Fruit[]{ new Fruit("File:images/apple.png", 0.99, 0, 1), new Fruit("File:images/apricot.png", 1.49, 3, 1), new Fruit("File:images/banana.png", 0.49, 6, 1), new Fruit("File:images/cherry.png", 1.99, 0, 2), new Fruit("File:images/grape.png", 0.99, 3, 2), new Fruit("File:images/lemmon.png", 1.99, 6, 2), new Fruit("File:images/orange.png", 0.99, 0, 3), new Fruit("File:images/pear.png", 1.49, 3, 3), new Fruit("File:images/strawberry.png", 1.99, 6, 3), new Fruit("File:images/watermelon.png", 0.99, 0, 4) }; // 存储每个水果对应的输入框,用于后续结算读取数值 TextField[] inputFields = new TextField[fruits.length]; // 循环创建所有水果对应的图片、价格标签、输入框 for (int i = 0; i < fruits.length; i++) { Fruit fruit = fruits[i]; // 创建图片控件 ImageView iv = new ImageView(new Image(fruit.imgPath)); pane.add(iv, fruit.col, fruit.row); // 创建价格标签 pane.add(new Label(fruit.price + "/lb"), fruit.col + 1, fruit.row); // 创建输入框 TextField tf = new TextField(); tf.setMaxWidth(50); inputFields[i] = tf; pane.add(tf, fruit.col + 2, fruit.row); } // 窗口尺寸配置 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配置 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)); 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 total = 0; for (int i = 0; i < fruits.length; i++) { total += parseInput(inputFields[i]) * fruits[i].price; } result.setText("Total: $" + PRICE_FORMAT.format(total)); }); // 窗口渲染 Scene scene = new Scene(border); primaryStage.setTitle("Anna's Fresh Market"); primaryStage.setScene(scene); primaryStage.setResizable(true); primaryStage.show(); } }
内容的提问来源于stack exchange,提问作者MOJ
相关产品推荐
相关产品推荐

