为什么屏幕上画了什么?

时间:2018-10-22 03:58:22

标签: java multithreading swing user-interface animation

我正在尝试做一个简单的7段显示并进行测试,我想制作一个简单的动画,该动画按顺序显示数字,并在1秒的数字绘制之间进行分隔,并且必须无限期运行,但是我无法弄清楚如何绘制显示本身(实现动画,没有动画,我知道如何一张一张地打印数字)。

PD:如果有人需要,我会为您提供所有源代码,但“动画”位于第120行,我在其中定义了运行动画的线程。

源代码:

public class MainWindow extends JFrame {

private JPanel contentPane;
private CustomRectangle custRect = null;
private JButton btnCancel;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                MainWindow frame = new MainWindow();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */

public MainWindow() {
    getContentPane().setBackground(Color.BLACK);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setUndecorated(true);
    setSize(400, 400);
    contentPane = new JPanel();
    contentPane.setLayout(null);
    custRect = new CustomRectangle(getContentPane().getSize());
    getContentPane().add(custRect);
    getContentPane().add(getBtnCancel(), BorderLayout.SOUTH);
}

private Color complementaryColor(Color background) {
    int alpha = background.getAlpha();
    int red = background.getRed();
    int blue = background.getBlue();
    int green = background.getGreen();

    // find compliments
    red = (~red) & 0xff;
    blue = (~blue) & 0xff;
    green = (~green) & 0xff;

    return new Color(red, green, blue, alpha);
}

private JButton getBtnCancel() {
    if (btnCancel == null) {
        btnCancel = new JButton("Cancel");
        btnCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        btnCancel.setBackground(null);
        btnCancel.setBorder(null);
        btnCancel.setForeground(complementaryColor(getContentPane().getBackground()));
        btnCancel.setFocusPainted(false);
    }
    return btnCancel;
}

private class CustomRectangle extends JComponent {

    private byte[] nums = new byte[] { 0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B };

    private double mainWidth = 0.0;
    private double mainHeight = 0.0;
    private Graphics2D g2d = null;

    public CustomRectangle(Dimension size) {
        mainWidth = size.getWidth();
        mainHeight = size.getHeight();
    }

    public byte[] getNums() {
        return nums;
    }

    @Override
    public void paintComponent(Graphics g) {
        g2d = (Graphics2D) g;

        Calendar calendar = Calendar.getInstance();
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minutes = calendar.get(Calendar.MINUTE);
        int seconds = calendar.get(Calendar.SECOND);

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        Thread th = new Thread() {
            public void run() {
                while(true) {
                    for(int i = 0; i < nums.length; i++)
                            generalCall(nums[i]);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        };th.start();
    }

    public void generalCall(byte val) {
        drawAHoursHigh(val);
        drawBHoursHigh(val);
        drawCHoursHigh(val);
        drawDHoursHigh(val);
        drawEHoursHigh(val);
        drawFHoursHigh(val);
        drawGHoursHigh(val);

    }
    private Color getColor(byte val, int shift) {
        int r = 255;
        int g = 0;
        int b = 0;
        int a = 255 * (val >> shift) & 1;

        System.out.println("R: " + r + " G: " + g + " B: " + b + " Alpha: " + a);

        if (a == 0)
            return new Color(15, 15, 15);
        else
            return new Color(r, g, b);
    }

    private void drawAHoursHigh(byte val) {
        System.out.print("A: ");
        Shape a = new RoundRectangle2D.Double(60, 20, 78, 18, 10, 10);
        g2d.setColor(getColor(val, 6));
        g2d.fill(a);
        g2d.draw(a);
    }

    private void drawBHoursHigh(byte val) {
        System.out.print("B: ");
        Shape b = new RoundRectangle2D.Double(140, 40, 18, 98, 10, 10);
        g2d.setColor(getColor(val, 5));
        g2d.fill(b);
        g2d.draw(b);
    }

    private void drawCHoursHigh(byte val) {
        System.out.print("C: ");
        Shape c = new RoundRectangle2D.Double(140, 160, 18, 98, 10, 10);
        g2d.setColor(getColor(val, 4));
        g2d.fill(c);
        g2d.draw(c);
    }

    private void drawDHoursHigh(byte val) {
        System.out.print("D: ");
        Shape d = new RoundRectangle2D.Double(60, 260, 78, 18, 10, 10);
        g2d.setColor(getColor(val, 3));
        g2d.fill(d);
        g2d.draw(d);
    }

    private void drawEHoursHigh(byte val) {
        System.out.print("E: ");
        Shape e = new RoundRectangle2D.Double(40, 160, 18, 98, 10, 10);
        g2d.setColor(getColor(val, 2));
        g2d.fill(e);
        g2d.draw(e);
    }

    private void drawFHoursHigh(byte val) {
        System.out.print("F: ");
        Shape f = new RoundRectangle2D.Double(40, 40, 18, 98, 10, 10);
        g2d.setColor(getColor(val, 1));
        g2d.fill(f);
        g2d.draw(f);
    }

    private void drawGHoursHigh(byte val) {
        System.out.print("G: ");
        Shape g = new RoundRectangle2D.Double(60, 140, 78, 18, 10, 10);
        g2d.setColor(getColor(val, 0));
        g2d.fill(g);
        g2d.draw(g);
    }
}
}

1 个答案:

答案 0 :(得分:0)

首先,请阅读:

有关绘画在Swing中如何工作的更多信息。

接下来,请阅读:

为了更好地理解Swing中的并发问题-简短的版本,Swing不是线程安全的,并且是单线程的。当您要执行重复操作以更新UI时,这会引起许多问题。

然后,请阅读How to Use Swing Timers以获得可行的解决方案。

让我们开始确定核心问题...

这个...

contentPane = new JPanel();
contentPane.setLayout(null);

通常不是一个好主意,但是您还是不使用它,所以它只是白噪声

这个...

custRect = new CustomRectangle(getContentPane().getSize());

是错误的,因为在您请求他contentPane的大小时,它尚未实现或在屏幕上没有布局,因此结果是0x0。无论如何,您都不应该依赖于此,如果您想知道容器的大小,请在实际需要时提出要求。

下一步...

private Graphics2D g2d = null;

您永远不应保留对未创建的任何图形上下文的引用。在Swing中,上下文在所有绘制的组件之间共享,这意味着它可能很脏,带有其他内容,或者被裁剪以排除要绘制的区域。

最后。。。

@Override
public void paintComponent(Graphics g) {
    g2d = (Graphics2D) g;

    Calendar calendar = Calendar.getInstance();
    int hour = calendar.get(Calendar.HOUR_OF_DAY);
    int minutes = calendar.get(Calendar.MINUTE);
    int seconds = calendar.get(Calendar.SECOND);

    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    Thread th = new Thread() {
        public void run() {
            while(true) {
                for(int i = 0; i < nums.length; i++)
                        generalCall(nums[i]);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    };th.start();
}

paintComponent将在Swing认为需要重新粉刷您的组件时被调用,第一次实现时,可能需要连续快速多次,这意味着您现在有Thread个运行。

绘制应该完成一项工作,绘制组件的当前上下文,别无其他。就您而言,Swing Timer是一个更可行,更安全的解决方案。

然后清理一下,看起来可能类似于...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;

public class MainWindow extends JFrame {

    private CustomRectangle custRect = null;
    private JButton btnCancel;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MainWindow frame = new MainWindow();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public MainWindow() {
        getContentPane().setBackground(Color.BLACK);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(400, 400);
        custRect = new CustomRectangle();
        getContentPane().add(custRect);
        getContentPane().add(getBtnCancel(), BorderLayout.SOUTH);
    }

    private Color complementaryColor(Color background) {
        int alpha = background.getAlpha();
        int red = background.getRed();
        int blue = background.getBlue();
        int green = background.getGreen();

        // find compliments
        red = (~red) & 0xff;
        blue = (~blue) & 0xff;
        green = (~green) & 0xff;

        return new Color(red, green, blue, alpha);
    }

    private JButton getBtnCancel() {
        if (btnCancel == null) {
            btnCancel = new JButton("Cancel");
            btnCancel.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
            });
            btnCancel.setBackground(null);
            btnCancel.setBorder(null);
            btnCancel.setForeground(complementaryColor(getContentPane().getBackground()));
            btnCancel.setFocusPainted(false);
        }
        return btnCancel;
    }

    private class CustomRectangle extends JComponent {

        private byte[] nums = new byte[]{0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B};

        public CustomRectangle() {
            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    repaint();
                }
            });
        }

        public byte[] getNums() {
            return nums;
        }

        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;

            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            for (int i = 0; i < nums.length; i++) {
                generalCall(g2d, nums[i]);
            }
        }

        public void generalCall(Graphics2D g2d, byte val) {
            drawAHoursHigh(g2d, val);
            drawBHoursHigh(g2d, val);
            drawCHoursHigh(g2d, val);
            drawDHoursHigh(g2d, val);
            drawEHoursHigh(g2d, val);
            drawFHoursHigh(g2d, val);
            drawGHoursHigh(g2d, val);
        }

        private Color getColor(byte val, int shift) {
            int r = 255;
            int g = 0;
            int b = 0;
            int a = 255 * (val >> shift) & 1;

            System.out.println("R: " + r + " G: " + g + " B: " + b + " Alpha: " + a);

            if (a == 0) {
                return new Color(15, 15, 15);
            } else {
                return new Color(r, g, b);
            }
        }

        private void drawAHoursHigh(Graphics2D g2d, byte val) {
            System.out.print("A: ");
            Shape a = new RoundRectangle2D.Double(60, 20, 78, 18, 10, 10);
            g2d.setColor(getColor(val, 6));
            g2d.fill(a);
            g2d.draw(a);
        }

        private void drawBHoursHigh(Graphics2D g2d, byte val) {
            System.out.print("B: ");
            Shape b = new RoundRectangle2D.Double(140, 40, 18, 98, 10, 10);
            g2d.setColor(getColor(val, 5));
            g2d.fill(b);
            g2d.draw(b);
        }

        private void drawCHoursHigh(Graphics2D g2d, byte val) {
            System.out.print("C: ");
            Shape c = new RoundRectangle2D.Double(140, 160, 18, 98, 10, 10);
            g2d.setColor(getColor(val, 4));
            g2d.fill(c);
            g2d.draw(c);
        }

        private void drawDHoursHigh(Graphics2D g2d, byte val) {
            System.out.print("D: ");
            Shape d = new RoundRectangle2D.Double(60, 260, 78, 18, 10, 10);
            g2d.setColor(getColor(val, 3));
            g2d.fill(d);
            g2d.draw(d);
        }

        private void drawEHoursHigh(Graphics2D g2d, byte val) {
            System.out.print("E: ");
            Shape e = new RoundRectangle2D.Double(40, 160, 18, 98, 10, 10);
            g2d.setColor(getColor(val, 2));
            g2d.fill(e);
            g2d.draw(e);
        }

        private void drawFHoursHigh(Graphics2D g2d, byte val) {
            System.out.print("F: ");
            Shape f = new RoundRectangle2D.Double(40, 40, 18, 98, 10, 10);
            g2d.setColor(getColor(val, 1));
            g2d.fill(f);
            g2d.draw(f);
        }

        private void drawGHoursHigh(Graphics2D g2d, byte val) {
            System.out.print("G: ");
            Shape g = new RoundRectangle2D.Double(60, 140, 78, 18, 10, 10);
            g2d.setColor(getColor(val, 0));
            g2d.fill(g);
            g2d.draw(g);
        }
    }
}