如何用java swing实现这样的效果,多条动态曲线的同时绘制

如何用java swing实现这样的效果,用到线程,当点击上方按钮时,开始绘制对应曲线,并从右向左移动。

img

参考gpt:
要使用Java Swing实现这样的效果,您可以创建一个继承自JPanel的自定义面板,并在该面板上绘制曲线。然后,通过使用线程来控制曲线的移动和重绘。

下面是一个简单的示例代码,展示了如何在Java Swing中实现这个效果:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class CurvePanel extends JPanel implements ActionListener {
    private int x; // 当前绘制位置
    private Timer timer; // 定时器

    public CurvePanel() {
        x = getWidth(); // 初始化绘制位置为面板宽度
        timer = new Timer(10, this); // 创建定时器,每10毫秒触发一次
        JButton startButton = new JButton("Start");
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                timer.start(); // 点击按钮开始绘制和移动曲线
            }
        });
        setLayout(new BorderLayout());
        add(startButton, BorderLayout.NORTH);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.RED);
        int y = getHeight() / 2; // 曲线的垂直位置为面板高度的一半
        g.drawLine(x, y, x, y); // 绘制曲线的一个点
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        x--; // 每次定时器触发时,向左移动一像素
        if (x < 0) {
            x = getWidth(); // 当绘制位置超出面板宽度时,重新开始绘制
        }
        repaint(); // 重绘面板
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Curve Animation");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                CurvePanel curvePanel = new CurvePanel();
                frame.add(curvePanel);
                frame.setSize(400, 200);
                frame.setVisible(true);
            }
        });
    }
}

在上述示例中,创建了一个自定义的CurvePanel类,继承自JPanel。在paintComponent方法中,使用Graphics对象绘制曲线的一个点,初始位置为(x, y)。在actionPerformed方法中,通过每次减少x的值,使曲线向左移动。使用定时器控制每次移动的时间间隔,并在startButton按钮的动作监听器中启动定时器。

最后,通过创建一个JFrame窗口,并将CurvePanel添加到窗口中,来显示界面。

希望这可以帮助您实现所需的效果!如有进一步的问题,请随时提问。

以下是一个使用 Java Swing 绘制对应曲线,并从右向左移动的代码示例,它将在点击上方按钮时启动:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class CurvePanel extends JPanel implements ActionListener, Runnable {
    private int x;  // 曲线起点横坐标位置 
    private int width;  // 组件宽度 
    private Timer timer;  // 定时器控制曲线移动 
    private Thread thread;  // 控制绘制曲线的线程 
    private boolean isRunning;  // 是否正在运行绘制线程 
    private int[] curve;  // 需要绘制的曲线数据 

    public CurvePanel() {
        // 初始化组件属性 
        x = getWidth();
        width = x;
        setPreferredSize(new Dimension(400, 200));
        setBackground(Color.WHITE);
        
        //  定义成员变量
        isRunning = false;
        curve = new int[width];
        for (int i = 0; i < width; i++) {
            curve[i] = (int) (50 * (1 - Math.sin(Math.toRadians(i * 180.0 / width))));
        }
        
        // 创建定时器
        timer = new Timer(20, this);
        timer.setInitialDelay(0);
        timer.start();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (x < 0) {
            x = width;
        } else {
            x -= 1;
        }
        repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        int y, nextY;
        for (int i = 0; i < width - 1; i++) {
            y = getHeight() / 2 - curve[(i + x) % width];
            nextY = getHeight() / 2 - curve[(i + x + 1) % width];
            g.drawLine(i, y, i + 1, nextY);
        }
    }

    public void startCurveThread() {
        if (!isRunning) {
            thread = new Thread(this);
            isRunning = true;
            thread.start();
        }
    }

    @Override
    public void run() {
        while (isRunning) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在主类中,我们将创建一个带有 "Start" 按钮和 CurvePanel 组件的窗口:

import javax.swing.*;
import java.awt.*;

public class CurveDemo implements Runnable {
    private JFrame frame;
    private JButton startButton;
    private CurvePanel curvePanel;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new CurveDemo());
    }

    @Override
    public void run() {
        frame = new JFrame("Curve Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        startButton = new JButton("Start");
        startButton.addActionListener(new StartButtonListener());

        curvePanel = new CurvePanel();

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(startButton, BorderLayout.NORTH);
        panel.add(curvePanel, BorderLayout.CENTER);

        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private class StartButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            curvePanel.startCurveThread();
        }
    }
}

当用户在 CurvePanel 组件上点击 "Start" 按钮时,将启动控制绘制曲线和移动曲线的线程。此时,在 actionPerformed() 方法中每隔一段时间将更新 x 值,并调用 repaint() 方法重新绘制曲线,直到曲线的最后一个点完全不可见。注意,使用睡眠使线程在一定间隔内轮询,以避免 CPU 占用率过高。