diff --git a/src/main/java/com/zhangmeng/online/exam/ui/OnlineExamApplication.java b/src/main/java/com/zhangmeng/online/exam/ui/OnlineExamApplication.java index 893951d..ac69e82 100644 --- a/src/main/java/com/zhangmeng/online/exam/ui/OnlineExamApplication.java +++ b/src/main/java/com/zhangmeng/online/exam/ui/OnlineExamApplication.java @@ -1,9 +1,16 @@ package com.zhangmeng.online.exam.ui; import com.zhangmeng.online.exam.ui.admin.LoginPage; import javafx.application.Application; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.control.Accordion; +import javafx.scene.control.Button; +import javafx.scene.control.TitledPane; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.HBox; import javafx.stage.Stage; import java.io.IOException; @@ -19,6 +26,8 @@ public class OnlineExamApplication extends Application { stage.setTitle("在线考试系统"); stage.show(); + + } diff --git a/src/main/java/com/zhangmeng/online/exam/ui/admin/IndexPage.java b/src/main/java/com/zhangmeng/online/exam/ui/admin/IndexPage.java index 033d6e8..227a148 100644 --- a/src/main/java/com/zhangmeng/online/exam/ui/admin/IndexPage.java +++ b/src/main/java/com/zhangmeng/online/exam/ui/admin/IndexPage.java @@ -9,6 +9,9 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; +import java.util.ArrayList; +import java.util.List; + /** * @author zm * @date 2025/3/5 9:36 @@ -19,7 +22,18 @@ public class IndexPage extends BorderPane { private SideMenu sideMenu = null; public IndexPage() { - sideMenu = new SideMenu(); // 导航栏容器 + + SideMenu.SideMenuItem item1 = new SideMenu.SideMenuItem("试卷管理", new SideMenu.SideMenuData("试卷管理", "/paper/list")); + SideMenu.SideMenuItem item2 = new SideMenu.SideMenuItem("题库管理", new SideMenu.SideMenuData("题库管理", "/question/list")); + SideMenu.SideMenuItem item3 = new SideMenu.SideMenuItem("用户管理", new SideMenu.SideMenuData("用户管理", "/user/list")); + SideMenu.SideMenuItem item4 = new SideMenu.SideMenuItem("系统设置", new SideMenu.SideMenuData("系统设置", "/system/setting")); + List menuItems = new ArrayList<>(); + menuItems.add(item1); + menuItems.add(item2); + menuItems.add(item3); + menuItems.add(item4); + + sideMenu = new SideMenu(menuItems); // 导航栏容器 StackPane contentArea = new StackPane(); // 右侧内容区 contentArea.setStyle("-fx-background-color: #3ce53c;"); diff --git a/src/main/java/com/zhangmeng/online/exam/ui/components/DynamicTableComponent.java b/src/main/java/com/zhangmeng/online/exam/ui/components/DynamicTableComponent.java new file mode 100644 index 0000000..c536202 --- /dev/null +++ b/src/main/java/com/zhangmeng/online/exam/ui/components/DynamicTableComponent.java @@ -0,0 +1,76 @@ +package com.zhangmeng.online.exam.ui.components; + +import javafx.beans.property.SimpleStringProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.TextFieldTableCell; +import javafx.scene.layout.VBox; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 动态表格 + * + * @author zm + * @date 2025/3/5 15:17 + * @version: 1.0 + */ +public class DynamicTableComponent extends VBox { + private final ObservableList data = FXCollections.observableArrayList(); + + // 数据模型定义(使用JavaFX属性)‌:ml-citation{ref="1,3" data="citationList"} + public static class DynamicDataModel { + private final Map properties = new HashMap<>(); + + public DynamicDataModel(Map data) { + data.forEach((k, v) -> + properties.put(k, new SimpleStringProperty(v)) + ); + } + + public SimpleStringProperty getProperty(String key) { + return properties.get(key); + } + } + + public DynamicTableComponent() { + super(); + TableView tableView = new TableView<>(); + + // 动态生成列(示例字段)‌:ml-citation{ref="3,4" data="citationList"} + List columns = Arrays.asList("姓名", "年龄", "城市"); + columns.forEach(col -> { + TableColumn column = + new TableColumn<>(col); + + // 数据绑定‌:ml-citation{ref="1,3" data="citationList"} + column.setCellValueFactory(param -> + param.getValue().getProperty(col) + ); + + // 启用单元格编辑‌:ml-citation{ref="4,5" data="citationList"} + column.setCellFactory(TextFieldTableCell.forTableColumn()); + column.setOnEditCommit(event -> { + DynamicDataModel row = event.getRowValue(); + row.getProperty(col).set(event.getNewValue()); + }); + + tableView.getColumns().add(column); + }); + + // 填充示例数据‌:ml-citation{ref="2,3" data="citationList"} + data.add(new DynamicDataModel(Map.of( + "姓名", "张三", + "年龄", "28", + "城市", "北京" + ))); + tableView.setItems(data); + this.getChildren().addAll(tableView); + } + +} diff --git a/src/main/java/com/zhangmeng/online/exam/ui/layouts/SideMenu.java b/src/main/java/com/zhangmeng/online/exam/ui/layouts/SideMenu.java index 502d951..acf62b9 100644 --- a/src/main/java/com/zhangmeng/online/exam/ui/layouts/SideMenu.java +++ b/src/main/java/com/zhangmeng/online/exam/ui/layouts/SideMenu.java @@ -1,8 +1,21 @@ package com.zhangmeng.online.exam.ui.layouts; +import com.zhangmeng.online.exam.ui.admin.IndexPage; +import com.zhangmeng.online.exam.ui.components.DynamicTableComponent; +import com.zhangmeng.online.exam.ui.components.ShortAnswerComponent; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.geometry.Insets; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Accordion; import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.TitledPane; +import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; +import java.util.List; /** @@ -12,12 +25,129 @@ import javafx.scene.layout.VBox; */ public class SideMenu extends VBox { + public static class SideMenuData{ + private String text; + private String url; - public SideMenu() { + public SideMenuData(String text, String url) { + this.text = text; + this.url = url; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + } + + public static class SideMenuItem{ + + private String text; + private SideMenuData sideMenuData; + + public SideMenuItem(String text, SideMenuData sideMenuData) { + this.text = text; + this.sideMenuData = sideMenuData; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public SideMenuData getSideMenuData() { + return sideMenuData; + } + + public void setSideMenuData(SideMenuData sideMenuData) { + this.sideMenuData = sideMenuData; + } + } + + + public SideMenu(List menuItems) { this.setSpacing(10); this.setPrefWidth(200); - this.setStyle("-fx-background-color: #2c3e50;"); - } +// this.setStyle("-fx-background-color: #2c3e50;"); + Accordion accordion = new Accordion(); + + for (SideMenuItem item : menuItems) { + + TitledPane tp = new TitledPane(); + tp.setText(item.getText()); + + HBox hbox = new HBox(); + hbox.setPadding(javafx.geometry.Insets.EMPTY); + + hbox.setSpacing(10); + hbox.setAlignment(javafx.geometry.Pos.CENTER); + Label label = new Label(item.getSideMenuData().getText()); + hbox.getChildren().add(label); + tp.setContent(hbox); + + hbox.hoverProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { + if (newValue){ + hbox.setStyle("-fx-background-color: #b3f0ee;"); + }else { + hbox.setStyle("-fx-background-color: white;"); + } + } + }); + + hbox.setOnMouseClicked(event -> { + System.out.println("hbox.setOnMouseClicked====>" + item.getSideMenuData().getUrl()); +// Parent parent = hbox.getParent().getParent().getParent().getParent(); +// System.out.println(parent.getClass().getName()); + + Scene scene = hbox.getScene(); + IndexPage root = (IndexPage)scene.getRoot(); + + + DynamicTableComponent shortAnswerComponent = new DynamicTableComponent(); + shortAnswerComponent.setPadding(new Insets(15)); + root.setCenter(shortAnswerComponent); + }); + + tp.expandedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { + System.out.println("tp.expandedProperty().addListener====>" + newValue); + } + }); + + accordion.getPanes().add(tp); + } + + this.getChildren().add(accordion); + + accordion.expandedPaneProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, TitledPane oldValue, TitledPane newValue) { + if (newValue == null){ + System.out.println(oldValue.getText()+ "=====>折叠"); + return; + } + System.out.println(newValue.getText()+ "=====>展开"); + } + }); + + } }