以前接触java感觉其在桌面开发上,总是不太方便,没有一个好的拖拽界面布局工具,可以快速构建窗体. 最近学习了一下NetBeans IDE 8.1,感觉其窗体设计工具还是很不错的 , 就尝试一下做了一个窗体应用程序. 总体下来,感觉和winform开发相差也不大,只是一些具体的设置或者语法有些差异,可以通过查阅相关资料进行掌握:
1 应用结构
新建一个java应用程序JavaApp,并创建相关的包及文件,其中简单实现了一个登录界面(JDBC 访问MYSQL数据库),登录成功后跳转到主界面.在主界面上单击菜单,可以打开子窗体.java swing自带的JTabbedPane没有显示关闭按钮的功能,这里在com.mkmis.controls包下自定义了一个TabbedPane控件,可以实现带关闭按钮的页签面板.应用结构如下图所示:
2 登陆界面设计
在IDE中新建一个Login的JFrame窗体,单击[设计]视图,可以将组件面板中的相关控件拖放到界面上,和Vistual Studio的操作差别不大,就是界面显示效果较差,不及Vistual Studio.用户名文本框用的文本字段,密码框用的是口令字段控件.登录和退出按钮用的是按钮控件.
设计完成后,单击运行按钮,界面效果如下图所示:
3 相关属性设置
Java Swing的很多属性设置用的方法,而NET用的属性.例如设置窗体标题,java swing用的是setTitle().另外窗体居中用的是setLocationRelativeTo(getOwner()). 获取文本框的值为getText()方法,如下代码所示:
1 public Login() {
2 initComponents();
3 setTitle("登录");
4 setDefaultCloseOperation(EXIT_ON_CLOSE);
5 setVisible(true);
6 setResizable(false);
7 setLocationRelativeTo(getOwner()); //居中显示
8
9 }
1 private void btnLoginActionPerformed(java.awt.event.ActionEvent evt) {
2 // TODO add your handling code here:
3 if(this.txtUserName.getText()!="" && this.txtPWD.getText().toString()!="")
4 {
5 Connection conn = DBConnection.getConnection();
6 PreparedStatement ps = null;
7 ResultSet rs = null;
8 try {
9 ps = conn.prepareStatement(
"select * from users where UserName = ? and password = ?");
10 ps.setString(1,this.txtUserName.getText());//
11 ps.setString(2, this.txtPWD.getText());
12 rs = ps.executeQuery();
13 while (rs.next()) {
14 User user = new User();
15 user.setId(rs.getInt("id"));
16 user.setUsername(rs.getString("UserName"));
17 user.setPassword(rs.getString("password"));
18
19 System.out.println(user.toString());
20 //跳转页面
21 FrameMain frm=new FrameMain(user.getUsername());
22 frm.setVisible(true);
23 this.dispose();//关闭当前窗体
24
25 }
26 } catch (SQLException e) {
27 e.printStackTrace();
28 } finally {
29 DBConnection.closeResultSet(rs);
30 DBConnection.closeStatement(ps);
31 DBConnection.closeConnection(conn);
32 }
33
34 }
35 }
显示一个窗体是设置其setVisiable(true);关闭一个窗体用的dispose();在登录界面想着输完用户名和密码后,按enter键可以自动登录,在网上搜下,发现了一个变通的方法,就是监听密码框的keypressed事件,当然需要验证一下用户名和密码是否为空(此处未加验证!),如下代码所示:
1 private void txtPWDKeyPressed(java.awt.event.KeyEvent evt) {
2 // TODO add your handling code here:
3 if(evt.getKeyCode()==KeyEvent.VK_ENTER)
4 {
5 //调用登录事件
6 btnLoginActionPerformed(null);
7
8 }
9 }
4 主界面
登录成功后,单击左边的树叶节点,通过反射动态实例化窗体(实际上菜单应该从数据库加载)并显示,主界面如下:
图表控件用的是JFreeChart控件,默认显示中文有乱码情况,需要设置显示中文处的字体进行解决.另外设置主界面显示最大化的代码为this.setExtendedState(this.getExtendedState()|JFrame.MAXMIZED_BOTH).为了让某个控件可以随着窗体大小变化而自动调整,需要设置其水平和垂直自动调整.
1 public FrameMain(){
2 initComponents();
3 setLocationRelativeTo(getOwner()); //居中显示
4 this.setExtendedState(this.getExtendedState()|JFrame.MAXIMIZED_BOTH );
//最大化 window
5 LoadTree();
6
7 }
8 public FrameMain(String uname){
9 initComponents();
10 setLocationRelativeTo(getOwner()); //居中显示
11 this.setExtendedState(this.getExtendedState()|JFrame.MAXIMIZED_BOTH );
12 LoadTree();
13 this.lblUser.setText("欢迎 "+uname+ " 登录!");
14
15 }
主界面在初始化时,调用LoadTree方法来填充左边的菜单树,如下所示:
1 private void LoadTree()
2 {
3 //自定义控件,支持关闭按钮
4 jTabbedPane1.setCloseButtonEnabled(true);
5
6 DefaultMutableTreeNode node1 = new DefaultMutableTreeNode("软件部");
7 node1.add(new DefaultMutableTreeNode("产品部"));
8 node1.add(new DefaultMutableTreeNode("测试部"));
9 node1.add(new DefaultMutableTreeNode("设计部"));
10
11 DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("销售部");
12 node2.add(new DefaultMutableTreeNode("jack"));
13 node2.add(new DefaultMutableTreeNode("Lily"));
14 node2.add(new DefaultMutableTreeNode("Smith"));
15
16 DefaultMutableTreeNode top = new DefaultMutableTreeNode("职员管理");
17
18
19 top.add(new DefaultMutableTreeNode("总经理"));
20 top.add(node1);
21 top.add(node2);
22
23 //JTree tree=new JTree(top);
24 DefaultTreeModel model = new DefaultTreeModel (top);
25 this.jTree1.setModel(model);
26 //jTree1.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION)
27 //set jframe icon
28 try
29
30 {
31 Image icon= ImageIO.read(this.getClass().getResource("/images/Icon.png"));
32 tabIcon = createImageIcon("/images/Icon.png", "tab icon");
33
34 this.setIconImage(icon);
35 }
36 catch(IOException ex)
37 {
38
39 System.out.println(ex);
40
41 }
42
43 }
在Tree的值变化事件中,通过class.forName()和 cls.newInstance()反射动态实例化窗体,代码如下:
1 private void jTree1ValueChanged(javax.swing.event.TreeSelectionEvent evt) {
2 // TODO add your handling code here:
3
4 DefaultMutableTreeNode node = (DefaultMutableTreeNode)
jTree1.getLastSelectedPathComponent();
5
6 if (node == null){
7 //Nothing is selected.
8 return;
9 }
10
11 Object nodeInfo = node.getUserObject();
12 String item = (String) nodeInfo;
13
14 if (node.isLeaf()) {
15 String item1 = (String) nodeInfo;
16 // this.setTitle(item1);
17 //File f = new File("client.jar");
18 //URLClassLoader cl = new URLClassLoader(new URL[]{f.toURI().toURL(), null});
19 //Class<?> clazz = cl.loadClass("epicurus.Client");
20 //Method main = clazz.getMethod("main", String[].class);
21 //main.invoke(null, new Object[]{new String[]{}});
22 try {
23 Class cls = Class.forName("com.mkmis.forms.JIFrame1");
24 javax.swing.JInternalFrame frm =
(javax.swing.JInternalFrame) cls.newInstance();
25 frm.setVisible(true);
26
27 //jTabbedPane1.addTab(" "+item1+" ",null,frm);
28 jTabbedPane1.addTab(" "+item1+" ",this.tabIcon,frm);
29
30 }
31 catch (Throwable e) {
32 System.err.println(e);
33 }
34 } else {
35 System.out.println("not leaf");
36 }
37 }
在javaswing中的路径也和net不同,下面定义了一个创建ImageIcon的方法:
1 /** Returns an ImageIcon, or null if the path was invalid. */
2 protected ImageIcon createImageIcon(String path,String description) {
3 java.net.URL imgURL = getClass().getResource(path);
4 if (imgURL != null) {
5 return new ImageIcon(imgURL, description);
6 } else {
7 System.err.println("Couldn't find file: " + path);
8 return null;
9 }
10 }
5 JDBC MYSQL代码
1 package com.mkmis.db;
2
3 import java.io.FileInputStream;
4 import java.io.IOException;
5 import java.sql.Connection;
6 import java.sql.DriverManager;
7 import java.sql.PreparedStatement;
8 import java.sql.ResultSet;
9 import java.sql.SQLException;
10 import java.sql.Statement;
11 import java.util.Properties;
12
13
14 public class DBConnection {
15
16 public static Connection getConnection() {
17 Properties props = new Properties();
18 FileInputStream fis = null;
19 Connection con = null;
20 try {
21 fis = new FileInputStream("db.properties");
22 props.load(fis);
23 //
24 Class.forName(props.getProperty("DB_DRIVER_CLASS"));
25 //
26 con = DriverManager.getConnection(props.getProperty("DB_URL"), props.getProperty("DB_USERNAME"), props.getProperty("DB_PASSWORD"));
27 } catch (IOException | SQLException | ClassNotFoundException e) {
28 e.printStackTrace();
29 }
30 return con;
31 }
32
33 // �ر�ResultSet
34 public static void closeResultSet(ResultSet rs) {
35 if (rs != null) {
36 try {
37 rs.close();
38 rs = null;
39 } catch (SQLException e) {
40 e.printStackTrace();
41 }
42 }
43 }
44
45 //Statement
46 public static void closeStatement(Statement stm) {
47 if (stm != null) {
48 try {
49 stm.close();
50 stm = null;
51 } catch (SQLException e) {
52 e.printStackTrace();
53 }
54 }
55 }
56
57 //PreparedStatement
58 public static void closePreparedStatement(PreparedStatement pstm) {
59 if (pstm != null) {
60 try {
61 pstm.close();
62 pstm = null;
63 } catch (SQLException e) {
64 e.printStackTrace();
65 }
66 }
67 }
68
69 //Connection
70 public static void closeConnection(Connection con) {
71 if (con != null) {
72 try {
73 con.close();
74 con = null;
75 } catch (SQLException e) {
76 e.printStackTrace();
77 }
78 con = null;
79 }
80 }
81
82 }
View Code
1 /*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6 package com.mkmis.forms;
7
8 import java.awt.Color;
9 import java.awt.Dimension;
10 import java.awt.Font;
11
12 import org.jfree.chart.ChartFactory;
13 import org.jfree.chart.ChartPanel;
14 import org.jfree.chart.JFreeChart;
15 import org.jfree.chart.StandardChartTheme;
16 import org.jfree.chart.axis.CategoryAxis;
17 import org.jfree.chart.axis.NumberAxis;
18 import org.jfree.chart.block.BlockBorder;
19 import org.jfree.chart.plot.CategoryPlot;
20 import org.jfree.chart.renderer.category.BarRenderer;
21 import org.jfree.chart.title.TextTitle;
22 import org.jfree.data.category.CategoryDataset;
23 import org.jfree.data.category.DefaultCategoryDataset;
24 //import org.jfree.ui.ApplicationFrame;
25 //import org.jfree.ui.RefineryUtilities;
26 /**
27 *
28 * @author wangming
29 */
30 public class JIFrame1 extends javax.swing.JInternalFrame {
31
32 /**
33 * Creates new form JIFrame1
34 */
35 public JIFrame1() {
36 initComponents();
37 //hiding title bar of JInternalFrame
38 ((javax.swing.plaf.basic.BasicInternalFrameUI)this.getUI()).setNorthPane(null);
39 this.setBackground(Color.white);
40
41 CategoryDataset dataset = createDataset();
42 JFreeChart chart = createChart(dataset);
43 ChartPanel chartPanel = new ChartPanel(chart);
44 chartPanel.setFillZoomRectangle(true);
45 chartPanel.setMouseWheelEnabled(true);
46 chartPanel.setPreferredSize(new Dimension(500, 270));
47 setContentPane(chartPanel);
48 }
49
50 /**
51 * This method is called from within the constructor to initialize the form.
52 * WARNING: Do NOT modify this code. The content of this method is always
53 * regenerated by the Form Editor.
54 */
55 @SuppressWarnings("unchecked")
56 // <editor-fold defaultstate="collapsed" desc="Generated Code">
57 private void initComponents() {
58
59 setBorder(null);
60 setClosable(true);
61 setMaximizable(true);
62 setResizable(true);
63
64 javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
65 getContentPane().setLayout(layout);
66 layout.setHorizontalGroup(
67 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
68 .addGap(0, 410, Short.MAX_VALUE)
69 );
70 layout.setVerticalGroup(
71 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
72 .addGap(0, 285, Short.MAX_VALUE)
73 );
74
75 pack();
76 }// </editor-fold>
77
78 private static final long serialVersionUID = 1L;
79
80 static {
81 // set a theme using the new shadow generator feature available in
82 // 1.0.14 - for backwards compatibility it is not enabled by default
83 ChartFactory.setChartTheme(new StandardChartTheme("JFree/Shadow",
84 true));
85 }
86
87 /**
88 * Creates a new demo instance.
89 *
90 * @param title the frame title.
91 */
92 public JIFrame1(String title) {
93 super(title);
94 CategoryDataset dataset = createDataset();
95 JFreeChart chart = createChart(dataset);
96 ChartPanel chartPanel = new ChartPanel(chart);
97 chartPanel.setFillZoomRectangle(true);
98 chartPanel.setMouseWheelEnabled(true);
99 chartPanel.setPreferredSize(new Dimension(500, 270));
100 setContentPane(chartPanel);
101 }
102
103 /**
104 * Returns a sample dataset.
105 *
106 * @return The dataset.
107 */
108 private static CategoryDataset createDataset() {
109 DefaultCategoryDataset dataset = new DefaultCategoryDataset();
110 dataset.addValue(7445, "JFreeSVG", "Warm-up");
111 dataset.addValue(24448, "Batik", "Warm-up");
112 dataset.addValue(4297, "JFreeSVG", "Test");
113 dataset.addValue(21022, "Batik", "Test");
114 return dataset;
115 }
116
117 /**
118 * Creates a sample chart.
119 *
120 * @param dataset the dataset.
121 *
122 * @return The chart.
123 */
124 private static JFreeChart createChart(CategoryDataset dataset) {
125 //中文乱码,设置字体
126 Font font=new Font("微软雅黑",Font.BOLD,18);//测试是可以的
127
128
129
130
131 JFreeChart chart = ChartFactory.createBarChart("性能: JFreeSVG 对比 Batik", null /* x-axis label*/,
132 "毫秒" /* y-axis label */, dataset);
133 //中文乱码,设置字体
134 chart.getTitle().setFont(font);
135
136 chart.addSubtitle(new TextTitle("在SVG中产生1000个图表"));
137 chart.setBackgroundPaint(Color.white);
138 CategoryPlot plot = (CategoryPlot) chart.getPlot();
139 NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
140 rangeAxis.setLabelFont(font);
141
142 CategoryAxis domainAxis = plot.getDomainAxis();
143 domainAxis.setLabelFont(font);
144 // ******************************************************************
145 // More than 150 demo applications are included with the JFreeChart
146 // Developer Guide...for more information, see:
147 //
148 // > http://www.object-refinery.com/jfreechart/guide.html
149 //
150 // ******************************************************************
151
152
153 rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
154 BarRenderer renderer = (BarRenderer) plot.getRenderer();
155 renderer.setDrawBarOutline(false);
156 chart.getLegend().setFrame(BlockBorder.NONE);
157 return chart;
158 }
159
160 /**
161 * Starting point for the demonstration application.
162 *
163 * @param args ignored.
164 */
165 // public static void main(String[] args) {
166 // BarChartDemo1 demo = new BarChartDemo1("JFreeChart: BarChartDemo1.java");
167 // demo.pack();
168 // RefineryUtilities.centerFrameOnScreen(demo);
169 // demo.setVisible(true);
170 // }
171
172 // Variables declaration - do not modify
173 // End of variables declaration
174 }
View Code
运行此app,一定要引入需要的库,mysql jdbc驱动和jfreechart库