以前接触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 publicLogin() {2 initComponents();3 setTitle("登录");4 setDefaultCloseOperation(EXIT_ON_CLOSE);5 setVisible(true);6 setResizable(false);7 setLocationRelativeTo(getOwner()); //居中显示
8
9 }
1 private voidbtnLoginActionPerformed(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 = newUser();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=newFrameMain(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 voidtxtPWDKeyPressed(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 publicFrameMain(){2 initComponents();3 setLocationRelativeTo(getOwner()); //居中显示
4 this.setExtendedState(this.getExtendedState()|JFrame.MAXIMIZED_BOTH );
//最大化 window
5 LoadTree();6
7 }8 publicFrameMain(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 voidLoadTree()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 = newDefaultTreeModel (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 voidjTree1ValueChanged(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 protectedImageIcon createImageIcon(String path,String description) {3 java.net.URL imgURL =getClass().getResource(path);4 if (imgURL != null) {5 return newImageIcon(imgURL, description);6 } else{7 System.err.println("Couldn't find file: " +path);8 return null;9 }10 }
5 JDBC MYSQL代码
1 packagecom.mkmis.db;2
3 importjava.io.FileInputStream;4 importjava.io.IOException;5 importjava.sql.Connection;6 importjava.sql.DriverManager;7 importjava.sql.PreparedStatement;8 importjava.sql.ResultSet;9 importjava.sql.SQLException;10 importjava.sql.Statement;11 importjava.util.Properties;12
13
14 public classDBConnection {15
16 public staticConnection getConnection() {17 Properties props = newProperties();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 returncon;31 }32
33 //�ر�ResultSet
34 public static voidcloseResultSet(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 voidcloseStatement(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 voidclosePreparedStatement(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 voidcloseConnection(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
6 图表窗体代码
1 /*
2 * To change this license header, choose License Headers in Project Properties.3 * To change this template file, choose Tools | Templates4 * and open the template in the editor.5 */
6 packagecom.mkmis.forms;7
8 importjava.awt.Color;9 importjava.awt.Dimension;10 importjava.awt.Font;11
12 importorg.jfree.chart.ChartFactory;13 importorg.jfree.chart.ChartPanel;14 importorg.jfree.chart.JFreeChart;15 importorg.jfree.chart.StandardChartTheme;16 importorg.jfree.chart.axis.CategoryAxis;17 importorg.jfree.chart.axis.NumberAxis;18 importorg.jfree.chart.block.BlockBorder;19 importorg.jfree.chart.plot.CategoryPlot;20 importorg.jfree.chart.renderer.category.BarRenderer;21 importorg.jfree.chart.title.TextTitle;22 importorg.jfree.data.category.CategoryDataset;23 importorg.jfree.data.category.DefaultCategoryDataset;24 //import org.jfree.ui.ApplicationFrame;25 //import org.jfree.ui.RefineryUtilities;
26 /**
27 *28 *@authorwangming29 */
30 public class JIFrame1 extendsjavax.swing.JInternalFrame {31
32 /**
33 * Creates new form JIFrame134 */
35 publicJIFrame1() {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 = newChartPanel(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 always53 * regenerated by the Form Editor.54 */
55 @SuppressWarnings("unchecked")56 //
57 private voidinitComponents() {58
59 setBorder(null);60 setClosable(true);61 setMaximizable(true);62 setResizable(true);63
64 javax.swing.GroupLayout layout = newjavax.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 }//
77
78 private static final long serialVersionUID = 1L;79
80 static{81 //set a theme using the new shadow generator feature available in82 //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 *@paramtitle the frame title.91 */
92 publicJIFrame1(String title) {93 super(title);94 CategoryDataset dataset =createDataset();95 JFreeChart chart =createChart(dataset);96 ChartPanel chartPanel = newChartPanel(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 *@returnThe dataset.107 */
108 private staticCategoryDataset createDataset() {109 DefaultCategoryDataset dataset = newDefaultCategoryDataset();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 returndataset;115 }116
117 /**
118 * Creates a sample chart.119 *120 *@paramdataset the dataset.121 *122 *@returnThe chart.123 */
124 private staticJFreeChart 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 JFreeChart146 //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 returnchart;158 }159
160 /**
161 * Starting point for the demonstration application.162 *163 *@paramargs 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 modify173 //End of variables declaration
174 }
View Code
运行此app,一定要引入需要的库,mysql jdbc驱动和jfreechart库