用javafx做的简易密码生成器

最近了解到javafx这个比较新的技术。用javafx做的应用可以很轻松地实现MVC设计,界面可以用css美化,原生支持界面特效,scene builder也比windowbuilder更加友好。

大概看了看教程,我就试着做了个简单的密码生成器。用惯了swing后用javafx感觉不太顺手,好在这种模式跟xcode很接近,所以上手并不难,很快就实现了预想的功能。
不过javafx仍然有硬伤:内存占用过大。这也是java程序的通病。即使使用Lambdas表达式代替抽象类处理事件也不能节省内存使用。

下载地址:


PasswordGenerator.jar

源代码:


Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package passwordgenerator;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("mainframe.fxml"));
primaryStage.setTitle("Simple Password Generator");
primaryStage.setScene(new Scene(root, 800, 300));
primaryStage.show();
}
}

Controller.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package passwordgenerator;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.util.Random;
public class Controller {
private final String capitalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private final String lowercaseChars = "abcdefghijklmnopqrstuvwxyz";
private final String numberChars = "0123456789";
@FXML
private CheckBox capital;
@FXML
private CheckBox lowercase;
@FXML
private CheckBox number;
@FXML
private CheckBox others;
@FXML
private CheckBox mustInclude;
@FXML
private TextField custom;
@FXML
private TextArea result;
@FXML
private Spinner<Integer> length;
private String selectedChars;
private String resultStr, charsStr;
private Random random = new Random();
private boolean noSelection;
private Alert alert;
private int len;
@FXML
private void initialize() {
length.setValueFactory(new ValueFactory());
length.getEditor().setOnKeyTyped(event ->
length.getValueFactory().setValue(Integer.parseInt(length.getEditor().getText()))
);
}
@FXML
private void clipboard() {
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable trans = new StringSelection(result.getText());
clip.setContents(trans, null);
}
@FXML
private void generate() {
selectedChars = "";
noSelection = true;
if (capital.isSelected()) {
selectedChars += capitalChars;
noSelection = false;
}
if (lowercase.isSelected()) {
selectedChars += lowercaseChars;
noSelection = false;
}
if (number.isSelected()) {
selectedChars += numberChars;
noSelection = false;
}
if (others.isSelected()) {
if (custom.getText().length() == 0) {
alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Warning");
alert.setHeaderText("You selected \"Others\" but no character is found in the box.");
alert.showAndWait();
return;
}
selectedChars += custom.getText();
noSelection = false;
}
if (noSelection) {
alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Warning");
alert.setHeaderText("You didn't selected any of the categories");
alert.showAndWait();
return;
}
resultStr = "";
charsStr = "";
len = length.getValue();
if (mustInclude.isSelected()) {
if (capital.isSelected()) {
charsStr += capitalChars.charAt(random.nextInt(26));
len--;
}
if (lowercase.isSelected()) {
charsStr += lowercaseChars.charAt(random.nextInt(26));
len--;
}
if (number.isSelected()) {
charsStr += numberChars.charAt(random.nextInt(10));
len--;
}
if (others.isSelected()) {
charsStr += custom.getText().charAt(random.nextInt(custom.getText().length()));
len--;
}
}
for (int i = 1; i <= len; i++) {
charsStr += selectedChars.charAt(random.nextInt(selectedChars.length()));
}
int i;
//System.out.println("Original:" + charsStr);
while (charsStr.length() > 0) {
i = random.nextInt(charsStr.length());
resultStr += charsStr.charAt(i);
//System.out.println("Delete char at " + i);
try {
charsStr = charsStr.substring(0, i) + charsStr.substring(i + 1);
} catch (StringIndexOutOfBoundsException e) {
try {
charsStr = charsStr.substring(0, i);
} catch (StringIndexOutOfBoundsException ee) {
try {
charsStr = charsStr.substring(i + 1);
} catch (StringIndexOutOfBoundsException eee) {
break;
}
}
}
//System.out.println("Result:" + charsStr);
}
result.setText(resultStr);
}
class ValueFactory extends SpinnerValueFactory<Integer> {
public ValueFactory() {
super();
setValue(12);
}
@Override
public void decrement(int steps) {
if (getValue() - steps > 0) {
setValue(getValue() - steps);
}
}
@Override
public void increment(int steps) {
setValue(getValue() + steps);
}
}
}

mainframe.fxml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.effect.Blend?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<BorderPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.102"
fx:controller="passwordgenerator.Controller">
<top>
<VBox BorderPane.alignment="CENTER">
<children>
<Separator orientation="VERTICAL" prefHeight="5.0"/>
<HBox alignment="CENTER_LEFT">
<children>
<CheckBox fx:id="capital" mnemonicParsing="false" selected="true" text="Capital Letters(A..Z)"/>
<Separator prefWidth="5.0"/>
<CheckBox fx:id="lowercase" mnemonicParsing="false" selected="true"
text="Lowercase Letters(a..z)"/>
<Separator layoutX="178.0" layoutY="19.0" prefWidth="5.0"/>
<CheckBox fx:id="number" mnemonicParsing="false" selected="true" text="Numbers(0..9)"/>
</children>
</HBox>
<Separator orientation="VERTICAL" prefHeight="5.0"/>
<HBox alignment="CENTER_LEFT">
<children>
<CheckBox fx:id="others" mnemonicParsing="false" text="Others: "/>
<TextField fx:id="custom" text=",.-=_*@$#%^&amp;()~"/>
<Separator prefWidth="5.0"/>
<CheckBox fx:id="mustInclude" mnemonicParsing="false" text="Must Include Selected Categories">
<font>
<Font name="System Bold" size="15.0"/>
</font>
</CheckBox>
</children>
</HBox>
</children>
</VBox>
</top>
<bottom>
<GridPane BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
<children>
<Label text="Length: ">
<font>
<Font size="20.0"/>
</font>
</Label>
<Spinner fx:id="length" editable="true"/>
</children>
</HBox>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<Button mnemonicParsing="false" onAction="#generate" text="Generate"/>
<Separator prefWidth="5.0"/>
<Button mnemonicParsing="false" onAction="#clipboard" text="Copy"/>
</children>
</HBox>
</children>
</GridPane>
</bottom>
<center>
<TextArea fx:id="result" wrapText="true" BorderPane.alignment="CENTER"/>
</center>
<effect>
<Blend mode="MULTIPLY"/>
</effect>
</BorderPane>

文章目录
  1. 1. 下载地址:
  2. 2. 源代码:
|