解决方案 »

  1.   

    想法挺好的,线程错了。用 Thread 那部分想办法改成用 javax.swing.Timer
      

  2.   

    哦,线程怎么错了啊?求指出,为什么要用Timer呢
      

  3.   

    哦,我看了Timer的API。就是在EDT中执行了。觉得应该用Timer。修改后的代码如下,还望检查:
    package animation;import java.awt.BorderLayout;
    import java.awt.Graphics;
    import java.awt.Rectangle;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.image.BufferedImage;import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JWindow;
    import javax.swing.SwingConstants;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    import javax.swing.UIManager;@SuppressWarnings("serial")
    public class WindowClosingAnimation extends JPanel {
    /**
     * Specifies the content pane.
     */
    public WindowClosingAnimation() {
    setLayout(new BorderLayout());
    add(new JLabel("测试窗口关闭效果", SwingConstants.CENTER), BorderLayout.CENTER);
    } private static void createAndShowGUI() {
    /* Specifies the L&F using its own JFrame decorations */
    JFrame.setDefaultLookAndFeelDecorated(true);
    try {
    UIManager.setLookAndFeel("com.han.gen.GenLookAndFeel");
    } catch (Exception e) {
    e.printStackTrace();
    } /* Creates a JFrame object and shows it */
    JFrame jFrame = new JFrame();
    jFrame.setContentPane(new WindowClosingAnimation());
    jFrame.setSize(300, 200);
    jFrame.setLocationRelativeTo(null);
    jFrame.setVisible(true); // Choose "true" or "false" to see the difference
    setWindowClosingAnimated(true, jFrame);
    } private static void setWindowClosingAnimated(boolean animated, JFrame jFrame) {
    if (animated) {
    jFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    addWindowClosingAnimationToJFrame(jFrame);
    } else {
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    } private static void addWindowClosingAnimationToJFrame(JFrame jFrame) {
    jFrame.addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosing(WindowEvent e) {
    windowClosingAnimation(jFrame);
    }
    });
    } private static void windowClosingAnimation(JFrame jFrame) {
    /* Firstly stores the bounds of our JFrame object to be closed as final */
    final Rectangle bounds = jFrame.getBounds(); /* Captured the entire JFrame image */
    BufferedImage image = new BufferedImage(bounds.width, bounds.height,
    BufferedImage.TYPE_INT_ARGB);
    Graphics g = image.getGraphics();
    jFrame.paint(g);
    g.dispose(); /*
     * Creates a new JWindow object to show the captured image, and at the
     * same time hides the JFrame object.
     */
    JWindow jWindow = new JWindow() {
    @Override
    public void paint(Graphics g) {
    super.paint(g);
    g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
    }
    };
    jWindow.setBounds(bounds);
    jFrame.setVisible(false);
    jWindow.setVisible(true); /* Uses a Timer to perform the size variation of JWindow */
    int delay = 15; // milliseconds
    final int indent = 20;
    ActionListener taskPerformer = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
    // ...Perform a task...
    Rectangle bounds = jWindow.getBounds();
    bounds.x += indent / 2;
    bounds.y += indent / 2;
    bounds.width -= indent;
    bounds.height -= indent;
    if (bounds.width < 0 || bounds.height < 0) {
    System.exit(0);
    } else {
    jWindow.setBounds(bounds);// will call repaint()
    }
    }
    };
    new Timer(delay, taskPerformer).start();
    } public static void main(String[] args) {
    // To make sure that the GUI creation happens on the EDT
    SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
    createAndShowGUI();
    }
    });
    }
    }
      

  4.   

    哦,我看了Timer的API。就是在EDT中执行了。觉得应该用Timer。修改后的代码如下,还望检查:
    package animation;import java.awt.BorderLayout;
    import java.awt.Graphics;
    import java.awt.Rectangle;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.image.BufferedImage;import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JWindow;
    import javax.swing.SwingConstants;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    import javax.swing.UIManager;@SuppressWarnings("serial")
    public class WindowClosingAnimation extends JPanel {
    /**
     * Specifies the content pane.
     */
    public WindowClosingAnimation() {
    setLayout(new BorderLayout());
    add(new JLabel("测试窗口关闭效果", SwingConstants.CENTER), BorderLayout.CENTER);
    } private static void createAndShowGUI() {
    /* Specifies the L&F using its own JFrame decorations */
    JFrame.setDefaultLookAndFeelDecorated(true);
    try {
    UIManager.setLookAndFeel("com.han.gen.GenLookAndFeel");
    } catch (Exception e) {
    e.printStackTrace();
    } /* Creates a JFrame object and shows it */
    JFrame jFrame = new JFrame();
    jFrame.setContentPane(new WindowClosingAnimation());
    jFrame.setSize(300, 200);
    jFrame.setLocationRelativeTo(null);
    jFrame.setVisible(true); // Choose "true" or "false" to see the difference
    setWindowClosingAnimated(true, jFrame);
    } private static void setWindowClosingAnimated(boolean animated, JFrame jFrame) {
    if (animated) {
    jFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    addWindowClosingAnimationToJFrame(jFrame);
    } else {
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    } private static void addWindowClosingAnimationToJFrame(JFrame jFrame) {
    jFrame.addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosing(WindowEvent e) {
    windowClosingAnimation(jFrame);
    }
    });
    } private static void windowClosingAnimation(JFrame jFrame) {
    /* Firstly stores the bounds of our JFrame object to be closed as final */
    final Rectangle bounds = jFrame.getBounds(); /* Captured the entire JFrame image */
    BufferedImage image = new BufferedImage(bounds.width, bounds.height,
    BufferedImage.TYPE_INT_ARGB);
    Graphics g = image.getGraphics();
    jFrame.paint(g);
    g.dispose(); /*
     * Creates a new JWindow object to show the captured image, and at the
     * same time hides the JFrame object.
     */
    JWindow jWindow = new JWindow() {
    @Override
    public void paint(Graphics g) {
    super.paint(g);
    g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
    }
    };
    jWindow.setBounds(bounds);
    jFrame.setVisible(false);
    jWindow.setVisible(true); /* Uses a Timer to perform the size variation of JWindow */
    int delay = 15; // milliseconds
    final int indent = 20;
    ActionListener taskPerformer = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
    // ...Perform a task...
    Rectangle bounds = jWindow.getBounds();
    bounds.x += indent / 2;
    bounds.y += indent / 2;
    bounds.width -= indent;
    bounds.height -= indent;
    if (bounds.width < 0 || bounds.height < 0) {
    System.exit(0);
    } else {
    jWindow.setBounds(bounds);// will call repaint()
    }
    }
    };
    new Timer(delay, taskPerformer).start();
    } public static void main(String[] args) {
    // To make sure that the GUI creation happens on the EDT
    SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
    createAndShowGUI();
    }
    });
    }
    }

      

  5.   

    可以控制更多窗口关闭时的动态效果,比如窗口旋转变形、淡入淡出、大小缩放等:
    package animation;import java.awt.AlphaComposite;
    import java.awt.BorderLayout;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.awt.RenderingHints;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.image.BufferedImage;import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JWindow;
    import javax.swing.SwingConstants;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    import javax.swing.UIManager;@SuppressWarnings("serial")
    public class WindowClosingAnimation extends JPanel {
    static float alpha = 1.0f;
    static double shx = 0.0; /**
     * Specifies the content pane.
     */
    public WindowClosingAnimation() {
    setLayout(new BorderLayout());
    add(new JLabel("测试窗口关闭效果", SwingConstants.CENTER), BorderLayout.CENTER);
    } private static void createAndShowGUI() {
    /* Specifies the L&F using its own JFrame decorations */
    JFrame.setDefaultLookAndFeelDecorated(true);
    try {
    UIManager.setLookAndFeel("com.han.gen.GenLookAndFeel");
    } catch (Exception e) {
    e.printStackTrace();
    } /* Creates a JFrame object and shows it */
    JFrame jFrame = new JFrame();
    jFrame.setContentPane(new WindowClosingAnimation());
    jFrame.setSize(300, 200);
    jFrame.setLocationRelativeTo(null);
    jFrame.setVisible(true); // Choose "true" or "false" to see the difference
    setWindowClosingAnimated(true, jFrame);
    } private static void setWindowClosingAnimated(boolean animated, JFrame jFrame) {
    if (animated) {
    jFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    addWindowClosingAnimationToJFrame(jFrame);
    } else {
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    } private static void addWindowClosingAnimationToJFrame(JFrame jFrame) {
    jFrame.addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosing(WindowEvent e) {
    windowClosingAnimation(jFrame);
    }
    });
    } private static void windowClosingAnimation(JFrame jFrame) {
    /* Firstly stores the bounds of our JFrame object to be closed as final */
    final Rectangle bounds = jFrame.getBounds(); /* Captured the entire JFrame image */
    BufferedImage image = new BufferedImage(bounds.width, bounds.height,
    BufferedImage.TYPE_INT_ARGB);
    Graphics g = image.getGraphics();
    jFrame.paint(g);
    g.dispose(); /*
     * Creates a new JWindow object to show the captured image, and at the
     * same time hides the JFrame object.
     */
    JWindow jWindow = new JWindow() {
    @Override
    public void paint(Graphics g) {
    super.paint(g);// important to call to have transparency
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g2.setComposite(AlphaComposite.getInstance(
    AlphaComposite.SRC_OVER, alpha));
    g2.shear(shx, 0);
    g2.drawImage(image, 0, 0, getWidth(), getHeight(), this);
    }
    };
    jWindow.setBounds(bounds);
    jFrame.setVisible(false);
    jWindow.setVisible(true); /* Uses a Timer to perform the size variation of JWindow */
    int delay = 30; // milliseconds
    final int indent = 20;
    ActionListener taskPerformer = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
    // ...Perform a task...
    alpha -= 0.1;
    shx += 0.01;
    Rectangle bounds = jWindow.getBounds();
    bounds.x += indent / 2;
    bounds.y += indent / 2;
    bounds.width -= indent;
    bounds.height -= indent;
    if (shx > 0.1 || alpha < 0 || bounds.width < 0
    || bounds.height < 0) {
    System.exit(0);
    } else {
    jWindow.setBounds(bounds);// will call repaint()
    }
    }
    };
    new Timer(delay, taskPerformer).start();
    } public static void main(String[] args) {
    // To make sure that the GUI creation happens on the EDT
    SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
    createAndShowGUI();
    }
    });
    }
    }