目录
目标
舞台Stage设置
整体布局与工具栏
主体框架设置
搜索区域
商品显示区域
目标
工具栏的使用
更多布局面板的使用
自定义复杂布局
完成商城的首页数据展示功能,效果图如下
舞台Stage设置
给舞台设置上图标
primaryStage.getIcons().add(new Image("file:D:\\icons\\index\\slogan.png"));
完整代码
primaryStage.setTitle("天天商城"); primaryStage.setResizable(false); primaryStage.setScene(new Scene(borderPane, 500, 350)); primaryStage.getIcons().add(new Image("file:D:\\icons\\index\\slogan.png")); primaryStage.show();
整体布局与工具栏
主体框架分析如上,我们可以采用 BorderPane
//主页设置
BorderPane borderPane = new BorderPane();
对于工具栏,FX也提供了对应的控件 ToolBar 工具栏 , MenuButton 菜单按钮
工具栏中可以直接放入组件 也就是说 Button , ChoiseBox 等控件都可以直接放
这里我们选择使用 菜单按钮 是因为该按钮可以绑定菜单项 从而实现下拉功能
//菜单栏
MenuButton b1 = new MenuButton("商品管理");
//菜单 b1 的菜单项
MenuItem t1 = new MenuItem("商品新增");
MenuItem t2 = new MenuItem("商品删除");
MenuButton b2 = new MenuButton("类别管理");
//菜单 b2 的菜单项
MenuItem t3 = new MenuItem("类别新增");
MenuItem t4 = new MenuItem("类别删除");
//创建工具栏 并对菜单进行绑定
ToolBar barCtl = new ToolBar(b1, b2);
将菜单与菜单项进行绑定
b1.getItems().add(t1);
b1.getItems().add(t2);
b2.getItems().add(t3);
b2.getItems().add(t4);
将工具栏放入布局的上方
borderPane.setTop(barCtl);
主体框架设置
观察可以发现主体部分也可以采取边框布局设置,不过在此处,我们选择换一个布局来实现它 SplitPane 分割面板
与边框布局不同,这个布局的方向只能是水平的或者是垂直的,可以放入多个控件或者布局,会为每个控件生成一个分割条,我们可以 通过拉动他来改变控件或者布局占据的空间大小
大致情况如下,此处为水平的分割面板
布局代码如下
//分割面板
SplitPane splitPane = new SplitPane();
我们使用分割面板将页面分为上下两块
上: 商品搜索控件,且全部水平排列,可以使用 HBox
下:商品数据显示区域,因为商品数据比较多,页面存放不下这么多数据,需要该容器为滚动面板 ScrollPane ,在内容溢出的 情况下会自动出现滚动条。其内部的商品条目都是垂直排列,可以使用 VBOX
布局代码
VBox vBox = new VBox();
ScrollPane scrollPane = new ScrollPane(vBox);
主体部分代码
//分割面板
SplitPane splitPane = new SplitPane();
//搜索部分
HBox hBox = new HBox();
//内容显示部分
VBox vBox = new VBox();
ScrollPane scrollPane = new ScrollPane(vBox);
主框架完整代码
//工具栏
borderPane.setTop(barCtl);
//分割面板
borderPane.setCenter(splitPane);
//设置搜索区域的间隙为5
hBox.setSpacing(5);
//设置搜索区域的整体控件居中
hBox.setAlignment(Pos.CENTER);
//分割面板设置
splitPane.getItems().addAll(hBox, scrollPane);
//此处是设置分割线的为值 (第几根分割线,占内容大小比例)
splitPane.setDividerPosition(0, 0.1);
//分割面板默认是水平分排列 需要改为垂直排列 splitPane.setOrientation(Orientation.VERTICAL);
搜索区域
Label l1 = new Label("🔍");
ChoiceBox cateCtl = new ChoiceBox();
ChoiceBoxorderCtl = new ChoiceBox();
TextField nameCtl = new TextField();
第一个下拉框存放的是商品分类,所以我们绑定的类型是 Category ,并需要将数据库数据查询并进行绑定
注意:数据库中是没有 全部 这个分类数据的,该数据显示在这里是为了方便搜索,同时该数据是由手动添加的
//查询数据库分类数据
List cateList = categoryDao.list();
//手动添加分类,并设置id为-1,到时候只要判断id是否为-1就能知道用户是否选了全部 cateList.add(0, new Category(-1, "全部"));
//数据绑定
cateCtl.getItems().addAll(cateList);
//必须配置转换器 否则数据无法识别
cateCtl.setConverter(new StringConverter<>() {
@Override
public String toString(Category category) {
return category.getName();
}
@Override
public Category fromString(String s) {
return null; }
});
//设置默认选中第0个选项
cateCtl.setValue(cateCtl.getItems().get(0));
对于排序下拉框而言,我们可以直接绑定 String 的值,但是取值的时候需要依次做判断,比较繁琐,我们九可以选择对象绑定的写法, 为该选项生成对应的对象类型,取值的操作就会简化很多
public class Option {
//这个值用于显示
private String property;
//这个值放的是 列名+排序规则(升序,降序)
//如果做查询 只要拿到该值然后做sql拼接就行了
private String value;
}
进行数据绑定该数据由我们手动定义,数据库中没有对应数据
orderCtl.getItems().addAll(
new Option("全部", ""),
new Option("时间升序", " create_time asc"),
new Option("时间降序", " create_time desc"),
new Option("价格升序", " price asc"),
new Option("价格降序", " price desc")
);
orderCtl.setConverter(new StringConverter<>() {
@Override
public String toString(Option option) {
return option.getProperty();
}
@Override
public Option fromString(String s) {
return null;
}
});
orderCtl.setValue(orderCtl.getItems().get(0));
商品显示区域
该区域的主要难点是 自定义布局:
多种布局嵌套 整个大区域是一个滚动面板,在滚动面板中存在一个 VBox 垂直面板,这个我们在上面分析了 那么在这里,还需要完成的则是这一块的布局:
对于每个商品的显示,我选择使用了 TitledPane 标题面板 ,这个面板的特点:
1:面板具备对应的标题,可以用来放商品的名字
2:具备折叠功能,可以让页面看上去不是那么拥挤,点开折叠则可以查看商品内容与操作 基本使用
//定义标题面板
TitledPane titlePane = new TitledPane();
//设置面板标题
titlePane.setText("xx");
//设置面板是否展开
titlePane.setExpanded(false);
//设置面板是否可以折叠
titlePane.setCollapsible(true);
对于每个标题面板,其中的商品内容也是采用了多个控件与布局衔接的方式做出来的
大致思路如下:
构建标题面板 TitledPane ,面板中放入一个边框布局 BorderPane
边框布局的左边放一个图片控件 ImageView ,右边放一个垂直布局 VBox
向 VBox 布局中依次放入多个标签 Label ,商品价格,商品描述,商品创建时间
向 VBox 布局放入 HBox 布局,并向 HBox 布局中放入两个按钮
完整代码
//生成商品展示内容
//获得数据库商品数据
goodsDao.list(name, sql).forEach(g -> {
//标题面板设置
TitledPane titlePane = new TitledPane();
titlePane.setText(g.getName());
titlePane.setExpanded(false);
titlePane.setCollapsible(true);
//此处需要设置为当前Stage的宽度稍小一点
//不然占不满一行
titlePane.setPrefWidth(500 - 20);
BorderPane borderPane = new BorderPane();
//设置标题面板的内容
titlePane.setContent(borderPane);
//生成图片控件
//根据商品的cover属性设置图片
//并设置空间大小
Image image = new Image("file:" + g.getCover());
ImageView imageView = new ImageView(image);
imageView.setFitWidth(80);
imageView.setFitHeight(80);
borderPane.setLeft(imageView);
//标签设置
Label l1 = new Label("商品价格: " + g.getPrice().toString());
Label l2 = new Label("商品描述: " + g.getDescription().toString());
Label l3 = new Label("商品创建时间: " + g.getCreateTime().toString());
//HBox区域
Button buy = new Button("购买");
Button car = new Button("添加购物车");
HBox h1 = new HBox(buy, car); h1.setSpacing(3);
VBox v1 = new VBox(l1, l2, l3, h1); v1.setSpacing(5);
borderPane.setCenter(v1);
//【这个地方注意了 是使用getChildren()来获得控件集合】 vBox.getChildren().add(titlePane); });