大作业-简易购物车
简易购物车
1. 效果展示
均为gif,加载过程请耐心等待
2. 细节介绍
源码地址:https://github.com/dongmingchao/JavaPTA/blob/master/src/six/ShoppingCartDemo2.java
1. 使用JavaFX,JavaFX的特性就是fxml,从fxml中读取布局
使用lookup方法
先读入资源
VBox buyGood = FXMLLoader.load(getClass().getResource("good.fxml"));
然后使用lookup,参数和web开发时候的jQuery选择器类似,据说支持类选择器,但是支持好像不完整,所以这里仅仅使用id选择器
TableView<cartItem> goodList = (TableView<cartItem>) buyGood.lookup("#goodList");
要在fxml中如下定义fx:id
2. 使用TableView展示商品
为什么使用TableView:这里“数量”一项包含两个按钮,由于ListView不能在每个项中增加按钮或者其他Object,但是TableView却可以,所以才使用TableView
1. 新建TableView,然后使用setItems
方法设置让TableView显示的数据
这里数据要求封装成ObservableList
对象,我们可以如下生成一个ObservableList
对象
ObservableList<cartItem> goodItems = FXCollections.observableArrayList();
goodList.setItems(goodItems);
但是注意我们并没有指出哪一列使用哪个属性,所以需要指明列显示数据对应的属性名
goodList.getColumns().get(0).setCellValueFactory(new PropertyValueFactory<>("name"));
goodList.getColumns().get(1).setCellValueFactory(new PropertyValueFactory<>("singlePrice"));
goodList.getColumns().get(2).setCellValueFactory(new PropertyValueFactory<>("numberTF"));
goodItems中放的是cartItem
对象,我们来看cartItem
对象的属性是如何建立的
private StringProperty name = new SimpleStringProperty();
private IntegerProperty number = new SimpleIntegerProperty();
private DoubleProperty price = new SimpleDoubleProperty();
private DoubleProperty singlePrice = new SimpleDoubleProperty();
private ObjectProperty<VBox> numberTF;
private Label theNumber;
private Button subNumber;
注意这里的变量名,和上一段代码中PropertyValueFactory
函数的构建参数是一样的,这一点务必牢记,这是一种简单的构造Table单元格的方法。这样就可以在goodItems
中调用add方法添加cartItem
对象,同时在第一列显示name
属性,在第二列显示singlePrice
属性,在第三列显示numberTF
属性
⚠️所有要展示的属性(例如上面的name,singlePrice,numberTF)都需要生成getter和setter,这是内部建立TableCell的必需方法
2. 构建含有Button的数量属性
我们注意到上面的代码中有个叫做numberTF的ObjectProperty
,所以就是在初始化的时候给这个属性一个pane值来放Button,我使用的是VBox这个pane类
addNumber = new Button("+");
subNumber = new Button("-");
theNumber = new Label(number.toString());
numberTF = new SimpleObjectProperty<>(new VBox(addNumber,theNumber,subNumber));
在Button点击的时候要改变变量number
的值,LabeltheNumber
显示的值,同时要根据number
和singlePrice
的值计算price的值,所以我直接写进一个setNumber里,从而实现数据动态绑定。
⚠️使用BigDecimal计算,避免出现3x1.2=3.599999的情况
public void setNumber(int number) {
this.number.set(number);
if (theNumber!=null) theNumber.setText(String.valueOf(number));
this.setPrice(BigDecimal.valueOf(singlePrice.get()).multiply(BigDecimal.valueOf(number)).doubleValue());
}
和Button点击绑定的函数我一起写进了构造器,根据我的设计,在购物车中的cartItem
在数量变为0的时候会自动被删除,而在商品列表的cartItem
数量最低可以为0,再点击的时候就会无效,显然这个处理点击时候的传入数字的操作是不一样的,所以我将它抽象出来。下面附带我的构造函数。
abstract void calcButton(int number);
public cartItem(String name, Integer number, double singlePrice) {
this.setName(name);
this.setSinglePrice(singlePrice);
this.setNumber(number);
addNumber = new Button("+");
subNumber = new Button("-");
theNumber = new Label(number.toString());
theNumber.setStyle("-fx-font-size: 20px");//fxcss设置字体大小为20px
numberTF = new SimpleObjectProperty<>(new VBox(addNumber,theNumber,subNumber));
subNumber.setOnAction(event -> calcButton(this.getNumber() - 1));
addNumber.setOnAction(event -> calcButton(this.getNumber() + 1));
}
这里附带说一种利用fxml设置触发方法的方式:在fxml中使用onAction="#FunctionName"
方法,编译时会根据fx:controller
指向的类中寻找方法并绑定。
例如我在fxml中最外层父容器的属性如下:
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="557.0" prefWidth="330.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="six.Controller">
此时被绑定的类就是six.Controller,在此类中实现backTo方法,然后就可以如下使用
<Button fx:id="watch" mnemonicParsing="false" text="我选择观望" onAction="#backTo"/>
将backTo方法绑定到变量名是watch的Button上,对于Button来说Action就是在被点击的时候触发,对于TextField就是编辑时敲击回车触发。
3. 关于Controller
可能有人就会问了,fxml取Controller中的方法学会了,但是如果在代码中取对应的Controller呢?在JavaFX中有个对应的FXMLLoader
类,创建该类的对象后,可以使用该对象取到fxml中的控件和Controller。具体代码如下
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("cart.fxml"));
VBox root = loader.load();
controller = loader.getController();
先码到这里,以后慢慢补,个人网站搭建中,到时候会放到那里,也会放一些其他的东西。
本次就算是抛砖引玉,将我踩过的坑列出一些,希望对你有所帮助,代码仓促,码风dirty,轻喷