javaFX自定义标题栏(含自定义表单tableView)

发布于:2025-03-04 ⋅ 阅读:(9) ⋅ 点赞:(0)

基于:openjfx 17.0.2    openJDK 17.0.1    idea    win10  scene builder 2.0

使用fxml制作ui

必须定义AnchorPane,他的作用就是让嵌入其中的元件固定在此(相对上级元素的)位置。AnchorPane此时在BorderPane的Top位置,用于自定义标题栏。

关键点:Hbox右边距设置为0,但是不能点击左边据设置框!如图:

表单tableView有个关键选项,用来自动填充满,均匀分布列:  

完整代码 

fxml部分

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.demo4.HelloController">
   <top>
      <AnchorPane prefHeight="36.0" prefWidth="200.0" BorderPane.alignment="CENTER">
         <children>
            <Label prefHeight="36.0" prefWidth="60.0" text="自定义标题栏" AnchorPane.leftAnchor="0.0" />
            <HBox prefHeight="36.0" prefWidth="180.0" AnchorPane.rightAnchor="0.0">
               <children>
                  <Button fx:id="windowMinButton" mnemonicParsing="false" onMouseClicked="#windowMin" prefWidth="60.0" text="min" />
                  <Button fx:id="windowMaxButton" mnemonicParsing="false" onMouseClicked="#windowMax" prefWidth="60.0" text="max" />
                  <Button fx:id="windowCloseButton" mnemonicParsing="false" onMouseClicked="#windowClose" prefWidth="60.0" text="close" />
               </children>
            </HBox>
         </children>
      </AnchorPane>
   </top>
   <center>
      <TableView fx:id="tableView" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
        <columns>
          <TableColumn fx:id="name" prefWidth="75.0" text="name" />
          <TableColumn fx:id="age" prefWidth="75.0" text="age" />
            <TableColumn fx:id="button" prefWidth="75.0" text="button" />
        </columns>
         <columnResizePolicy>
            <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
         </columnResizePolicy>
      </TableView>
   </center>
   <bottom>
      <Button fx:id="addTableView" mnemonicParsing="false" onMouseClicked="#addTableView" text="addTableView" BorderPane.alignment="CENTER" />
   </bottom>
</BorderPane>

控制器部分

package com.example.demo4;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.geometry.Rectangle2D;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.stage.Screen;
import javafx.stage.Stage;

public class HelloController {

    @FXML
    private TableColumn<Person, Void> button;

    @FXML
    private Button windowMinButton;

    @FXML
    private Button windowMaxButton;

    @FXML
    private TableColumn<Person, String> name;

    @FXML
    private TableView<Person> tableView;

    @FXML
    private Button windowCloseButton;

    @FXML
    private TableColumn<Person, Number> age;

    @FXML
    void windowMin(MouseEvent event) {
        Stage stage = (Stage) windowMinButton.getScene().getWindow();
        stage.setIconified(true);
    }
    // 最大化/还原窗口(注意:这里没有直接的“最大化”方法,需要手动管理状态)
    private boolean isMaximized = false; // 用于跟踪窗口是否最大化
    @FXML
    void windowMax(MouseEvent event) {
        Stage stage = (Stage) windowMaxButton.getScene().getWindow();
        Screen screen = Screen.getPrimary();
        Rectangle2D bounds = screen.getVisualBounds();
        if (isMaximized) {
            // 还原窗口到之前的大小,并移动到屏幕中心
            double width = 600; // 假设之前的宽度是600
            double height = 400; // 假设之前的高度是400
            stage.setWidth(width); 
            stage.setHeight(height); 
            stage.setX((bounds.getWidth() - width) / 2);
            stage.setY((bounds.getHeight() - height) / 2);
            isMaximized = false;
        } else {
            // 记录当前大小
            double x = stage.getX();
            double y = stage.getY();
            double width = stage.getWidth();
            double height = stage.getHeight();

            // 最大化窗口到屏幕大小
            Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
            stage.setX(screenBounds.getMinX());
            stage.setY(screenBounds.getMinY());
            stage.setWidth(screenBounds.getWidth());
            stage.setHeight(screenBounds.getHeight());

            // 存储最大化状态
            isMaximized = true;
        }
    }

    @FXML
    void windowClose(MouseEvent event) {
        Stage stage = (Stage) windowCloseButton.getScene().getWindow();
        stage.close();
    }

    public void addTableView(MouseEvent mouseEvent) {
        // 设置列的单元格值工厂,其中的id以及name是Person类中的字段名。
        name.setCellValueFactory(new PropertyValueFactory<>("name"));
        age.setCellValueFactory(new PropertyValueFactory<>("age"));

        // 自定义单元格工厂
        button.setCellFactory(param -> {
            TableCell<Person, Void> cell = new TableCell<>() {
                private final Button button = new Button("Delete");

                @Override
                public void updateItem(Void item, boolean empty) {
                    super.updateItem(item, empty);
                    if (empty) {
                        setGraphic(null);
                    } else {
                        setGraphic(button);

                        // 处理按钮点击事件,这里是删除按钮所在行
                        button.setOnAction(event -> {
                            ObservableList<Person> items = getTableView().getItems();
                            int index = getIndex();
                            if (index >= 0) {
                                items.remove(index);
                            }
                        });
                    }
                }
            };
            return cell;
        });

        // 创建一些数据
        ObservableList<Person> data = FXCollections.observableArrayList(
                new Person("Alice", 1),
                new Person("Bob", 2),
                new Person("Charlie", 3)
        );

        // 将数据设置到TableView中
        tableView.setItems(data);
    }
}

application主程序部分

package com.example.demo4;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import java.io.IOException;

public class HelloApplication extends Application {
    double OffsetX, OffsetY;

    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 600, 400);
        // 定义拖动窗口
        scene.setOnMousePressed(event -> {
            OffsetX = event.getSceneX();
            OffsetY = event.getSceneY();

        });
        //鼠标拖动窗口
        scene.setOnMouseDragged(event -> {
            stage.setX(event.getScreenX() - OffsetX);
            stage.setY(event.getScreenY() - OffsetY);
        });
        // 去掉窗口标题、最小化、最大化和关闭按钮以及窗口边框
        stage.initStyle(StageStyle.UNDECORATED);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

用到的Person类部分

package com.example.demo4;

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Person {
    // 最好定义成final
    private final StringProperty name;
    private final IntegerProperty age;

    public Person(String name, int age) {
        this.name = new SimpleStringProperty(name);
        this.age = new SimpleIntegerProperty(age);
    }

    // 不能删除getAge和getName,否则报错
    public int getAge() {
        return age.get();
    }

    public String getName() {
        return name.get();
    }
}

代码参考资料:CSDN  AI

欢迎指正错误,本人新手