在 JFrame 中生成方波

Posted

技术标签:

【中文标题】在 JFrame 中生成方波【英文标题】:Generate square wave in 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;

【问题讨论】:

【参考方案1】:

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

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

例如,请注意,此代码并没有完全按照您的意图执行,但确实显示了使用 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

以上是关于在 JFrame 中生成方波的主要内容,如果未能解决你的问题,请参考以下文章

使用 NAudio 无法正确生成方波

正弦信号怎么变成方波信号,需要怎么处理?

怎样将正弦波变成方波或者锯齿波?

信号转换 | 如何将正弦波转换成方波?

连载9:用余弦信号合成方波信号

正弦波转换为方波