问题描述
我有当前的课堂作业,但无法设置矩形的边距。它是一个水果列表,应该计算用户选择的所需水果的总数。 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());
}
}
}