JavaFX字库精简项目开发(四)—— 装配LocalServer

概述

JavaFX是用于构建富互联网应用程序的Java库。使用JavaFX开发的应用程序可以在各种设备上运行,如台式计算机,手机,物联网设备,平板电脑等。最近为了巩固一下JavaFX学习成果,准备利用整个技术开发一个工具软件能够对字库进行裁剪,可以根据用户的设置自动生成精简字库,简化手动裁剪的麻烦。

技术实现

在上一篇文章我在程序中增加了WebView组件,可以引入Web前端技术。但是javaFX的WebView组件仅仅适用于web页面的显示场景,对于文件下载支持不好。网上虽然有下载文件的例子,我实验没有成功。因此我决定将前端生成的json文件内容通过post请求发送到javaFX创建的服务器中,再完成文件创建写入操作。

涉及技术

  • JavaFX8中的WebView,jfoenix8
  • html js css 基本的web技术
  • SimpleServer

功能编码

后端服务创建

使用hutool工具类创建简单服务器

import cn.hutool.http.HttpUtil;
import cn.hutool.http.server.SimpleServer;
import cn.hutool.json.JSONUtil;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;


public class LocalServer {


    public static void startLocalServer() throws Exception {
        SimpleServer server = HttpUtil.createServer(8082);
        server.addAction("/font/convert", (request, res) -> {
            FileInputStream fis = null;
            BufferedOutputStream bos = null;
            try {
                fis = new FileInputStream(MainController.fileDes);
                byte[] tmp = new byte[fis.available()];
                fis.read(tmp);
                res.setContentType("application/octet-stream");
                res.setHeader("Content-Disposition",
                        "attachment;fileName=" + new String("msyh_simplify.ttf".getBytes("utf-8"), "iso8859-1"));
                res.setHeader("Content-Length", String.valueOf(tmp.length));
                bos = new BufferedOutputStream(res.getOut());
                bos.write(tmp, 0, tmp.length);
                bos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (fis!=null) {
                    try {
                        fis.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
                if (bos!=null) {
                    try {
                        bos.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        });
        //用来处理前端传来的数据
        server.addAction("/push/json", (request, res) -> {
          String output = (String) JSONUtil.parseArray(request.getParams().get("res")).get(0);
          String fileName = (String) JSONUtil.parseArray(request.getParams().get("name")).get(0);
            System.out.println(res+"----"+fileName);
          String filePath = MainController.getBasicFilePath()+ File.separator+fileName;
            Files.write(Paths.get(filePath),output.getBytes(Charset.defaultCharset()));
        });
        server.start();
    }
}

前端调用接口

//调用简化后ttf字库,转换为json字库
function convertTTFtoJson() {
    opentype.load('http://127.0.0.1:8082/font/convert', function(err, font) {
        if (err)
            throw err;
        var result = convert(font);
        exportString(result, font.familyName + "_" + font.styleName + ".json");
    });


}
restrictCharactersCheck.onchange = function() {
    restrictCharacterSetInput.disabled = !restrictCharactersCheck.checked;
};
//导出字符串
var exportString = function(output, filename) {

    var blob = new Blob([output], {
        type: 'text/plain'
    });
    var objectURL = URL.createObjectURL(blob);

    var link = document.createElement('a');
    link.href = objectURL;
    link.download = filename || 'data.json';
    link.target = '_blank';
    // link.click();

    var event = document.createEvent("MouseEvents");
    event.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false,
        false, false, false, 0, null);
    link.dispatchEvent(event);
    //将json传回cs端的服务器
    var res = {"res":output,"name":filename}
    $.ajax({
        url:'http://127.0.0.1:8082/push/json',
        type: 'POST',
        data: res,
        dataType: 'JSON',
        success: function (data) {
        }
    });
};
//字体库简化
var convert = function(font) {

    console.log(font);

    var scale = (1000 * 100) / ((font.unitsPerEm || 2048) * 72);
    var result = {};
    result.glyphs = {};

    var restriction = {
        range: null,
        set: null
    };

    if (restrictCharactersCheck.checked) {
        var restrictContent = restrictCharacterSetInput.value;
        var rangeSeparator = '-';
        if (restrictContent.indexOf(rangeSeparator) != -1) {
            var rangeParts = restrictContent.split(rangeSeparator);
            if (rangeParts.length === 2 && !isNaN(rangeParts[0]) &&
                !isNaN(rangeParts[1])) {
                restriction.range = [parseInt(rangeParts[0]),
                    parseInt(rangeParts[1])
                ];
            }
        }
        if (restriction.range === null) {
            restriction.set = restrictContent;
        }
    }

    font.glyphs
        .forEach(function(glyph) {
            if (glyph.unicode !== undefined) {
                var glyphCharacter = String.fromCharCode(glyph.unicode);
                var needToExport = true;
                if (restriction.range !== null) {
                    needToExport = (glyph.unicode >= restriction.range[0] && glyph.unicode <= restriction.range[1]);
                } else if (restriction.set !== null) {
                    needToExport = (restrictCharacterSetInput.value
                        .indexOf(glyphCharacter) != -1);
                }
                if (needToExport) {

                    var token = {};
                    token.ha = Math.round(glyph.advanceWidth * scale);
                    token.x_min = Math.round(glyph.xMin * scale);
                    token.x_max = Math.round(glyph.xMax * scale);
                    token.o = ""

                    glyph.path.commands.forEach(function(command, i) {
                        if (command.type.toLowerCase() === "c") {
                            command.type = "b";
                        }
                        token.o += command.type.toLowerCase();
                        token.o += " "
                        if (command.x !== undefined &&
                            command.y !== undefined) {
                            token.o += Math.round(command.x * scale);
                            token.o += " "
                            token.o += Math.round(command.y * scale);
                            token.o += " "
                        }
                        if (command.x1 !== undefined &&
                            command.y1 !== undefined) {
                            token.o += Math.round(command.x1 * scale);
                            token.o += " "
                            token.o += Math.round(command.y1 * scale);
                            token.o += " "
                        }
                        if (command.x2 !== undefined &&
                            command.y2 !== undefined) {
                            token.o += Math.round(command.x2 * scale);
                            token.o += " "
                            token.o += Math.round(command.y2 * scale);
                            token.o += " "
                        }
                    });
                    result.glyphs[String.fromCharCode(glyph.unicode)] = token;
                }
            };
        });
    result.familyName = font.familyName;
    result.ascender = Math.round(font.ascender * scale);
    result.descender = Math.round(font.descender * scale);
    result.underlinePosition = Math.round(font.tables.post.underlinePosition *
        scale);
    result.underlineThickness = Math.round(font.tables.post.underlineThickness *
        scale);
    result.boundingBox = {
        "yMin": Math.round(font.tables.head.yMin * scale),
        "xMin": Math.round(font.tables.head.xMin * scale),
        "yMax": Math.round(font.tables.head.yMax * scale),
        "xMax": Math.round(font.tables.head.xMax * scale)
    };
    result.resolution = 1000;
    result.original_font_information = font.tables.name;
    if (font.styleName.toLowerCase().indexOf("bold") > -1) {
        result.cssFontWeight = "bold";
    } else {
        result.cssFontWeight = "normal";
    };

    if (font.styleName.toLowerCase().indexOf("italic") > -1) {
        result.cssFontStyle = "italic";
    } else {
        result.cssFontStyle = "normal";
    };
    return JSON.stringify(result);
};

总结

以上已经完成全后端的简单交互,实现了文件文件的下载。通过javaFX中打开相应的文件路径,就可以做到下载功能。

好的,我可以为您提供一份简单的JavaFX代码示例,用于实现TICTACTOE三子棋游戏。以下是示例代码: ```java import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.GridPane; import javafx.stage.Stage; public class TicTacToe extends Application { private boolean playerXTurn = true; private Button[][] buttons = new Button[3][3]; private Label label = new Label("X's turn"); @Override public void start(Stage primaryStage) { GridPane gridPane = new GridPane(); gridPane.setHgap(10); gridPane.setVgap(10); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Button button = new Button(); button.setPrefSize(100, 100); button.setOnAction(event -> { if (button.getText().isEmpty()) { if (playerXTurn) { button.setText("X"); label.setText("O's turn"); } else { button.setText("O"); label.setText("X's turn"); } playerXTurn = !playerXTurn; checkWinner(); } }); buttons[i][j] = button; gridPane.add(button, i, j); } } Scene scene = new Scene(new javafx.scene.layout.VBox(gridPane, label), 320, 320); primaryStage.setScene(scene); primaryStage.show(); } private void checkWinner() { for (int i = 0; i < 3; i++) { if (!buttons[i][0].getText().isEmpty() && buttons[i][0].getText().equals(buttons[i][1].getText()) && buttons[i][0].getText().equals(buttons[i][2].getText())) { showWinner(buttons[i][0].getText()); return; } } for (int i = 0; i < 3; i++) { if (!buttons[0][i].getText().isEmpty() && buttons[0][i].getText().equals(buttons[1][i].getText()) && buttons[0][i].getText().equals(buttons[2][i].getText())) { showWinner(buttons[0][i].getText()); return; } } if (!buttons[0][0].getText().isEmpty() && buttons[0][0].getText().equals(buttons[1][1].getText()) && buttons[0][0].getText().equals(buttons[2][2].getText())) { showWinner(buttons[0][0].getText()); return; } if (!buttons[0][2].getText().isEmpty() && buttons[0][2].getText().equals(buttons[1][1].getText()) && buttons[0][2].getText().equals(buttons[2][0].getText())) { showWinner(buttons[0][2].getText()); return; } boolean isDraw = true; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (buttons[i][j].getText().isEmpty()) { isDraw = false; break; } } if (!isDraw) { break; } } if (isDraw) { showWinner("draw"); } } private void showWinner(String winner) { if (winner.equals("draw")) { label.setText("It's a draw!"); } else { label.setText(winner + " wins!"); } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { buttons[i][j].setDisable(true); } } } public static void main(String[] args) { launch(args); } } ``` 在这份代码中,我们使用了JavaFX的GridPane布局,创建了一个3*3的按钮矩阵。每次点击按钮,就会在对应的位置上放置一个“X”或“O”,并检查是否有胜利者。当游戏结束时,游戏将不再响应任何点击操作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NewTech精选

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值