diff --git a/resources/icons/trash.png b/resources/icons/trash.png new file mode 100644 index 0000000..9c019cb Binary files /dev/null and b/resources/icons/trash.png differ diff --git a/src/com/lottery/action/ImportLotteryAllAction.java b/src/com/lottery/action/ImportLotteryAllAction.java index a5831ef..80c13a3 100644 --- a/src/com/lottery/action/ImportLotteryAllAction.java +++ b/src/com/lottery/action/ImportLotteryAllAction.java @@ -1,5 +1,6 @@ package com.lottery.action; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; @@ -7,9 +8,10 @@ import java.util.ArrayList; import java.util.List; -import javax.swing.JFileChooser; +import javax.swing.*; import javax.swing.filechooser.FileFilter; +import com.lottery.component.ProgressPanel; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; @@ -22,7 +24,15 @@ */ public class ImportLotteryAllAction implements ActionListener { - @Override + private ProgressPanel progressPanel; + private Frame frame; + + public ImportLotteryAllAction(Frame frame, ProgressPanel progressPanel) { + this.frame = frame; + this.progressPanel = progressPanel; + } + + @Override public void actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); @@ -53,8 +63,16 @@ public String getDescription() { if (state == 1) { return; } else { - File file = fileChooser.getSelectedFile(); - processImport(file); + final File file = fileChooser.getSelectedFile(); + progressPanel.start(); + Thread performer = new Thread(new Runnable() { + public void run() { + processImport(file); + progressPanel.stop(); + JOptionPane.showMessageDialog(frame, "导入全排列数据成功!", "系统消息", JOptionPane.INFORMATION_MESSAGE); + } + }, "导入全排列数据"); + performer.start(); } } diff --git a/src/com/lottery/action/ImportLotteryAnyAction.java b/src/com/lottery/action/ImportLotteryAnyAction.java index cf01f7c..89bf119 100644 --- a/src/com/lottery/action/ImportLotteryAnyAction.java +++ b/src/com/lottery/action/ImportLotteryAnyAction.java @@ -1,6 +1,7 @@ package com.lottery.action; import com.lottery.common.SpringBeanFactory; +import com.lottery.component.ProgressPanel; import com.lottery.model.LotteryAny; import com.lottery.service.LotteryAnyService; import org.apache.commons.io.FileUtils; @@ -8,6 +9,7 @@ import javax.swing.*; import javax.swing.filechooser.FileFilter; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; @@ -21,6 +23,14 @@ */ public class ImportLotteryAnyAction implements ActionListener { + private ProgressPanel progressPanel; + private Frame frame; + + public ImportLotteryAnyAction(Frame frame, ProgressPanel progressPanel) { + this.frame = frame; + this.progressPanel = progressPanel; + } + @Override public void actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(); @@ -52,8 +62,16 @@ public String getDescription() { if (state == 1) { return; } else { - File file = fileChooser.getSelectedFile(); - processImport(file); + final File file = fileChooser.getSelectedFile(); + progressPanel.start(); + Thread performer = new Thread(new Runnable() { + public void run() { + processImport(file); + progressPanel.stop(); + JOptionPane.showMessageDialog(frame, "导入中奖数据成功!", "系统消息", JOptionPane.INFORMATION_MESSAGE); + } + }, "导入中奖数据"); + performer.start(); } } diff --git a/src/com/lottery/component/MemoryPanel.java b/src/com/lottery/component/MemoryPanel.java new file mode 100644 index 0000000..240b8d3 --- /dev/null +++ b/src/com/lottery/component/MemoryPanel.java @@ -0,0 +1,48 @@ +package com.lottery.component; + +import javax.swing.*; +import java.awt.*; + +/** + * Created by tasly on 2014/10/21. + */ +public class MemoryPanel extends JPanel { + //状态条的颜色 + private Color edgeColor = new Color(82, 115, 214); + private Color centerColor = new Color(180, 200, 230); + + public void paint(Graphics g) { + super.paint(g); + //得到当前组件(JPanel)的大小 + Dimension dimension = getSize(); + //得到各边框的宽度 + Insets insets = getInsets(); + int left = insets.left; + int top = insets.top; + //得到内存使用状态信息 + Runtime runtime = Runtime.getRuntime(); + long freeMemory = runtime.freeMemory(); + long totalMemory = runtime.totalMemory(); + //组件(JPanel)除去左、右边框后的宽度 + int insideWidth = dimension.width - (insets.left + insets.right); + //内存使用量的显示宽度 + int usedAmount = insideWidth - (int) (((long) insideWidth * freeMemory) / totalMemory); + int insideHeight = dimension.height - (insets.bottom + insets.top); + Graphics2D g2 = (Graphics2D) g; + //设置渐变效果的画笔 + g2.setPaint(new GradientPaint(left, top, edgeColor, left, insideHeight / 2, centerColor, true)); + g.fillRect(left, top, usedAmount, insideHeight); + g.setColor(getBackground()); + g.fillRect(left + usedAmount, top, insideWidth - usedAmount, insideHeight); + g.setFont(getFont()); + g.setColor(Color.black); + //显示状态的文字 + String memory = (Long.toString((totalMemory - freeMemory) / 1048576L) + "M of " + Long.toString(totalMemory / 1048576L) + 'M'); + //确定文字的显示位置 + FontMetrics fontmetrics = g.getFontMetrics(); + int stringWidth = fontmetrics.charsWidth(memory.toCharArray(), 0, memory.length()); + int stringHeight = fontmetrics.getHeight() - fontmetrics.getDescent(); + //显示文字 + g.drawString(memory, left + (insideWidth - stringWidth) / 2, top + (insideHeight + stringHeight) / 2); + } +} diff --git a/src/com/lottery/component/ProgressPanel.java b/src/com/lottery/component/ProgressPanel.java new file mode 100644 index 0000000..20baaa4 --- /dev/null +++ b/src/com/lottery/component/ProgressPanel.java @@ -0,0 +1,384 @@ +package com.lottery.component; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Area; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import javax.swing.JComponent; + +public class ProgressPanel extends JComponent implements MouseListener +{ + /** Contains the bars composing the circular shape. */ + protected Area[] ticker = null; + /** The animation thread is responsible for fade in/out and rotation. */ + protected Thread animation = null; + /** Notifies whether the animation is running or not. */ + protected boolean started = false; + /** Alpha level of the veil, used for fade in/out. */ + protected int alphaLevel = 0; + /** Duration of the veil's fade in/out. */ + protected int rampDelay = 300; + /** Alpha level of the veil. */ + protected float shield = 0.70f; + /** Message displayed below the circular shape. */ + protected String text = ""; + /** Amount of bars composing the circular shape. */ + protected int barsCount = 14; + /** Amount of frames per seconde. Lowers this to save CPU. */ + protected float fps = 15.0f; + /** Rendering hints to set anti aliasing. */ + protected RenderingHints hints = null; + + /** + * Creates a new progress panel with default values:
+ * + */ + public ProgressPanel() + { + this(""); + } + + /** + * Creates a new progress panel with default values:
+ * + * @param text The message to be displayed. Can be null or empty. + */ + public ProgressPanel(String text) + { + this(text, 14); + } + + /** + * Creates a new progress panel with default values:
+ * + * @param text The message to be displayed. Can be null or empty. + * @param barsCount The amount of bars composing the circular shape + */ + public ProgressPanel(String text, int barsCount) + { + this(text, barsCount, 0.70f); + } + + /** + * Creates a new progress panel with default values:
+ * + * @param text The message to be displayed. Can be null or empty. + * @param barsCount The amount of bars composing the circular shape. + * @param shield The alpha level between 0.0 and 1.0 of the colored + * shield (or veil). + */ + public ProgressPanel(String text, int barsCount, float shield) + { + this(text, barsCount, shield, 15.0f); + } + + /** + * Creates a new progress panel with default values:
+ * + * @param text The message to be displayed. Can be null or empty. + * @param barsCount The amount of bars composing the circular shape. + * @param shield The alpha level between 0.0 and 1.0 of the colored + * shield (or veil). + * @param fps The number of frames per second. Lower this value to + * decrease CPU usage. + */ + public ProgressPanel(String text, int barsCount, float shield, float fps) + { + this(text, barsCount, shield, fps, 300); + } + + /** + * Creates a new progress panel. + * @param text The message to be displayed. Can be null or empty. + * @param barsCount The amount of bars composing the circular shape. + * @param shield The alpha level between 0.0 and 1.0 of the colored + * shield (or veil). + * @param fps The number of frames per second. Lower this value to + * decrease CPU usage. + * @param rampDelay The duration, in milli seconds, of the fade in and + * the fade out of the veil. + */ + public ProgressPanel(String text, int barsCount, float shield, float fps, int rampDelay) + { + this.text = text; + this.rampDelay = rampDelay >= 0 ? rampDelay : 0; + this.shield = shield >= 0.0f ? shield : 0.0f; + this.fps = fps > 0.0f ? fps : 15.0f; + this.barsCount = barsCount > 0 ? barsCount : 14; + + this.hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + this.hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + this.hints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + } + + /** + * Changes the displayed message at runtime. + * + * @param text The message to be displayed. Can be null or empty. + */ + public void setText(String text) + { + this.text = text; + repaint(); + } + + /** + * Returns the current displayed message. + */ + public String getText() + { + return text; + } + + /** + * Starts the waiting animation by fading the veil in, then + * rotating the shapes. This method handles the visibility + * of the glass pane. + */ + public void start() + { + addMouseListener(this); + setVisible(true); + ticker = buildTicker(); + animation = new Thread(new Animator(true)); + animation.start(); + } + + /** + * Stops the waiting animation by stopping the rotation + * of the circular shape and then by fading out the veil. + * This methods sets the panel invisible at the end. + */ + public void stop() + { + if (animation != null) { + animation.interrupt(); + animation = null; + animation = new Thread(new Animator(false)); + animation.start(); + } + } + + /** + * Interrupts the animation, whatever its state is. You + * can use it when you need to stop the animation without + * running the fade out phase. + * This methods sets the panel invisible at the end. + */ + public void interrupt() + { + if (animation != null) { + animation.interrupt(); + animation = null; + + removeMouseListener(this); + setVisible(false); + } + } + + public void paintComponent(Graphics g) + { + if (started) + { + int width = getWidth(); + int height = getHeight(); + + double maxY = 0.0; + + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHints(hints); + + g2.setColor(new Color(255, 255, 255, (int) (alphaLevel * shield))); + g2.fillRect(0, 0, getWidth(), getHeight()); + + for (int i = 0; i < ticker.length; i++) + { + int channel = 224 - 128 / (i + 1); + g2.setColor(new Color(channel, channel, channel, alphaLevel)); + g2.fill(ticker[i]); + + Rectangle2D bounds = ticker[i].getBounds2D(); + if (bounds.getMaxY() > maxY) + maxY = bounds.getMaxY(); + } + + if (text != null && text.length() > 0) + { + FontRenderContext context = g2.getFontRenderContext(); + TextLayout layout = new TextLayout(text, getFont(), context); + Rectangle2D bounds = layout.getBounds(); + g2.setColor(getForeground()); + layout.draw(g2, (float) (width - bounds.getWidth()) / 2, + (float) (maxY + layout.getLeading() + 2 * layout.getAscent())); + } + } + } + + /** + * Builds the circular shape and returns the result as an array of + * Area. Each Area is one of the bars + * composing the shape. + */ + private Area[] buildTicker() + { + Area[] ticker = new Area[barsCount]; + Point2D.Double center = new Point2D.Double((double) getWidth() / 2, (double) getHeight() / 2); + double fixedAngle = 2.0 * Math.PI / ((double) barsCount); + + for (double i = 0.0; i < (double) barsCount; i++) + { + Area primitive = buildPrimitive(); + + AffineTransform toCenter = AffineTransform.getTranslateInstance(center.getX(), center.getY()); + AffineTransform toBorder = AffineTransform.getTranslateInstance(45.0, -6.0); + AffineTransform toCircle = AffineTransform.getRotateInstance(-i * fixedAngle, center.getX(), center.getY()); + + AffineTransform toWheel = new AffineTransform(); + toWheel.concatenate(toCenter); + toWheel.concatenate(toBorder); + + primitive.transform(toWheel); + primitive.transform(toCircle); + + ticker[(int) i] = primitive; + } + + return ticker; + } + + /** + * Builds a bar. + */ + private Area buildPrimitive() + { + Rectangle2D.Double body = new Rectangle2D.Double(6, 0, 30, 12); + Ellipse2D.Double head = new Ellipse2D.Double(0, 0, 12, 12); + Ellipse2D.Double tail = new Ellipse2D.Double(30, 0, 12, 12); + + Area tick = new Area(body); + tick.add(new Area(head)); + tick.add(new Area(tail)); + + return tick; + } + + /** + * Animation thread. + */ + private class Animator implements Runnable + { + private boolean rampUp = true; + + protected Animator(boolean rampUp) + { + this.rampUp = rampUp; + } + + public void run() + { + Point2D.Double center = new Point2D.Double((double) getWidth() / 2, (double) getHeight() / 2); + double fixedIncrement = 2.0 * Math.PI / ((double) barsCount); + AffineTransform toCircle = AffineTransform.getRotateInstance(fixedIncrement, center.getX(), center.getY()); + + long start = System.currentTimeMillis(); + if (rampDelay == 0) + alphaLevel = rampUp ? 255 : 0; + + started = true; + boolean inRamp = rampUp; + + while (!Thread.interrupted()) + { + if (!inRamp) + { + for (int i = 0; i < ticker.length; i++) + ticker[i].transform(toCircle); + } + + repaint(); + + if (rampUp) + { + if (alphaLevel < 255) + { + alphaLevel = (int) (255 * (System.currentTimeMillis() - start) / rampDelay); + if (alphaLevel >= 255) + { + alphaLevel = 255; + inRamp = false; + } + } + } else if (alphaLevel > 0) { + alphaLevel = (int) (255 - (255 * (System.currentTimeMillis() - start) / rampDelay)); + if (alphaLevel <= 0) + { + alphaLevel = 0; + break; + } + } + + try + { + Thread.sleep(inRamp ? 10 : (int) (1000 / fps)); + } catch (InterruptedException ie) { + break; + } + Thread.yield(); + } + + if (!rampUp) + { + started = false; + repaint(); + + setVisible(false); + removeMouseListener(ProgressPanel.this); + } + } + } + + public void mouseClicked(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + } + + public void mouseReleased(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } +} \ No newline at end of file diff --git a/src/com/lottery/dao/hibernate3/SimpleHibernateDao.java b/src/com/lottery/dao/hibernate3/SimpleHibernateDao.java index c8944b0..dda46d6 100644 --- a/src/com/lottery/dao/hibernate3/SimpleHibernateDao.java +++ b/src/com/lottery/dao/hibernate3/SimpleHibernateDao.java @@ -43,7 +43,7 @@ public SimpleHibernateDao() { logger.warn(getClass().getSimpleName() + " not set the actual class on superclass generic parameter"); this.entityClass = (Class) Object.class; } - this.entityClass = (Class) params[0]; + this.entityClass = (Class) params[0]; } public SimpleHibernateDao(final SessionFactory sessionFactory, final Class entityClass) { diff --git a/src/com/lottery/ui/MainUI.java b/src/com/lottery/ui/MainUI.java index bcf12cb..c984f15 100644 --- a/src/com/lottery/ui/MainUI.java +++ b/src/com/lottery/ui/MainUI.java @@ -1,106 +1,140 @@ package com.lottery.ui; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.EventQueue; - -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JToolBar; -import javax.swing.UIManager; -import javax.swing.border.EmptyBorder; -import javax.swing.plaf.nimbus.NimbusLookAndFeel; - import com.lottery.action.ExitAction; import com.lottery.action.ImportLotteryAllAction; import com.lottery.action.ImportLotteryAnyAction; import com.lottery.common.SpringBeanFactory; +import com.lottery.component.MemoryPanel; +import com.lottery.component.ProgressPanel; import com.lottery.service.LotteryAllService; +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; +import javax.swing.plaf.nimbus.NimbusLookAndFeel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.URL; + public class MainUI extends JFrame { - private static final long serialVersionUID = -2089179114014597392L; - private JPanel contentPane; - - /** - * Launch the application. - */ - public void init() { - EventQueue.invokeLater(new Runnable() { - public void run() { - try { - UIManager.setLookAndFeel(new NimbusLookAndFeel()); - MainUI frame = new MainUI(); - frame.setSize(1000, 700); - frame.setVisible(true); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - - /** - * Create the frame. - */ - public MainUI() { - setTitle("大乐透分析系统"); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - setBounds(100, 100, 450, 300); - - JMenuBar menuBar = new JMenuBar(); - setJMenuBar(menuBar); - - JMenu mnNewMenu = new JMenu("文 件"); - menuBar.add(mnNewMenu); - - JMenuItem menuItem = new JMenuItem("导入数据"); - mnNewMenu.add(menuItem); - - JMenuItem menuItem_1 = new JMenuItem("退 出"); - mnNewMenu.add(menuItem_1); - menuItem_1.addActionListener(new ExitAction(this)); - - contentPane = new JPanel(); - contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); - contentPane.setLayout(new BorderLayout(0, 0)); - setContentPane(contentPane); - - JToolBar toolBar = new JToolBar(); - toolBar.setEnabled(false); - contentPane.add(toolBar, BorderLayout.NORTH); - - JButton initBtn = new JButton("导入全排列"); - initBtn.addActionListener(new ImportLotteryAllAction()); - initBtn.setPreferredSize(new Dimension(100, 30)); - toolBar.add(initBtn); - LotteryAllService lotteryAllService = (LotteryAllService) SpringBeanFactory.getInstance() - .getBeanById("lotteryAllService"); - if (lotteryAllService != null) { - if (lotteryAllService.countLotteryAll() != 0) { - initBtn.setEnabled(false); - } else { - initBtn.setEnabled(true); - } - } - - JButton importBtn = new JButton("导入数据"); - importBtn.addActionListener(new ImportLotteryAnyAction()); - importBtn.setPreferredSize(new Dimension(80, 30)); - toolBar.add(importBtn); - - JComboBox comboBox_1 = new JComboBox(); - comboBox_1.setPreferredSize(new Dimension(350, 30)); - toolBar.add(comboBox_1); - - JComboBox comboBox = new JComboBox(); - comboBox.setPreferredSize(new Dimension(350, 30)); - toolBar.add(comboBox); - } + private static final long serialVersionUID = -2089179114014597392L; + private JPanel contentPane; + + /** + * Launch the application. + */ + public void init() { + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + UIManager.setLookAndFeel(new NimbusLookAndFeel()); + MainUI frame = new MainUI(); + frame.setSize(1000, 700); + frame.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + /** + * Create the frame. + */ + public MainUI() { + setTitle("大乐透分析系统"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setBounds(100, 100, 450, 300); + + ProgressPanel glassPane = new ProgressPanel(); + setGlassPane(glassPane); + + JMenuBar menuBar = new JMenuBar(); + setJMenuBar(menuBar); + + JMenu mnNewMenu = new JMenu("文 件"); + menuBar.add(mnNewMenu); + + JMenuItem menuItem = new JMenuItem("导入数据"); + mnNewMenu.add(menuItem); + + JMenuItem menuItem_1 = new JMenuItem("退 出"); + mnNewMenu.add(menuItem_1); + menuItem_1.addActionListener(new ExitAction(this)); + + contentPane = new JPanel(); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + contentPane.setLayout(new BorderLayout(0, 0)); + setContentPane(contentPane); + + JToolBar toolBar = new JToolBar(); + toolBar.setEnabled(false); + contentPane.add(toolBar, BorderLayout.NORTH); + + JButton initBtn = new JButton("导入全排列"); + initBtn.addActionListener(new ImportLotteryAllAction(this, glassPane)); + initBtn.setPreferredSize(new Dimension(100, 30)); + toolBar.add(initBtn); + LotteryAllService lotteryAllService = (LotteryAllService) SpringBeanFactory.getInstance() + .getBeanById("lotteryAllService"); + if (lotteryAllService != null) { + if (lotteryAllService.countLotteryAll() != 0) { + initBtn.setEnabled(false); + } else { + initBtn.setEnabled(true); + } + } + + JButton importBtn = new JButton("导入数据"); + importBtn.addActionListener(new ImportLotteryAnyAction(this, glassPane)); + importBtn.setPreferredSize(new Dimension(80, 30)); + toolBar.add(importBtn); + + JComboBox comboBox_1 = new JComboBox(); + comboBox_1.setPreferredSize(new Dimension(350, 30)); + toolBar.add(comboBox_1); + + JComboBox comboBox = new JComboBox(); + comboBox.setPreferredSize(new Dimension(350, 30)); + toolBar.add(comboBox); + + JPanel statusPanel = new JPanel(); + contentPane.add(statusPanel, BorderLayout.SOUTH); + statusPanel.setLayout(new BorderLayout(0, 0)); + + JPanel memoryStatusPanel = new JPanel(); + memoryStatusPanel.setBorder(new LineBorder(Color.LIGHT_GRAY, 1, true)); + statusPanel.add(memoryStatusPanel, BorderLayout.EAST); + + final MemoryPanel memoryPanel = new MemoryPanel(); + memoryPanel.setPreferredSize(new Dimension(100, 15)); + memoryPanel.setMaximumSize(new Dimension(100, 15)); + memoryPanel.setMinimumSize(new Dimension(100, 15)); + memoryStatusPanel.add(memoryPanel); + + JButton gcButton = new JButton(""); + gcButton.setToolTipText("垃圾回收"); + URL url = getClass().getResource("/icons/trash.png"); + if(url != null){ + gcButton.setIcon(new ImageIcon(url)); + } + gcButton.setPreferredSize(new Dimension(25, 25)); + memoryStatusPanel.add(gcButton); + gcButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.gc(); + memoryPanel.repaint(); + } + }); + + Timer timer = new Timer(2000, new ActionListener() { + public void actionPerformed(ActionEvent actionevent) { + memoryPanel.repaint(); + } + }); + timer.start(); + } }