【问题标题】:Generate square wave in JFrame在 JFrame 中生成方波
【发布时间】:2016-05-24 14:34:46
【问题描述】:

我的方波代码效率低下。我有 2 个按钮、1 个表格和类似正方形出现的坐标系。我希望波浪实时滚动/移动,直到它到达坐标系的末端,而不是仅仅通过选择两个按钮来显示。另外,如果有人有更好的绘制方波的方法,请告诉我。

public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.drawLine(20, 300, 20, 450);
    g2d.drawLine(20, 350, 400, 350);
    g2d.drawLine(20, 400, 400, 400);
    g2d.drawLine(20, 450, 400, 450);

    if (this.jButtonSTART.isSelected() & this.jButtonAND.isSelected()) {
            this.draw(g2d);
        }
}

public void draw(Graphics2D g2d) {
    boolean up = true;
    while (x <= 380) {
        g2d.setColor(Color.blue);
        if (x > 0 && x % 95 == 0) {
            up = !up;
            g2d.drawLine(20 + x, up ? 315 : 350 + y, 20 + x, up ? 350 : 315 + y);
        } else {
            if (up) {
                g2d.drawLine(20 + x, 315 + y, 21 + x, y + 315);
            } else {
                g2d.drawLine(20 + x, 350 + y, 21 + x, y + 350);
            }
        }
        x++;
    }
    x = 0;
}

【问题讨论】:

    标签: java swing jframe wave


    【解决方案1】:

    绘制方波并移动它的简单方法:

    1. 创建一个比 GUI 更长的 BufferedImage。它的长度应与方波的周期相匹配,并且至少是显示它的 GUI 组件的两倍。
    2. 在 JPanel 的paintComponent 方法覆盖中绘制,而不是在paint 方法中。
    3. 首先在您的覆盖中调用 super 的 paintComponent 方法。
    4. 您将使用 g.drawImage(myImage, imageX, imageY, this) 绘制图像,其中 imageX 和 imageY 是 JPanel 扩展绘图类的私有实例字段。
    5. 在 Swing Timer 中,随着 Timer 的每个滴答声(即每次调用其 ActionListener 的 actionPerformed 方法)推进 imageX)。
    6. 然后在同一个 actionPerformed 方法中对绘图 JPanel 调用 repaint()
    7. 完成。

    例如,请注意,此代码并没有完全按照您的意图执行,但确实显示了使用 Swing Timer 和 paintComponent 的 Swing 动画示例。

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.GradientPaint;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class MoveWave extends JPanel {
        private static final int PREF_W = 400;
        private static final int PREF_H = 200;
        private static final int TIMER_DELAY = 40;
        public static final int DELTA_X = 2;
        public static final int STARTING_MY_IMAGE_X = -PREF_W;
        private static final Color COLOR_1 = Color.RED;
        private static final Color COLOR_2 = Color.BLUE;
        private static final Color BG = Color.BLACK;
        private static final int CIRCLE_COUNT = 10;
        private BufferedImage myImage = null;
        private int myImageX = STARTING_MY_IMAGE_X;
        private int myImageY = 0;
    
        public MoveWave() {
            setBackground(BG);
            myImage = new BufferedImage(2 * PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = myImage.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setPaint(new GradientPaint(0, 0, COLOR_1, 20, 20, COLOR_2, true));
            for (int i = 0; i < CIRCLE_COUNT; i++) {
                int x = (i * 2 * PREF_W) / CIRCLE_COUNT;
                int y = PREF_H / 4;
                int width = (2 * PREF_W) / CIRCLE_COUNT;
                int height = PREF_H / 2;
                g2.fillOval(x, y, width, height);
            }
            g2.dispose();
            new Timer(TIMER_DELAY, new TimerListener()).start();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (myImage != null) {
                g.drawImage(myImage, myImageX, myImageY, this);
            }
        }
        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
                return super.getPreferredSize();
            }
            return new Dimension(PREF_W, PREF_H);
        }
    
        private class TimerListener implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                myImageX += DELTA_X;
                if (myImageX >= 0) {
                    myImageX = STARTING_MY_IMAGE_X;                        
                }
                repaint();
            }
        }
    
        private static void createAndShowGui() {
            JFrame frame = new JFrame("MoveWave");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(new MoveWave());
            frame.setResizable(false);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    

    【讨论】:

    • 你的计时器的 actionPerformed 方法应该在 imageX 达到一个完整波长时重置它。并且您还应该添加一个 ComponentListener,其 componentResized() 方法为组件的新大小重新创建图像。
    • @FredK: true,或者对于我的示例程序(见上文),我只是固定 GUI 的大小。
    • @Hovercraft Full of Eels 非常感谢您的帮助!我真的只是一个初学者,所以我很难理解你的步骤。在第二步之后你失去了我。你能再详细一点吗?我假设您希望我创建 paintComponent 方法,因为我没有
    • @Nest:首先阅读关于 Swing 图形的教程:* Lesson: Performing Custom Painting
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多