Main函数
使用idea 或 e(fx)lipse创建javafx项目,自动生成的入口文件
private static final Logger logger = Logger.getLogger(Main.class.getName());
private Stage stage;
private ShowPhotoController showPhotoController;
@Override
public void start(Stage primaryStage) throws Exception {
this.stage = primaryStage;
primaryStage.setTitle("魑魅魍魉"); //程序标题
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("images/icon.png"))); //设置图标
//primaryStage.initStyle(StageStyle.UNDECORATED);// 隐藏标题栏
initRootLayout(); //此处设置程序进入界面
//程序关闭时操作
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent event) {
if (showPhotoController != null) {
showPhotoController.closeMonitor();
}
Platform.exit();
}
});
}
private void initRootLayout() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("login/activity_login.fxml")); // 静态读取,无法获取controller
GridPane rootLayout = loader.load(); //activity_login.fxml的跟标签必须是GridPane 若返回其他则相应修改
Scene scene = new Scene(rootLayout, width, height); //新建场景
stage.setScene(scene); //设置场景
LoginController loginController = loader.getController(); //获取场景对应的Controller 用于控制页面显示
loginController.init(stage);
stage.show(); //显示页面
} catch (IOException e) {
e.printStackTrace();
}
}
private double width = 562; // 窗口宽度
private double height = 342; // 窗口高度
//部分代码省略
.fxml 界面
界面可视化需要添加插件 Scene builder 网上有教程,请自行百度
// 注意此处设置对应的controller
<GridPane fx:id="root" alignment="center" hgap="10" vgap="10" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.login.LoginController">
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import com.jfoenix.controls.JFXTextField?>
<?import com.jfoenix.controls.JFXPasswordField?>
<?import com.jfoenix.controls.JFXButton?>
<GridPane fx:id="root" alignment="center" hgap="10" vgap="10" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.login.LoginController">
<children>
<Pane fx:id="root_view" prefHeight="342.0" prefWidth="562.0" >
<children>
<Label layoutX="160.0" layoutY="200.0" prefHeight="23.0" prefWidth="80" text="用户名:" textAlignment="CENTER" textFill="WHITE"
style="-fx-font-size:16px;fx-text-fill:WHITE;-fx-prompt-text-fill:WHITE;"
/>
<JFXTextField fx:id="userName" onKeyPressed="#usernamePressed" layoutX="240" layoutY="190.0"
minWidth="160"
prefHeight="23.0" prefWidth="100.0" promptText="请输入用户名"
style="-fx-font-size:16px;-fx-text-fill:white;-fx-prompt-text-fill:white;" >
</JFXTextField>
<Label layoutX="160.0" layoutY="240.0" prefHeight="23.0" prefWidth="80" text="密 码:" textAlignment="CENTER" textFill="WHITE"
style="-fx-font-size:16px;-fx-text-fill:WHITE;-fx-prompt-text-fill:WHITE;"
/>
<JFXPasswordField fx:id="password" layoutX="240.0" layoutY="230.0"
minWidth="160"
prefHeight="23.0" prefWidth="100.0" onKeyPressed="#passwordPressed"
promptText="请输入密码" style="-fx-font-size:16px;-fx-text-fill:white;-fx-prompt-text-fill:white;">
</JFXPasswordField>
<JFXButton fx:id="btn_login" buttonType="RAISED"
layoutX="220.0" layoutY="280.0"
onAction="#onLogin" prefHeight="35" prefWidth="100" style="-fx-font-size:14px;-fx-background-color:WHITE;" text="登录" />
</children>
</Pane>
</children>
<columnConstraints>
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints />
</rowConstraints>
</GridPane>
CONTROLLER 用于操作页面显示,处理数据等
//所有.fxml页面的fx:id 在controller中需要使用@FXML注解声明
@FXML
private TextField userName;
@FXML
private TextField password;
@FXML
private JFXButton btn_login; //使用JFXButton需要导入jar包
@FXML
private Pane root_view;
private Stage primaryStage;
private Preferences prefs; //实现缓存数据
public void init(Stage primaryStage) {
this.primaryStage = primaryStage;
//设置页面背景 背景路径为工程跟路径开始,最终打包时,需将其目录拷贝到打包文件夹下
BackgroundImage myBI = new BackgroundImage(new Image("images/login.bg", 562, 342, false, true), BackgroundRepeat.REPEAT,
BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, BackgroundSize.DEFAULT);
root_view.setBackground(new Background(myBI));
prefs = Preferences.userNodeForPackage(Main.class); //实现用户缓存
String username = prefs.get("username", "");
userName.setText(username); //自动填入缓存的账号
if (!StringUtil.isEmpty(username)) { //账号不为空,自动选中密码输入框
password.requestFocus();
password.selectAll();
}
}
public void initialize() {
//会先调用
}
@FXML
public void passwordPressed(KeyEvent keyEvent) {
KeyCode code = keyEvent.getCode();
if (code == KeyCode.ENTER) {
onLogin();
}
}
@FXML
public void usernamePressed(KeyEvent keyEvent) {
KeyCode code = keyEvent.getCode();
if (code == KeyCode.ENTER) {
password.requestFocus();
}
}
@FXML
public void onLogin() {
String userNameText = userName.getText();
String passwordText = password.getText();
if (StringUtil.isEmpty(userNameText)) {
ToastUtil.toast("请输入用户名", 1500);
return;
}
if (StringUtil.isEmpty(passwordText)) {
ToastUtil.toast("请输入密码", 1500);
return;
}
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("username", userNameText);
hashMap.put("password", MD5Util.getMD5Str(passwordText));
btn_login.setDisable(true); // 点击之后按钮不可用
//封装的网络请求
DialogUtil.showDialog1(primaryStage, "正在登录...");
HttpUtil.getInstance().post(hashMap, HttpUtil.uri_login, new HttpCallBack() {
@Override
public void success(String success) {
System.out.println("success>>" + success);
saveUserNameAndPassword(userNameText, passwordText);
saveSuccessData(success);
parseSuccess(success);
}
@Override
public void fail(String fail) {
Platform.runLater(new Runnable() { // 主线程中完成
@Override
public void run() {
btn_login.setDisable(false); // 还原按钮
DialogUtil.dismissDialog();
ToastUtil.toast(fail, 1500);
}
});
}
});
}
其他内容
需要导入的包,若复制本程序,请注意版本
导包右键——》add as lib…
本程序使用OKHTTP
使用到的工具类
1、DialogUtil
package sample.utils;
import com.jfoenix.controls.JFXAlert;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialogLayout;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class DialogUtil {
private static JFXAlert alert;
public static void showDialog(Stage primaryStage, String title, String message, String btnStr) {
alert = new JFXAlert(primaryStage);
alert.initModality(Modality.APPLICATION_MODAL);
alert.setOverlayClose(false);
JFXDialogLayout layout = new JFXDialogLayout();
layout.setHeading(new Label(title));
layout.setBody(new Label(message));
JFXButton closeButton = new JFXButton(btnStr);
closeButton.getStyleClass().add("dialog-accept");
closeButton.setOnAction(event -> alert.hideWithAnimation());
layout.setActions(closeButton);
alert.setContent(layout);
alert.show();
}
public static void showDialog1(Stage primaryStage, String message) {
alert = new JFXAlert(primaryStage);
alert.initModality(Modality.APPLICATION_MODAL);
alert.setOverlayClose(false);
JFXDialogLayout layout = new JFXDialogLayout();
VBox vBox = new VBox();
ProgressBar progressBar = new ProgressBar();
vBox.getChildren().add(progressBar);
vBox.setAlignment(Pos.CENTER);
vBox.getChildren().add(new Label(message));
layout.setBody(vBox);
alert.setContent(layout);
alert.show();
}
public static void dismissDialog() {
if (alert != null) {
alert.hide();
}
}
}
2、HttpCallBack 及,网络请求 HttpUtil
package sample.utils;
public interface HttpCallBack {
void success(String success);
void fail(String fail);
}
/
package sample.utils;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.omg.Messaging.SYNC_WITH_TRANSPORT;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class HttpUtil {
private static String PrefixURL ="http://localhost:9000";
public static String uri_login = "/login";
private final OkHttpClient mOkHttpClient;
private volatile static HttpUtil INSTANCE;
private Interceptor netCacheInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
HttpUrl httpUrl = request.url().newBuilder().build();
Request build;
System.out.println("请求地址》》" + httpUrl.url());
if (!StringUtil.isEmpty(session)) {
build = request.newBuilder()
// add common header
.addHeader("contentType", "application/json; charset=utf-8").addHeader("cookie", session)
.url(httpUrl).build();
} else {
build = request.newBuilder()
// add common header
.addHeader("contentType", "application/json; charset=utf-8").url(httpUrl).build();
}
Response response = chain.proceed(build);
return response;
}
};
public HttpUtil() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
// 设置超时
builder.connectTimeout(60, TimeUnit.SECONDS);
builder.readTimeout(60, TimeUnit.SECONDS);
builder.writeTimeout(60, TimeUnit.SECONDS);
// 错误重连
// builder.retryOnConnectionFailure(true);
//设置拦截器
// builder.addInterceptor(netCacheInterceptor);
mOkHttpClient = builder.build();
}
//单例
public static HttpUtil getInstance() {
if (INSTANCE == null) {
synchronized (HttpUtil.class) {
if (INSTANCE == null) {
INSTANCE = new HttpUtil();
}
}
}
return INSTANCE;
}
/**
get请求
*/
public void get(String uri, HttpCallBack callBack) {
Request request = new Request.Builder().addHeader("Content-Type", "application/json; charset=utf-8")
.url(PrefixURL + uri).get().build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callBack.fail("请求失败");
}
@Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
boolean successful = response.isSuccessful();
String success = response.body().string(); //返回结果
if (successful) {
callBack.success(success);
} else {
callBack.fail("请求失败");
}
}
});
}
private String session; //请求的session
public void post(Map<String, String> map, String uri, HttpCallBack callBack) {
FormBody.Builder builder = new FormBody.Builder();
for (String in : map.keySet()) {
builder.add(in, map.get(in));
}
RequestBody body = builder.build();
Request.Builder builder1 = new Request.Builder();
builder1.addHeader("Content-Type", "application/json; charset=utf-8");
if (!StringUtil.isEmpty(session)) {
builder1.addHeader("cookie", session);
}
Request request = builder1.url(PrefixURL + uri).post(body).build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println("请求失败");
callBack.fail("请求失败");
}
@Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
Headers headers = response.headers();
List<String> cookies = headers.values("Set-Cookie");
if (cookies.size() > 0) {
String s = cookies.get(0);
session = s.substring(0, s.indexOf(";")); //取到session 用户下次请求 无session不影响
System.out.println("session>>>" + session);
}
boolean successful = response.isSuccessful();
String success = response.body().string();
// System.out.println("请求结果>>>"+success);
if (successful) {
callBack.success(success);
} else {
callBack.fail("请求失败");
}
}
});
}
/**
* 带token请求
*/
public void postToken(Map<String, String> map, String uri, HttpCallBack callBack, String token) {
FormBody.Builder builder = new FormBody.Builder();
for (String in : map.keySet()) {
builder.add(in, map.get(in));
}
RequestBody body = builder.build();
Request request = new Request.Builder().addHeader("Content-Type", "application/json; charset=utf-8")
.addHeader("Authorization", "Bearer " + token).url(PrefixURL + uri).post(body).build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callBack.fail("请求失败");
}
@Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
boolean successful = response.isSuccessful();
String success = response.body().string();
if (successful) {
callBack.success(success);
} else {
callBack.fail("请求失败");
}
}
});
}
private String BASE_PIC_URL = "http://localhost:8888";
//上传文件
public void uploadFile(Map<String, String> map, File[] files, String uri, HttpCallBack callBack) {
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
builder.addFormDataPart("参数1", map.get("参数1"));
builder.addFormDataPart("参数2", map.get("参数2"));
for (int i = 0; i < files.length; i++) {
File file = files[i];
System.out.println("file>>" + file.getPath());
int num = file.getName().indexOf(".");
RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpeg"), file);// 将file转换成RequestBody文件
// 这里以MP4视频为例
builder.addFormDataPart("photos[" + file.getName().substring(0, num) + "]", file.getName().toLowerCase(), fileBody);
}
MultipartBody requestBody = builder.build();
Request request = new Request.Builder().url(BASE_PIC_URL + uri).post(requestBody).build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println("上传图片》》失败");
callBack.fail("上传失败");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
boolean successful = response.isSuccessful();
String success = response.body().string();
System.out.println("上传图片》》success》》" + success);
if (successful) {
callBack.success(success);
} else {
callBack.fail("上传失败");
}
}
});
}
/**
请求体 json传参
**/
public void postJson(JSONObject jsonObject, String uri, HttpCallBack callBack) {
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, String.valueOf(jsonObject));
Request.Builder builder1 = new Request.Builder();
builder1.addHeader("Content-Type", "application/json; charset=utf-8");
if (!StringUtil.isEmpty(session)) {
builder1.addHeader("cookie", session);
}
Request request = builder1.url(PrefixURL + uri).post(body).build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println("请求失败");
callBack.fail("请求失败");
}
@Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
Headers headers = response.headers();
List<String> cookies = headers.values("Set-Cookie");
if (cookies.size() > 0) {
String s = cookies.get(0);
session = s.substring(0, s.indexOf(";"));
System.out.println("session>>>" + session);
}
boolean successful = response.isSuccessful();
String success = response.body().string();
// System.out.println("请求结果>>>"+success);
if (successful) {
callBack.success(success);
} else {
callBack.fail("请求失败");
}
}
});
}
}
3、MD5Util
package sample.utils;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
public static String getMD5Str(String str) {
byte[] digest = null;
try {
MessageDigest md5 = MessageDigest.getInstance("md5");
digest = md5.digest(str.getBytes("utf-8"));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 16是表示转换为16进制数
String md5Str = new BigInteger(1, digest).toString(16);
return md5Str;
}
}
4、StringUtil
package sample.utils;
public class StringUtil {
public static boolean isEmpty(String str) {
return str == null || str.length() == 0 || str.trim() == "";
}
}
5、ToastUtil 貌似是从哪copy的
package sample.utils;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import java.util.Timer;
import java.util.TimerTask;
/*
*@author unclezs.com
*@date 2019.07.06 12:46
*/
public class ToastUtil {
private static Stage stage = new Stage();
private static Label label = new Label();
static {
stage.initStyle(StageStyle.TRANSPARENT);// 舞台透明
}
// 默认3秒
public static void toast(String msg) {
toast(msg, 3000);
}
/**
* 指定时间消失
*
* @param msg
* @param time
*/
public static void toast(String msg, int time) {
label.setText(msg);
TimerTask task = new TimerTask() {
@Override
public void run() {
Platform.runLater(() -> stage.close());
}
};
init(msg);
Timer timer = new Timer();
timer.schedule(task, time);
stage.show();
}
// 设置消息
private static void init(String msg) {
Label label = new Label(msg);// 默认信息
label.setStyle("-fx-background: rgba(56,56,56,0.7);-fx-border-radius: 25;-fx-background-radius: 25");// label透明,圆角
label.setTextFill(Color.rgb(225, 255, 226));// 消息字体颜色
label.setPrefHeight(50);
label.setPadding(new Insets(15));
label.setAlignment(Pos.CENTER);// 居中
label.setFont(new Font(20));// 字体大小
Scene scene = new Scene(label);
scene.setFill(null);// 场景透明
stage.setScene(scene);
}
}
图片压缩库
thumbnailator-0.4.8.jar
// outPath 输入路径文件夹
//File[] files 要压缩的图片文件列表
Thumbnails.of(files)
.scale(1f)
.outputQuality(0.8f)
.toFiles(new File(outPath),Rename.NO_CHANGE);