大家好,今天给大家带来了使用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