前端人写后端javafx两个月的日常记录!

1,849 阅读3分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

JavaFX 是一个用于构建富 Internet 应用程序的 Java 库。使用该库编写的应用程序可以在多个平台上一致运行。使用 JavaFX 开发的应用程序可以在各种设备上运行,例如台式机、手机、电视、平板电脑等。

1.获取节点位置

这取决于您所说的绝对"是什么意思.节点有一个坐标系,其父级有一个坐标系,父级有一个坐标系,依此类推,最终有一个用于 Scene 的坐标系和一个用于屏幕的坐标系(这可能是一个物理显示设备的集合).

你可能想要相对于 Scene 的坐标,在这种情况下你可以做

Bounds boundsInScene = node.localToScene(node.getBoundsInLocal()); 

或相对于屏幕的坐标:

Bounds boundsInScreen = node.localToScreen(node.getBoundsInLocal()); 

无论哪种情况,结果都是 Bounds 对象有 getMinX(), getMinY(), getMaxX(), getMaxY()code>、getWidth() 和 getHeight() 方法.

2.ListView监听

    // 待岗容器列表
    ObservableList<Node> oriList = FXCollections.observableArrayList();

    // listview设置数据
    oriBox.setItems(oriList);

    // 监听listview点击
    private void listViewClick(ListView box, ObservableList<Node> list) {
        box.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(final MouseEvent mouseEvent) {
                node = (Pane) list.get(box.getSelectionModel().getSelectedIndex());
                Map params = (Map) node.getProperties().get("params");
                String name = (String) params.get("name");
                paneNode = generateRectangleNode(name);
                root.getChildren().add(paneNode);
                // 获取节点的位置
                Bounds boundsInScene = node.localToScene(node.getBoundsInLocal());
                paneNode.relocate(mouseEvent.getX()+boundsInScene.getMinX(), mouseEvent.getY()+boundsInScene.getMinY());
                box.getSelectionModel().clearSelection();
            }
        });
    }

3.键盘监听事件获取焦点

// 键盘事件
    private void initKeyPress() {
        settingDialog.setOnDialogOpened(event -> {
            settingDialog.requestFocus();
        });

        settingDialog.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                switch (event.getCode()) {
                    case F3:
                        System.out.println("保存");
                        break;
                    case F4:
                        closeDialog();
                        break;
                    case F5:
                        System.out.println("同步");
                        break;
                    case F6:
                        System.out.println("应用");
                        break;
                }
            }
        });
    }

4.让组件隐藏且不占用空间

pwdStrengthPane.setVisible(false);
// 设置其托管状态
pwdStrengthPane.setManaged(false);

5.进度条动态变化

    public void init(Stage stage) {
        Timeline task = new Timeline(
                new KeyFrame(
                        Duration.ZERO,
                        new KeyValue(initProgress.progressProperty(), 0)),
                new KeyFrame(
                        Duration.seconds(2),
                        new KeyValue(initProgress.progressProperty(), 1)));
        task.setCycleCount(Timeline.INDEFINITE);
        task.play();
    }

6.动态双向绑定数据

// model
package com.xmcares.scims.desktop.gui.models.cert;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class CertModel {
    private final StringProperty dpsrCardName=new SimpleStringProperty("");

    public StringProperty dpsrCardNameProperty() {
        return dpsrCardName ;
    }
    public final void setDpsrCardName(String text) {
        dpsrCardNameProperty().set(text);
    }
    public final String getDpsrCardName() {
        return dpsrCardNameProperty().get();
    }
}

// set
certmodel.setDpsrCardName((String) params.get("dpsrCardName"));

// bindData监听数据变化
certModel.dpsrCardNameProperty().addListener(((observable, oldValue, newValue) -> {
            dpsrCardName.setText(newValue);
            openDialog();
}));

7.全局注册数据 (如cookie)

// 设置data
ApplicationContext.getInstance().register("departurePassenger", departurePassenger);

// 全局获取data
JSONObject departurePassenger = (JSONObject) ApplicationContext.getInstance().getRegisteredObject("departurePassenger");

8.键盘大小写和中文限制

     // 大写锁定和限制输入中文
        usernameField.setTextFormatter(new TextFormatter<>((change) -> {
            change.setText(change.getText().toUpperCase().replaceAll("[\u4e00-\u9fa5]+",""));
            return change;
        }));

9.combox修改列表背景和文字颜色

.jfx-combo-box .list-cell:hover {
    -fx-background-color: rgb(245,245,245);
    -fx-text-fill: #000;
}

10.combox如何实现过滤查询

/**
 * @Description combox 过滤
 * @Author lius
 * @Date 2022/10/24 10:37
 */
package com.xmcares.scims.desktop.gui.components.comboBox;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.control.ComboBox;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

public class AutoCompleteComboBoxListener<T> implements EventHandler<KeyEvent> {

    private ComboBox<T> comboBox;
    private ObservableList<T> data;
    private boolean moveCaretToPos = false;
    private int caretPos;

    public AutoCompleteComboBoxListener(final ComboBox<T> comboBox) {
        this.comboBox = comboBox;
        data = comboBox.getItems();
        this.comboBox.setEditable(true);
        this.comboBox.setOnKeyReleased((EventHandler<? super KeyEvent>) AutoCompleteComboBoxListener.this);
    }

    @Override
    public void handle(KeyEvent event) {
        if (event.getCode() == KeyCode.UP) {
            caretPos = -1;
            moveCaret(comboBox.getEditor().getText().length());
            return;
        } else if (event.getCode() == KeyCode.DOWN) {
            if (!comboBox.isShowing())
                comboBox.show();

            caretPos = -1;
            moveCaret(comboBox.getEditor().getText().length());
            return;
        }

        if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT
                || event.isControlDown() || event.getCode() == KeyCode.HOME
                || event.getCode() == KeyCode.END || event.getCode() == KeyCode.TAB) {
            return;
        }

        comboBox.hide();

        if (event.getCode() == KeyCode.BACK_SPACE) {
            moveCaretToPos = true;
            caretPos = comboBox.getEditor().getCaretPosition();
        } else if (event.getCode() == KeyCode.DELETE) {
            moveCaretToPos = true;
            caretPos = comboBox.getEditor().getCaretPosition();
        }


        ObservableList<T> list = FXCollections.observableArrayList();
        for (int i = 0; i < data.size(); i++) {
                if (data.get(i) != null&&data.get(i).toString().toLowerCase().startsWith(
                        AutoCompleteComboBoxListener.this.comboBox
                                .getEditor().getText().toLowerCase())) {
                    list.add(data.get(i));
                }
        }
        String t = comboBox.getEditor().getText();
        comboBox.setItems(list);
        comboBox.getEditor().setText(t);
        if (!moveCaretToPos) {
            caretPos = -1;
        }
        moveCaret(t.length());
        if (!list.isEmpty()) {
            comboBox.show();
        }
    }

    private void moveCaret(int textLength) {
        if (caretPos == -1)
            comboBox.getEditor().positionCaret(textLength);
        else
            comboBox.getEditor().positionCaret(caretPos);
        moveCaretToPos = false;
    }

}



public class JavaFXApplication1 extends Application {

    @Override
    public void start(Stage primaryStage) {
        ComboBox<String> combo = new ComboBox<>();
        ObservableList<String> list = FXCollections.observableArrayList();
        list.add("A");
        list.add("AND");
        list.add("ANDR");
        list.add("ANDRE");
        list.add("B");
        list.add("BP");
        list.add("BPO");
        combo.setItems(list);
        new AutoCompleteComboBoxListener(combo);

        StackPane root = new StackPane();
        root.getChildren().add(combo);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

11.高度撑满使hbox定位到stackpane底部解决办法

        HBox changeBox = new HBox();
        changeBox.setMaxHeight(Region.USE_PREF_SIZE);
        changeBox.setMaxWidth(Region.USE_PREF_SIZE);
        setMargin(changeBox, new Insets(20));
        stackPane.setAlignment(changeBox, Pos.BOTTOM_CENTER);

12.跳转浏览器(解决ie浏览器拼接参数丢失问题)

        String deviceId = "";
        String staffCardId = "";
        URI uri = URI.create(MainService.SCIMS_SERVER_URL + MainService.SCIMS_COURTESY + "&staffCardId=" + staffCardId + "&deviceId=" + deviceId);
        /*下面这样处理是为了避免在打开IE浏览器的时候带&号后面的参数被截掉的问题*/
        String url = uri.toString().replaceAll(""", "'");
        url = """ + url + """;
        try {
            browse(url);
        } catch (IOException e) {
            e.printStackTrace();
        }



    public static void browse(String url) throws Exception {
        // 获取操作系统的名字
        String osName = System.getProperty("os.name", "");
        if (osName.startsWith("Mac OS")) {
            // 苹果的打开方式
            Class fileMgr = Class.forName("com.apple.eio.FileManager");
            Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[]{String.class});
            openURL.invoke(null, new Object[]{url});
        } else if (osName.startsWith("Windows")) {
            // windows的打开方式。
            //打开IE浏览器
            Runtime.getRuntime().exec("cmd /c start iexplore " + url);
        } else {
            // Unix or Linux的打开方式
            String[] browsers = {"firefox", "opera", "konqueror", "epiphany",
                    "mozilla", "netscape"};
            String browser = null;
            for (int count = 0; count < browsers.length && browser == null; count++) {
                // 执行代码,在brower有值后跳出,
                // 这里是如果进程创建成功了,==0是表示正常结束。
                if (Runtime.getRuntime()
                        .exec(new String[]{"which", browsers[count]})
                        .waitFor() == 0)
                    browser = browsers[count];
                if (browser == null)
                    throw new Exception("Could not find web browser");
                else
                    // 这个值在上面已经成功的得到了一个进程。
                    Runtime.getRuntime().exec(new String[]{browser, url});
            }
        }
    }

13.设置新的stage关闭后才能操作其他行为

stage.initModality(Modality.APPLICATION_MODAL);

14.设置stage自适应窗口大小

stage.sizeToScene();

15.表格数据导出excel

说明:guestTable为tableview的id;

    /*下载文件*/
    public void download() throws IOException {
        Workbook workbook = new HSSFWorkbook();
        Sheet spreadsheet = workbook.createSheet("FlightBoardingInfo");
        Row row = spreadsheet.createRow(0);

        for (int j = 0; j < guestTable.getColumns().size(); j++) {
            row.createCell(j).setCellValue(guestTable.getColumns().get(j).getText());
        }

        for (int i = 0; i < guestTable.getItems().size(); i++) {
            row = spreadsheet.createRow(i + 1);
            for (int j = 0; j < guestTable.getColumns().size(); j++) {
                if (guestTable.getColumns().get(j).getCellData(i) != null) {
                    row.createCell(j).setCellValue(guestTable.getColumns().get(j).getCellData(i).toString());
                } else {
                    row.createCell(j).setCellValue("");
                }
            }
        }
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("导出");
        fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("XLS", "*.xls"),
                new FileChooser.ExtensionFilter("Allfiles", "*.*"));
        File desktopDir = FileSystemView.getFileSystemView().getHomeDirectory();
        String currentDesktopPath = desktopDir.getAbsolutePath();
        fileChooser.setInitialDirectory(new File(currentDesktopPath));
        fileChooser.setInitialFileName("demo.xls");
        File file = fileChooser.showSaveDialog(this.getScene().getWindow());
        if (file != null) {
            try {
                FileOutputStream fileOut = new FileOutputStream(file.getAbsolutePath());
                workbook.write(fileOut);
                fileOut.close();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    }

16.Javafx JFXComboBox字体样式重置

/*重置下拉框下拉内容样式*/
.jfx-combo-box .list-view .list-cell {
    -fx-text-fill: #000;
}

/*重置下拉框下拉内容悬浮样式*/
.jfx-combo-box .list-cell:hover {
    -fx-background-color: #ccc;
    -fx-text-fill: #000;
}

/*注意:很久没试成功,发现这样可以,重置下拉框文本样式*/
.jfx-combo-box .cell {
    -fx-text-fill: white;
}

17.JNativeHook全局键盘的使用技巧

1.1 版本2.2.0-2.2.2打包没法运行问题

解决办法:

(1)换低2.1.0版本便可以解决,但是会有个问题,鼠标日志一直打印,禁用方法:

private void initGlobalClick() {
    try {
        GlobalScreen.registerNativeHook();
    } catch (NativeHookException ex) {
        System.exit(1);
    }
    GlobalMouseListener globalMouseListener = new GlobalMouseListener(this);
    GlobalScreen.addNativeMouseListener(globalMouseListener);
    // logger日志禁用
    Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
    LogManager.getLogManager().reset();
    logger.setLevel(Level.OFF);
    logger.setUseParentHandlers(false);
}

18.stage关闭后websocket可以重新激活打开

1.第一种方式

// 防止点击关闭后不能在打开
Platform.setImplicitExit(false);

2.第二种方式

      ownStage.setOnCloseRequest(e -> {
            Platform.exit();
            System.exit(0);
        });

查阅文档

比较全的文档: www.jc2182.com/javafx/java…

拖拽文档:www.leestorm.com/post/95.htm…

其他:

vimsky.com/examples/de…

jenkov.com/tutorials/j…

fxdocs.github.io/docs/html5/…

www.javaroad.cn/questions/1…