JAVA簡易人員管理視窗程式(未完成)
這是職訓初期製作的Swing桌面程式,只用了MVC架構中Model跟View的概念,Controller還沒拆出來。

另外刪除跟查詢的功能尚未完成。
他的初版-單純的新增人員視窗程式 製作過程
前情提要
這是上Java課的第二個課堂作業(第一個是用迴圈改變陣列印出來的格式)
要做出一個輸入的視窗,可以將輸入內容存入MySQL資料庫的表格中
要輸入的內容為姓名、年齡、信箱、電話、地址
以下使用的IDE為Eclipse
施作順序盤點與架構
有些說明比較籠統,可能需要搭配相關HackMD的課堂筆記進行閱讀,我會補充在文末
1.MySQL的部分
開一個資料庫叫做guiproject,新增一張表格(Table)叫user好了
user下方再開以下幾個欄位:(MySQL沒有大小寫之分)
- 關於下方幾個欄位標題的命名格式解釋
- e是指employee(員工)的意思,預設這是個員工資料的登錄視窗;e後方的英文就是我要新增的欄位
- eid
- 注意:設定為不得為null(NN),且自動新增(AI)
- ename
- 注意:設定為不得為null(NN)
- eage
- eemail
- ephone
- eadress
2.程式所需檔案樹狀目錄部分
- NewGuiProject:一個Java Project
- lib:放置mysql-connector-java-8.0.16.jar這個連接程式與資料庫工具的地方,在src下以一般folder開啟即可
- tw.personal.agatha.view:放置Jframe視窗程式檔案的package,針對package,後方的列點省略解說
- CountView.java:GUI視窗程式
- tw.personal.agatha.dbutils
- CountDB.java:設定程式與資料庫連接的檔案
- tw.personal.agatha.entity
- Employee.java:員工資料屬性設置區
施作細節
- mysql-connector-java-8.0.16.jar
- 只有複製貼進IDE中新增的lib目錄是不夠的,還得進行建構(按右鍵選Build Path中的第一個選項)
- Employee.java
public class Employee {
//第一步:設置五種資料的屬性
private int eid;
private String eName;
private String eAge;
private String eEmail;
private String ePhone;
private String eAdress;
//第二步:set & get
public int getEid() {
return eid;
}
public void setEid(int eid) {
this.eid = eid;
}
public String geteName() {
return eName;
}
public void seteName(String eName) {
this.eName = eName;
}
public String geteAge() {
return eAge;
}
public void seteAge(String eAge) {
this.eAge = eAge;
}
public String geteEmail() {
return eEmail;
}
public void seteEmail(String eEmail) {
this.eEmail = eEmail;
}
public String getePhone() {
return ePhone;
}
public void setePhone(String ePhone) {
this.ePhone = ePhone;
}
public String geteAdress() {
return eAdress;
}
public void seteAdress(String eAdress) {
this.eAdress = eAdress;
}
//第三步:toString
@Override
public String toString() {
return "Employee [eid=" + eid + ", eName=" + eName + ", eAge=" + eAge + ", eEmail=" + eEmail + ", ePhone="
+ ePhone + ", eAdress=" + eAdress + "]";
}
}
- CountDB.java
public class CountDB {
//第一步:設置常數,常數的命名規則為「全都大寫」
private static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; // 到JDBC的目錄下方查找Driver並複製過來(記得去掉class)
// 避免時區錯誤還有禁用SSL連線,加上?及後面的語句
private static final String JDBC_URL = "jdbc:mysql://localhost:3306/guiproject?serverTimezone=UTC&useSSL=false";
private static final String JDBC_NAME = "root";
private static final String JDBC_PASSWORD = "你的密碼"; // 這邊是輸入你的資料庫密碼,輸入錯誤會連線失敗
private static Connection conn = null;
//第二步之一:做一個靜態代碼塊建構子
static {
try {
Class.forName(JDBC_DRIVER);
System.out.println("連接成功"); // 測試用的,完成可以去掉
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//第二步之二:做一個靜態方法
public static Connection getConnection() {
try {
conn = DriverManager.getConnection(JDBC_URL, JDBC_NAME, JDBC_PASSWORD);
System.out.println("連接成功"); // 測試用的,完成可以去掉
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
//第三步:關閉的寫法
// PreparedStatement、Statement這些出現提示選有java.sql那個
// *.close();出現提示全選第2個
// 以下方法得是靜態的才能被同package下方的其他檔案使用
public static void close(Connection comm) { // 傳送Driver跟驗證帳密
if (comm != null) {
try {
comm.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void close(PreparedStatement ps) { // 傳送SQL語法(但能防止SQL注入攻擊)
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void close(Statement st) { // 傳送SQL語法
if (st != null) {
try {
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void close(ResultSet rs) { // 接受語法後搜尋的資料與存取
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- CountView.java
- 在Design工具中對視窗的外框上方點一下新增這個jar程式的標題吧(還可以加個icon)
- 如果要加入icon,記得在src新增一個一般folder放置圖片
- 設置透明度容易出現the frame is decorated java的錯誤提示無法預覽運行
- 在Design工具中畫出五個項目的文字方塊(作為提示)、輸入框跟送出按紐
- 記得對空無一物的內部點一下,修改Layout為(absolute),拖曳上去的物件才不會被固定版面給限制住
- 記得給每條輸入框設置自訂類別
- 對送出按鈕點兩下進行以下撰寫
- 在Design工具中對視窗的外框上方點一下新增這個jar程式的標題吧(還可以加個icon)
這是尚未開始寫將內容傳送到資料庫語法的時候的樣子:
這是整個寫完的樣子:
public class CountView extends JFrame {
private JPanel contentPane;
private JTextField input_eName;
private JTextField input_eAge;
private JTextField input_eEmail;
private JTextField input_ePhone;
private JTextField input_eAdress;
/**
* Launch the application.
*
* @return
*/
public static void main(String[] args) {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { // 我在main方法加入這個代碼,可以改變JFrame的外觀
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
CountView frame = new CountView();
frame.setVisible(true);
frame.setLocationRelativeTo(null); // 這是視窗預設居中的功能,看個人需求,不是一個必要過程
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public CountView() {
setResizable(false);
setFont(new Font("微軟正黑體", Font.PLAIN, 12));
setBackground(Color.WHITE);
setIconImage(Toolkit.getDefaultToolkit().getImage(CountView.class.getResource("/img/p.png")));
setTitle("新增人員");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 318, 232);
contentPane = new JPanel();
contentPane.setBackground(new Color(26, 53, 97));
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JLabel lblNewLabel = new JLabel("姓名");
lblNewLabel.setForeground(new Color(184, 196, 214)); // 這邊可以直接改色彩,工具預設的色彩太少了,可以用Google搜尋的Color Pikcer工具選顏色,再把RBG值填入此處
lblNewLabel.setFont(new Font("微軟正黑體", Font.BOLD, 12));
lblNewLabel.setBounds(22, 12, 109, 29);
contentPane.add(lblNewLabel);
JLabel lblNewLabel_1 = new JLabel("年齡");
lblNewLabel_1.setForeground(new Color(184, 196, 214));
lblNewLabel_1.setFont(new Font("微軟正黑體", Font.BOLD, 12));
lblNewLabel_1.setBounds(22, 48, 79, 29);
contentPane.add(lblNewLabel_1);
JLabel lblNewLabel_1_1 = new JLabel("信箱");
lblNewLabel_1_1.setForeground(new Color(184, 196, 214));
lblNewLabel_1_1.setFont(new Font("微軟正黑體", Font.BOLD, 12));
lblNewLabel_1_1.setBounds(22, 82, 79, 29);
contentPane.add(lblNewLabel_1_1);
JLabel lblNewLabel_1_1_1 = new JLabel("電話");
lblNewLabel_1_1_1.setForeground(new Color(184, 196, 214));
lblNewLabel_1_1_1.setFont(new Font("微軟正黑體", Font.BOLD, 12));
lblNewLabel_1_1_1.setBounds(22, 117, 79, 29);
contentPane.add(lblNewLabel_1_1_1);
JLabel lblNewLabel_1_1_1_1 = new JLabel("地址");
lblNewLabel_1_1_1_1.setForeground(new Color(184, 196, 214));
lblNewLabel_1_1_1_1.setFont(new Font("微軟正黑體", Font.BOLD, 12));
lblNewLabel_1_1_1_1.setBounds(22, 155, 79, 29);
contentPane.add(lblNewLabel_1_1_1_1);
input_eName = new JTextField();
input_eName.setForeground(new Color(63, 81, 112));
input_eName.setText("必填");
input_eName.setFont(new Font("微軟正黑體", Font.BOLD, 10));
input_eName.setBackground(new Color(232, 241, 255));
input_eName.setBounds(57, 15, 109, 22);
contentPane.add(input_eName);
input_eName.setColumns(10);
input_eAge = new JTextField();
input_eAge.setForeground(new Color(63, 81, 112));
input_eAge.setFont(new Font("微軟正黑體", Font.BOLD, 10));
input_eAge.setColumns(10);
input_eAge.setBackground(new Color(232, 241, 255));
input_eAge.setBounds(57, 51, 109, 22);
contentPane.add(input_eAge);
input_eEmail = new JTextField();
input_eEmail.setForeground(new Color(63, 81, 112));
input_eEmail.setFont(new Font("微軟正黑體", Font.BOLD, 10));
input_eEmail.setColumns(10);
input_eEmail.setBackground(new Color(232, 241, 255));
input_eEmail.setBounds(57, 85, 109, 22);
contentPane.add(input_eEmail);
input_ePhone = new JTextField();
input_ePhone.setForeground(new Color(63, 81, 112));
input_ePhone.setFont(new Font("微軟正黑體", Font.BOLD, 10));
input_ePhone.setColumns(10);
input_ePhone.setBackground(new Color(232, 241, 255));
input_ePhone.setBounds(57, 120, 109, 22);
contentPane.add(input_ePhone);
input_eAdress = new JTextField();
input_eAdress.setForeground(new Color(63, 81, 112));
input_eAdress.setFont(new Font("微軟正黑體", Font.BOLD, 10));
input_eAdress.setColumns(10);
input_eAdress.setBackground(new Color(232, 241, 255));
input_eAdress.setBounds(57, 158, 109, 22);
contentPane.add(input_eAdress);
JLabel lblNewLabel_2 = new JLabel("");
lblNewLabel_2.setIcon(new ImageIcon(CountView.class.getResource("/img/3060034.png")));
lblNewLabel_2.setBounds(188, 29, 90, 122);
contentPane.add(lblNewLabel_2);
JButton btnNewButton = new JButton("送出");
btnNewButton.setIcon(new ImageIcon(CountView.class.getResource("/img/shine.png")));
btnNewButton.setBackground(new Color(11, 32, 64));
btnNewButton.setFont(new Font("微軟正黑體", Font.BOLD, 12));
btnNewButton.setForeground(new Color(162, 215, 224));
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { // 主要步驟應該是從雙擊按鈕撰寫按紐細節開始,上面的程式碼主要是用Design功能完成後自動生成的(除了一些我為了美化所做的更動)
// 第一步:實體化,然後以輸入在框中的值set給Employee中出現之對應部分
Connection conn = null;
PreparedStatement ps = null;// 初始化這兩個值
Employee emp = new Employee();
emp.seteName(input_eName.getText());
emp.seteAge(input_eAge.getText());
emp.seteEmail(input_eEmail.getText());
emp.setePhone(input_ePhone.getText());
emp.seteAdress(input_eAdress.getText());
conn = CountDB.getConnection();// 呼叫寫在CountDB中的getConnection方法
String sql = "insert into user(eName,eAge,eEmail,ePhone,eAdress)values(?,?,?,?,?)";// 要傳輸的SQL指令
// 最後一步:連接資料庫並修飾上方程式碼
try {
ps = conn.prepareStatement(sql); // 這個打完編譯器會提示要不要做個try/catch,點下去變成下列形式了
ps.setString(1, emp.geteName());// 數字表示填入順序
ps.setString(2, emp.geteAge());
ps.setString(3, emp.geteEmail());
ps.setString(4, emp.getePhone());
ps.setString(5, emp.geteAdress());
// 第二步被移動到這裡了:做一個彈出視窗提示新增成功
int y = ps.executeUpdate();// 可寫可不寫
JOptionPane.showMessageDialog(null, "新增" + y + "筆資料成功");
} catch (SQLException e1) {
e1.printStackTrace();
} finally {// 不管如何必定會執行
CountDB.close(ps);
CountDB.close(conn);// 程式用完必須關閉資料庫
}
// 第三步移到最下方:把輸入的文字清空,才方便使用者新增下一筆
input_eName.setText("");
input_eAge.setText("");
input_eEmail.setText("");
input_ePhone.setText("");
input_eAdress.setText("");
}
});
btnNewButton.setBounds(184, 149, 94, 29);
contentPane.add(btnNewButton);
}
成品
過程中其他異常的事情
- 如果有跟我一樣加"連線成功"檢查是否連線成功,印出了3次,應該都是因為為static所以都被載入
- 如果有更動資料庫的表格內容,要按Apply再重新整理,才會看到後來丟進去的資料
涉及HackMD筆記
參考的其他技術文章
-
部分Win10電腦使用WindowBuilder時dpi顯示異常,導致編輯區跟實際程式比例不符的問題
- 可能的解決方法:用相容性-覆寫dpi的設置會使整個程式文字模糊,所以我採用這個討論中作者Tim Dowty的做法,到Eclipse根目錄點開Eclipse.ini,在-vmargs下方加入以下三行代碼:
-Dswt.enable.autoScale=true
-Dswt.autoScale=140 //原文的200會讓Swing JFrame製作工具預覽區變太大
-Dswt.autoScale.method=nearest
然而我旋即發現雖然Swing製作工具預覽區大小趨於實際jdk比例,但撰寫程式的地方卻破圖了,還變得容易當機
應該是我使用的主題跟這個設定有衝突,我後來還是將就使用讓系統覆寫dpi的方式,選擇系統(增強)會比較清晰一點,但有些按鈕會有消失的Bug
-
如何切換程式樣式風格
- 另外美化過程中不使用預設工具給的顏色,改成自己輸入感覺還是不夠的…但要做輸入框圓角化處理、改變視窗樣式等,由於建置工具老舊,方法會比較土炮一點,以上因為不是本次作業的重點(連接資料庫),所以暫時不深入
- 上圖可見我放入的素材圖片均呈鋸齒狀,疑似是我個人電腦的異常狀況,其他電腦不一定有這個現象。