Java如何实现无损绘画?
How to achieve non-destructive painting in Java?
我想在面板上画出许多不同频率的正弦曲线,但是因为绘画是破坏性的,所以我无法实现。我只能看到最后绘制的正弦曲线。
在代码中,generateSinus() 方法只被调用了三次,但它可能会被调用很多次,我不想为 paintComponent( ) 方法。
有没有办法实现无损绘画,看到所有不同频率的正弦曲线?
请看下面的代码:
package testdrawsinus;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestDrawSinus extends JPanel
{
private static double[] x;
private static double[] y;
private static boolean buttonClicked = false;
private static JPanel panel = new TestDrawSinus();
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GREEN);
if (buttonClicked)
{
for (int i=0; i<x.length; i++)
{
g.fillOval((int)x[i] + panel.getWidth()/2, -1*((int)y[i]) + panel.getHeight()/2, 10, 10);
}
buttonClicked = false;
}
}
private static void generateSinus(int freq)
{
x = new double[200];
y = new double[200];
for (int i=0; i<=199; i++)
{
x[i]= (double)i;
y[i] = 100*Math.sin(2*Math.PI*freq*i/200);
}
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
panel.setLayout(null);
panel.setBounds(20,20, 700,400);
panel.setBackground(Color.BLACK);
frame.add(panel);
JButton button1 = new JButton();
button1.setText("plot");
button1.setBounds(300, 500, 150, 50);
frame.add(button1);
button1.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
buttonClicked = true;
generateSinus(1);
panel.repaint();
generateSinus(2);
panel.repaint();
generateSinus(3);
panel.repaint();
}
});
}
}
感谢您的帮助。
有多种方法可以做到这一点,一种方法是将每个系列分成自己的模型,然后让面板绘制每个模型,例如...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
private Color[] masterColors = new Color[]{
Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY,
Color.GREEN, Color.MAGENTA, Color.ORANGE, Color.PINK,
Color.RED, Color.WHITE, Color.YELLOW
};
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
TestDrawSinus sinusPane = new TestDrawSinus();
JFrame frame = new JFrame();
frame.add(sinusPane);
JButton button1 = new JButton();
button1.setText("plot");
frame.add(button1, BorderLayout.SOUTH);
button1.addActionListener(new ActionListener() {
private List<Color> colors = new ArrayList<>();
private int freq = 0;
@Override
public void actionPerformed(ActionEvent e) {
sinusPane.addSinusPlot(generateSinus(++freq, nextColor()));
sinusPane.addSinusPlot(generateSinus(++freq, nextColor()));
sinusPane.addSinusPlot(generateSinus(++freq, nextColor()));
}
protected Color nextColor() {
if (colors.isEmpty()) {
colors.addAll(Arrays.asList(masterColors));
Collections.shuffle(colors);
}
return colors.remove(0);
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private Random rnd = new Random();
private SinusPlot generateSinus(int freq, Color color) {
double[] x = new double[200];
double[] y = new double[200];
for (int i = 0; i < 200; i++) {
x[i] = (double) i;
y[i] = 100 * Math.sin(2d * Math.PI * freq * i / 200d);
}
return new SinusPlot(x, y, color);
}
public class SinusPlot {
private double[] x;
private double[] y;
private Color color;
public SinusPlot(double[] x, double[] y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
public int getSize() {
return x.length;
}
public double getXAt(int index) {
return x[index];
}
public double getYAt(int index) {
return y[index];
}
public Color getColor() {
return color;
}
}
public class TestDrawSinus extends JPanel {
private List<SinusPlot> plots = new ArrayList<>(8);
public void addSinusPlot(SinusPlot plot) {
plots.add(plot);
repaint();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (SinusPlot plot : plots) {
System.out.println(plot.getColor());
g2d.setColor(plot.getColor());
for (int i = 0; i < plot.getSize(); i++) {
Ellipse2D dot = new Ellipse2D.Double(((getWidth() - plot.getSize()) / 2) + plot.getXAt(i), plot.getYAt(i) + getHeight() / 2, 10, 10);
g2d.fill(dot);
}
}
g2d.dispose();
}
}
}
null
布局不会帮到你,花点时间了解布局管理系统的工作原理,它会为你节省很多时间和精力。有关详细信息,请参阅 Laying Out Components Within a Container。
static
不是你的朋友(尤其是在这种情况下),努力了解没有它如何生活(以及何时使用它)
我想在面板上画出许多不同频率的正弦曲线,但是因为绘画是破坏性的,所以我无法实现。我只能看到最后绘制的正弦曲线。
在代码中,generateSinus() 方法只被调用了三次,但它可能会被调用很多次,我不想为 paintComponent( ) 方法。
有没有办法实现无损绘画,看到所有不同频率的正弦曲线?
请看下面的代码:
package testdrawsinus;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestDrawSinus extends JPanel
{
private static double[] x;
private static double[] y;
private static boolean buttonClicked = false;
private static JPanel panel = new TestDrawSinus();
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GREEN);
if (buttonClicked)
{
for (int i=0; i<x.length; i++)
{
g.fillOval((int)x[i] + panel.getWidth()/2, -1*((int)y[i]) + panel.getHeight()/2, 10, 10);
}
buttonClicked = false;
}
}
private static void generateSinus(int freq)
{
x = new double[200];
y = new double[200];
for (int i=0; i<=199; i++)
{
x[i]= (double)i;
y[i] = 100*Math.sin(2*Math.PI*freq*i/200);
}
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
panel.setLayout(null);
panel.setBounds(20,20, 700,400);
panel.setBackground(Color.BLACK);
frame.add(panel);
JButton button1 = new JButton();
button1.setText("plot");
button1.setBounds(300, 500, 150, 50);
frame.add(button1);
button1.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
buttonClicked = true;
generateSinus(1);
panel.repaint();
generateSinus(2);
panel.repaint();
generateSinus(3);
panel.repaint();
}
});
}
}
感谢您的帮助。
有多种方法可以做到这一点,一种方法是将每个系列分成自己的模型,然后让面板绘制每个模型,例如...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
private Color[] masterColors = new Color[]{
Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY,
Color.GREEN, Color.MAGENTA, Color.ORANGE, Color.PINK,
Color.RED, Color.WHITE, Color.YELLOW
};
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
TestDrawSinus sinusPane = new TestDrawSinus();
JFrame frame = new JFrame();
frame.add(sinusPane);
JButton button1 = new JButton();
button1.setText("plot");
frame.add(button1, BorderLayout.SOUTH);
button1.addActionListener(new ActionListener() {
private List<Color> colors = new ArrayList<>();
private int freq = 0;
@Override
public void actionPerformed(ActionEvent e) {
sinusPane.addSinusPlot(generateSinus(++freq, nextColor()));
sinusPane.addSinusPlot(generateSinus(++freq, nextColor()));
sinusPane.addSinusPlot(generateSinus(++freq, nextColor()));
}
protected Color nextColor() {
if (colors.isEmpty()) {
colors.addAll(Arrays.asList(masterColors));
Collections.shuffle(colors);
}
return colors.remove(0);
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private Random rnd = new Random();
private SinusPlot generateSinus(int freq, Color color) {
double[] x = new double[200];
double[] y = new double[200];
for (int i = 0; i < 200; i++) {
x[i] = (double) i;
y[i] = 100 * Math.sin(2d * Math.PI * freq * i / 200d);
}
return new SinusPlot(x, y, color);
}
public class SinusPlot {
private double[] x;
private double[] y;
private Color color;
public SinusPlot(double[] x, double[] y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
public int getSize() {
return x.length;
}
public double getXAt(int index) {
return x[index];
}
public double getYAt(int index) {
return y[index];
}
public Color getColor() {
return color;
}
}
public class TestDrawSinus extends JPanel {
private List<SinusPlot> plots = new ArrayList<>(8);
public void addSinusPlot(SinusPlot plot) {
plots.add(plot);
repaint();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (SinusPlot plot : plots) {
System.out.println(plot.getColor());
g2d.setColor(plot.getColor());
for (int i = 0; i < plot.getSize(); i++) {
Ellipse2D dot = new Ellipse2D.Double(((getWidth() - plot.getSize()) / 2) + plot.getXAt(i), plot.getYAt(i) + getHeight() / 2, 10, 10);
g2d.fill(dot);
}
}
g2d.dispose();
}
}
}
null
布局不会帮到你,花点时间了解布局管理系统的工作原理,它会为你节省很多时间和精力。有关详细信息,请参阅 Laying Out Components Within a Container。
static
不是你的朋友(尤其是在这种情况下),努力了解没有它如何生活(以及何时使用它)