JavaFX 实现自己的浏览器

大家好,今天给大家带来了使用JavaFX定制自己的浏览器

这是一个桌面应用可以使用jar方式运行,也可以用别的工具打包成exe,本人因不喜欢模块化,因此未使用FXML,纯代码加css方式实现的,大家先看看效果

 

 下面为结构图,代码一字不漏全在下面,可以直接复制粘贴运行,就创建普通的项目就行,不要用模块化

创建项目

1.先创建一个最普通的maven项目这里我就不演示了直接给大家看pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>MyBrowser</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>17.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-web</artifactId>
            <version>17.0.1</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.3</version>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <!-- <mainClass>启动类位置</mainClass> -->
                            <mainClass>com.kur.ban.BrowserStart</mainClass>
                        </manifest>
                    </archive>

                    <descriptorRefs>
                        <!-- jar 携带依赖 -->
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

创建BrowserApplication类

创建BrowserApplication继承Application重写start方法

package com.kur.ban;

import cn.hutool.core.lang.Console;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.ListChangeListener;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import java.awt.*;
import java.io.File;

public class BrowserApplication extends Application {
    private static final Log log = LogFactory.get();

    /**
     * @init() 此方法为初始化方法
     * @start() 此方法为运行中方法
     * @stop() 此方法在窗口关闭时调用
     */
    @Override
    public void init() throws Exception {
        super.init();
        log.info("正在初始化...");

        //下面的操作为创建一个txt文件,用来记录下载历史

        //获取系统的\
        String property = System.getProperty("file.separator");
        File file = new File("D:" + property + "Browser");
        //file.exists() 此方法为检测路径是否存在
        if (file.exists()) {
            String path = file.getAbsolutePath() + property + "download.txt";
            File download = new File(path);
            if (download.exists()) {
                log.info("默认存放下载记录的文件已存在");
            } else {
                if (download.createNewFile()) {
                    log.info("成功创建默认存放下载记录的文件");
                } else {
                    log.debug("创建默认存放下载记录的文件失败");
                }
            }
        } else {
            //file.mkdir() 此方法为创建文件夹的方法
            if (file.mkdir()) {
                String path = file.getAbsolutePath() + property + "download.txt";
                File download = new File(path);
                //download.createNewFile() 此方法为创建文件
                if (download.createNewFile()) {
                    log.info("成功创建默认存放下载记录的文件");
                }
                log.info("成功创建存放下载记录的文件的目标文件夹");
            }
        }
    }

    double x = 0; //记录x轴坐标
    double y = 0; //记录y轴坐标

    @Override
    public void start(Stage stage) throws Exception {
        //创建布局
        BorderPane borderPane = new BorderPane();
        borderPane.setId("borderPane");
        //创建场景
        Scene scene = new Scene(borderPane);
        //把场景放入到窗口
        stage.setScene(scene);
        stage.setWidth(1500);
        stage.setHeight(800);
        //因为是浏览器所以使用TabPane新建和删除页面
        TabPane tabPane = new TabPane();
        //通过方法返回一个tab
        Tab tab = Element_Tab.getTab(tabPane, stage);
        //添加一个tab
        tabPane.getTabs().add(tab);
//        tabPane.getSelectionModel().select(tab);
        //返回一个HBox布局,里面放着各种按钮
        HBox hBox = Element_TopButton.getTopButton(stage);
        //把tabPane放在borderPane的中间位置
        borderPane.setCenter(tabPane);
        //把hBox放在borderPane的上面
        borderPane.setTop(hBox);
        //设置窗口的样式,设置成无任何样式跟按钮,按钮需要全部自定义
        stage.initStyle(StageStyle.TRANSPARENT);
        //显示窗口
        stage.show();

        //给tabPane添加监听,监听tab面板增加和减少
        tabPane.getTabs().addListener(new ListChangeListener<Tab>() {
            @Override
            public void onChanged(Change<? extends Tab> change) {
                //默认选中新增加的tab面板
                tabPane.getSelectionModel().select(change.getList().size() - 1);
                if (change.getList().size() == 0) {
                    log.debug("所有的tab窗口都被关闭了,自动结束程序运行!");
                    Console.log("--------------------------------");
                    stage.close();
                    Platform.exit();
                }
            }
        });

        //鼠标按压事件
        scene.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                //mouseEvent.getScreenX()获取鼠标在屏幕上的坐标
                //stage.getX() 获取窗口的坐标
                x = mouseEvent.getScreenX() - stage.getX();
                y = mouseEvent.getScreenY() - stage.getY();
            }
        });

        //鼠标拖动事件
        scene.setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                stage.setX(mouseEvent.getScreenX() - x);
                stage.setY(mouseEvent.getScreenY() - y);
            }
        });
        //添加css样式
        scene.getStylesheets().addAll("/css/tabPane.css",
                "/css/topButton.css",
                "/css/textFiled.css",
                "/css/button.css",
                "/css/hBox.css",
                "/css/topHBox.css",
                "/css/progressBar.css",
                "/css/menuBar.css",
                "/css/label.css"
        );
        //添加图标
        stage.getIcons().add(new Image("icon/system.jpeg"));
    }

    @Override
    public void stop() throws Exception {
        super.stop();
    }
}

创建启动类BrowserStart

package com.kur.ban;
import javafx.application.Application;

//因为未使用模块化所以需要此启动方式,不然会报javafx缺少组件的错误
public class BrowserStart {
    public static void main(String[] args){
        Application.launch(BrowserApplication.class, args);
    }
}

创建Element_Tab

package com.kur.ban;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import javafx.collections.ListChangeListener;
import javafx.concurrent.Worker;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URLConnection;
import java.util.*;

public class Element_Tab {
    private static String tittle;

    public static Tab getTab(TabPane tabPane, Stage stage) throws IOException {
        Log log = LogFactory.get();
        Tab tab = new Tab();
        BorderPane borderPane = new BorderPane();
        tab.setContent(borderPane);
        WebView webView = new WebView();
        WebEngine engine = webView.getEngine();
        engine.load("https://www.baidu.com");
        webView.setContextMenuEnabled(true);
        TextField textField = Element_TextFiled.getTextField(engine);
        textField.setId("textFiled");
        Button retreat = Element_Button.retreat(engine);
        Button advance = Element_Button.advance(engine);
        Button refresh = Element_Button.refresh(engine);
        Button go = Element_Button.go(textField, engine);
        Button addTab = Element_Button.addTab(tabPane, stage);
        MenuBar menuBar = Element_MenuBar.getMenuBar(engine, stage);


        MenuBar downloadMenuBar = new MenuBar();
        downloadMenuBar.setId("downloadMenuBar");
        Menu downloadMenu = new Menu("下载管理");
        downloadMenu.setId("downloadMenu");
        downloadMenuBar.getMenus().addAll(downloadMenu);

        HBox topHBox = new HBox(retreat, advance, textField, go, addTab, refresh, menuBar, downloadMenuBar);
        topHBox.setId("topHBox");
        topHBox.setFillHeight(true);
        borderPane.setTop(topHBox);
        borderPane.setCenter(webView);
        ProgressBar progressBar = Element_ProgressBar.getProgressBar(webView, engine);
        progressBar.setId("progressBar");
        borderPane.setBottom(progressBar);
        engine.getLoadWorker().stateProperty().addListener((observableValue, state, t1) -> {
            if (t1 == Worker.State.FAILED) {
                engine.reload();
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.initOwner(stage);
                alert.setTitle("加载错误");
                alert.setContentText("您的网址有误! 请输入正确的网址." + "\n检查网络连接是否正常.");
                alert.getButtonTypes().addListener((ListChangeListener<ButtonType>) change -> {
                    Button button = (Button) change.getList();
                    button.setOnAction(actionEvent -> {
                        textField.isFocused();
                        engine.reload();
                    });
                });
                alert.show();
            }
        });
        engine.titleProperty().addListener((observableValue, oldValue, newValue) -> {
            tab.setText(newV
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JsonToDart

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

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

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

打赏作者

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

抵扣说明:

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

余额充值