巩固JavaSE基础--IDEA完成实战项目
PS:学习完JavaSE基础后,需要有一个项目来测试自己的学习成果,并加以巩固。所以在这里,就让我们来学习下“一本糊涂账”项目吧。(此项目来源于Java自学网站)
项目完成效果图一览
起始--新建项目
新建JavaEEApplication项目,并命名为“yc_hutubill”。并添加lib、classes、img文件夹。效果如下图:
并将classes文件夹作为编译后类的输出目录:
起始--表结构的设计
SQL语句:
#创建config表 use hutubill; CREATE TABLE config ( id int, key_ VARCHAR (255), value VARCHAR (255) )ENGINE=INNODB DEFAULT CHARSET=utf8; #创建消费分类表category create table category ( id int, name varchar(255) ) ENGINE=INNODB DEFAULT CHARSET=utf8; #创建消费记录表 create table record ( id int, spend int, cid int, comment varchar(255), date Date ) ENGINE=INNODB DEFAULT CHARSET=utf8; #加上主键约束 alter table category add constraint pk_category_id primary key (id); alter table record add constraint pk_record_id primary key (id); alter table config add constraint pk_config_id primary key (id); #设置id自动增长 alter table category change id id int auto_increment; alter table record change id id int auto_increment; alter table config change id id int auto_increment; #设置外键 alter table record add constraint fk_record_category foreign key (cid) references category(id);
旅途--原型设计
原型设计指的是,先把界面做出来,假面上的数据都是假数据,并不是从数据库里读出来的真实数据。之所以这么做,是因为,有了界面,才直观,我们对项目的规划才更有感觉,更重要的是,有了界面,才能更有效地个客户沟通,哪些功能需要修改,哪些功能可以删减。
居中面板
Swing并没有提供一种可以很简单就可以居中的布局器,但是这样的布局器又非常的常见,所以我们就需要开发一个居中面板的类:
package util; import gui.panel.WorkingPanel; import javax.swing.*; import java.awt.*; /** * @ClassName: CenterPanel * @Description:居中布局面板类 * @author: yunche * @date: 2018/07/19 */ public class CenterPanel extends JPanel { /** * 拉伸比例 */ private double rate; /** * 显示的组件 */ private JComponent c; /** * 是否拉伸 */ private boolean stretch; public CenterPanel(double rate, boolean stretch) { this.setLayout(null); this.rate = rate; this.stretch = stretch; } public CenterPanel(double rate) { this(rate, true); } @Override public void repaint() { if (null != c) { Dimension containerSize = this.getSize(); Dimension componentSize = c.getPreferredSize(); if (stretch) { c.setSize((int) (containerSize.width * rate), (int) (containerSize.height * rate)); } else { c.setSize(componentSize); } c.setLocation(containerSize.width / 2 - c.getSize().width / 2, containerSize.height / 2 - c.getSize().height / 2); } super.repaint(); } /** * 展示居中布局的面板 * @param p */ public void show(JComponent p) { this.c = p; Component[] cs = getComponents(); for (Component c : cs) { remove(c); } add(p); if (p instanceof WorkingPanel) { ((WorkingPanel) p).updateData(); } this.updateUI(); } }
里面涉及到的抽象类WorkingPanel,是用于提供面板的共性方法的,如注册监听器、更新数据等操作:
package gui.panel; import javax.swing.*; /** * @ClassName: WorkingPanel * @Description: 抽象类用于让子类重写必要的方法 * @author: yunche * @date: 2018/07/23 */ public abstract class WorkingPanel extends JPanel { /** * 更新数据 */ public abstract void updateData(); /** * 注册监听器 */ public abstract void addListener(); }
GUIUtil工具类
这个工具类可以帮助我们封装一些后面项目中会用到的常用的操作,代码如下:
package util; import javax.swing.*; import java.awt.*; import java.io.File; /** * @ClassName: GUIUtil * @Description: 专门处理图形界面的工具类 * @author: yunche * @date: 2018/07/19 */ public class GUIUtil { /** * 图片的文件夹路径 */ private static String imageFolder = "META-INF/img"; /** * 设置按钮的图标 * * @param b 按钮 * @param fileName 图标名 * @param tip 提示文本 */ public static void setImageIcon(JButton b, String fileName, String tip) { ImageIcon i = new ImageIcon(new File(imageFolder, fileName).getAbsolutePath()); b.setIcon(i); b.setPreferredSize(new Dimension(61, 81)); b.setToolTipText(tip); b.setVerticalTextPosition(JButton.BOTTOM); b.setHorizontalTextPosition(JButton.CENTER); b.setText(tip); } /** * 设置控件的前景色 * * @param color * @param cs */ public static void setColor(Color color, JComponent... cs) { for (JComponent c : cs) { c.setForeground(color); } } /** * 根据拉伸比例缩放展示面板 * * @param p 面板 * @param stretchRate 拉伸比例 */ public static void showPanel(JPanel p, double stretchRate) { GUIUtil.useLNF(); JFrame f = new JFrame(); f.setSize(500, 500); f.setLocationRelativeTo(null); CenterPanel cp = new CenterPanel(stretchRate); f.setContentPane(cp); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); cp.show(p); } public static void showPanel(JPanel p) { showPanel(p, 0.85); } /** * 检查文本输入是否是数字 * 若是数字,则通过检查返回true,否则返回false * * @param tf * @param input * @return */ public static boolean checkNumber(JTextField tf, String input) { if (!checkEmpty(tf, input)) { return false; } String text = tf.getText().trim(); try { Integer.parseInt(text); return true; } catch (NumberFormatException ne) { JOptionPane.showMessageDialog(null, input + " 需要是整数"); tf.grabFocus(); return false; } } /** * 检查文本框中的内容的是否为0 * 若为0,通不过检查返回false,不为0,通过检查返回true * * @param tf * @param input * @return */ public static boolean checkZero(JTextField tf, String input) { if (!checkNumber(tf, input)) { return false; } String text = tf.getText().trim(); if (0 == Integer.parseInt(text)) { JOptionPane.showMessageDialog(null, input + "不能为零"); tf.grabFocus(); return false; } return true; } /** * 检查是文本框的内容是否为空 * 若为空,则显示对话框,提示消息“不能为空” * 不为空,则返回true * * @param tf * @param input * @return */ public static boolean checkEmpty(JTextField tf, String input) { String text = tf.getText().trim(); if (0 == text.length()) { JOptionPane.showMessageDialog(null, input + "不能为空"); tf.grabFocus(); return false; } return true; } /** * 将文本转化为整型数字 * * @param tf * @return 转化后的整型数字 */ public static int getInt(JTextField tf) { return Integer.parseInt(tf.getText()); } /** * 使用水晶皮肤 */ public static void useLNF() { try { javax.swing.UIManager.setLookAndFeel("com.birosoft.liquid.LiquidLookAndFeel"); } catch (Exception e) { e.printStackTrace(); } } /** * 测试效果代码 * 去掉注释后可用 * @param args public static void main(String[] args) { GUIUtil.useLNF(); JPanel p = new JPanel(); p.add(new JButton("按钮1")); p.add(new JButton("按钮2")); GUIUtil.showPanel(p); } */ }
里面的用到的水晶皮肤需要导入liquidlnf.jar包,所有后面项目用到的jar包到放在网盘上,请对应下载(若有失效,请到Java自学网站上下载)。
ColorUtil工具类
package util; import java.awt.*; /** * @ClassName: ColorUtil * @Description: 颜色工具类 * @author: yunche * @date: 2018/07/20 */ public class ColorUtil { public static Color blueColor = Color.decode("#3399FF"); public static Color grayColor = Color.decode("#999999"); public static Color backgroundColor = Color.decode("#eeeeee"); public static Color warningColor = Color.decode("#FF3333"); /** * 根据进度条的百分比来改变颜色 * * @param per * @return */ public static Color getByPercentage(int per) { if (per > 100) { per = 100; } int r = 51; int g = 255; int b = 51; float rate = per / 100f; r = (int) ((255 - 51) * rate + 51); g = 255 - r + 51; Color color = new Color(r, g, b); return color; } }
CircleProgressBar
package util; import javax.swing.*; import java.awt.*; /** * @ClassName: CircleProgressBar * @Description: 消费一览圆形进度条 * @author: yunche * @date: 2018/07/20 */ public class CircleProgressBar extends JPanel { private int minimumProgress; private int maximumProgress; private int progress; private String progressText; private Color backgroundColor; private Color foregroundColor; public CircleProgressBar() { minimumProgress = 0; maximumProgress = 100; progressText = "0%"; } @Override public void paint(Graphics g) { super.paint(g); Graphics2D graphics2d = (Graphics2D) g; // 开启抗锯齿 graphics2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int x = 0; int y = 0; int width = 0; int height = 0; int fontSize = 0; if (getWidth() >= getHeight()) { x = (getWidth() - getHeight()) / 2 + 25; y = 25; width = getHeight() - 50; height = getHeight() - 50; fontSize = getWidth() / 8; } else { x = 25; y = (getHeight() - getWidth()) / 2 + 25; width = getWidth() - 50; height = getWidth() - 50; fontSize = getHeight() / 8; } graphics2d.setStroke(new BasicStroke(20.0f)); graphics2d.setColor(backgroundColor); graphics2d.drawArc(x, y, width, height, 0, 360); graphics2d.setColor(foregroundColor); graphics2d.drawArc(x, y, width, height, 90, -(int) (360 * ((progress * 1.0) / (maximumProgress - minimumProgress)))); graphics2d.setFont(new Font("黑体", Font.BOLD, fontSize)); FontMetrics fontMetrics = graphics2d.getFontMetrics(); int digitalWidth = fontMetrics.stringWidth(progressText); int digitalAscent = fontMetrics.getAscent(); graphics2d.setColor(foregroundColor); graphics2d.drawString(progressText, getWidth() / 2 - digitalWidth / 2, getHeight() / 2 + digitalAscent / 2); } public int getProgress() { return progress; } public void setProgress(int progress) { if (progress >= minimumProgress && progress <= maximumProgress) { this.progress = progress; } if (progress > maximumProgress) { this.progress = maximumProgress; } this.progressText = String.valueOf(progress + "%"); this.repaint(); } public Color getBackgroundColor() { return backgroundColor; } public void setBackgroundColor(Color backgroundColor) { this.backgroundColor = backgroundColor; this.repaint(); } public Color getForegroundColor() { return foregroundColor; } public void setForegroundColor(Color foregroundColor) { this.foregroundColor = foregroundColor; this.repaint(); } }
ChartUtil
package util; import com.objectplanet.chart.BarChart; import com.objectplanet.chart.Chart; import javax.swing.*; import java.awt.*; /** * @ClassName: CharUtil * @Description: 图表工具类 * @author: yunche * @date: 2018/07/20 */ public class ChartUtil { public static int max(double[] sampleValues) { int max = 0; for (double v : sampleValues) { if (v > max) { max = (int) v; } } return max; } private static String[] sampleLabels() { String[] sampleLabels = new String[30]; for (int i = 0; i < sampleLabels.length; i++) { if (0 == i % 5) { sampleLabels[i] = String.valueOf(i + 1 + "日"); } } return sampleLabels; } public static Image getImage(int width, int height) { // 模拟样本数据 double[] sampleValues = sampleValues(); // 下方显示的文字 String[] sampleLabels = sampleLabels(); // 样本中的最大值 int max = max(sampleValues); // 数据颜色 Color[] sampleColors = new Color[]{ColorUtil.blueColor}; // 柱状图 BarChart chart = new BarChart(); // 设置样本个数 chart.setSampleCount(sampleValues.length); // 设置样本数据 chart.setSampleValues(0, sampleValues); // 设置文字 chart.setSampleLabels(sampleLabels); // 设置样本颜色 chart.setSampleColors(sampleColors); // 设置取值范围 chart.setRange(0, max * 1.2); // 显示背景横线 chart.setValueLinesOn(true); // 显示文字 chart.setSampleLabelsOn(true); // 把文字显示在下方 chart.setSampleLabelStyle(Chart.BELOW); // 样本值的字体 chart.setFont("rangeLabelFont", new Font("Arial", Font.BOLD, 12)); // 显示图例说明 chart.setLegendOn(true); // 把图例说明放在左侧 chart.setLegendPosition(Chart.LEFT); // 图例说明中的文字 chart.setLegendLabels(new String[]{"月消费报表"}); // 图例说明的字体 chart.setFont("legendFont", new Font("Dialog", Font.BOLD, 13)); // 下方文字的字体 chart.setFont("sampleLabelFont", new Font("Dialog", Font.BOLD, 13)); // 图表中间背景颜色 chart.setChartBackground(Color.white); // 图表整体背景颜色 chart.setBackground(ColorUtil.backgroundColor); // 把图表转换为Image类型 Image im = chart.getImage(width, height); return im; } private static double[] sampleValues() { double[] result = new double[30]; for (int i = 0; i < result.length; i++) { result[i] = (int) (Math.random() * 300); } return result; } /** * 测试方法去掉注释可用 * @param args public static void main(String[] args) { JPanel p = new JPanel(); JLabel l = new JLabel(); Image img = ChartUtil.getImage(400, 300); Icon icon = new ImageIcon(img); l.setIcon(icon); p.add(l); GUIUtil.showPanel(p); } */ }
测试方法效果图:
界面类
就到这里吧,如果有兴趣的,可以去Java自学网站深入学习这个项目,这个网站挺不错的,自学java也不用愁没资源了。下面贴出项目框架图
不积跬步,无以至千里;不积小流,无以成江海