在由单独的 GUI 更改的 JFrame canvas 上使用 paintComponent()
Using paintComponent() on a JFrame canvas being altered by a separate GUI
我正在尝试制作一个使用两个 JFrame 的 JComponent 应用程序,一个框架带有可变滑块和文本字段,用于在第二个框架上显示烟花的图形。当按下 "fire" 按钮时,应该会出现烟花的效果图。但是,我发现通过放置战略打印语句,我的 paintComponent() 方法不会 运行 即使包装代码的条件语句得到满足。我还仔细检查了所有其他方法,以确保在正确的时间生成正确的值。在查看了我能找到的所有 JComponent 文献和问题后,恐怕我无法让它工作——这个问题很可能是由于我对该库不熟悉所致。话虽这么说,任何建议,无论多么基本,都将不胜感激。精简代码如下:
*也可能是摇摆计时器的问题,我不确定我是否使用正确
[fireworksCanvas.java]
public class fireworkCanvas extends JComponent implements ActionListener{
private static final long serialVersionUID = 1L;
private ArrayList<Ellipse2D> nodes = new ArrayList<Ellipse2D>();
private ArrayList<Line2D> cNodes = new ArrayList<Line2D>();
private ArrayList<QuadCurve2D> bCurves = new ArrayList<QuadCurve2D>();
private int[] arcX;
private int[] arcY;
private Color userColor;
private Random rand = new Random();
private int shellX, shellY, fType, theta, velocity;
private Timer timer;
private int time;
private double g = -9.8; //gravity in m/s
public boolean explosivesSet;
public fireworkCanvas() {
time = rand.nextInt(3000) + 2000;
timer = new Timer(time, this); // 5 seconds
timer.start();
fType = 0;
}
@Override
public void paintComponent(Graphics g){
if (explosivesSet) {
System.out.println("fType" + fType);
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g.setColor(Color.BLACK);
g.drawPolyline(arcX, arcY, arcX.length);
for (Ellipse2D e : nodes) {
System.out.println("painting nodes"); // NEVER PRINTS
g.setColor(userColor);
g.fillOval(shellX + (int) e.getX(), shellY + (int) e.getY(), (int) e.getWidth(), (int) e.getHeight());
}
for (Line2D l: cNodes) {
System.out.println("painting cNodes"); // NEVER PRINTS
g.setColor(determineColor("l"));
g.drawLine(shellX + (int) l.getX1(), shellY + (int) l.getY1(), shellX + (int) l.getX2(), shellY + (int) l.getY2());
}
for (QuadCurve2D c: bCurves) {
System.out.println("painting curves"); // NEVER PRINTS
g.setColor(determineColor("c"));
g2D.draw(c);
}
}
}
public Color determineColor(String type) {
// returns color
}
public void setExplosives() {
if (fType != 5 && fType != 0) {
nodes.clear(); // clears three array lists with FW components
cNodes.clear(); // these are the components to paint for the
bCurves.clear(); // firework explosion graphic
setArc(); // stores path of shell for a polyLine to be drawn
// builds and generates components for FW based on type chosen (fType)
setExplosivesSet(true);
repaint();
}
}
public void setArc() {
// builds int[] for shellX, shellY
}
@Override
public void actionPerformed(ActionEvent e) {
// nothing is here??
// should I use the action performed in some way?
}
[GUI.java]
public class GUI extends JFrame implements ActionListener, ChangeListener, ItemListener, MouseListener{
private static JFrame canvasFrame = new JFrame("Canvas");
private fireworkCanvas canvas = new fireworkCanvas();
private Choice fireworkChooser = new Choice();
private JSlider launchAngle = new JSlider();
private JSlider velocity = new JSlider();
private JSlider r = new JSlider();
private JSlider g = new JSlider();
private JSlider b = new JSlider();
private JPanel panel = new JPanel();
private JButton button = new JButton("Fire!");
private JLabel launchLabel = new JLabel("Launch Angle ");
private JLabel velocityLabel = new JLabel("Velocity ");
private JLabel rLabel = new JLabel("Red ");
private JLabel gLabel = new JLabel("Green ");
private JLabel bLabel = new JLabel("Blue ");
public static int fHeight = 500;
public static int fWidth = 500;
public GUI() {
this.add(panel);
panel.add(button);
panel.add(fireworkChooser);
panel.add(launchAngle);
panel.add(launchLabel);
panel.add(velocity);
panel.add(velocityLabel);
panel.add(r);
panel.add(rLabel);
panel.add(g);
panel.add(gLabel);
panel.add(b);
panel.add(bLabel);
addActionListener(this);
BoxLayout bl = new BoxLayout(getContentPane(), BoxLayout.Y_AXIS);
setLayout(bl);
fireworkChooser.addItemListener(this);
launchAngle.addChangeListener(this);
velocity.addChangeListener(this);
r.addChangeListener(this);
g.addChangeListener(this);
b.addChangeListener(this);
button.addActionListener(this);
fireworkChooser.add("Firework 1");
fireworkChooser.add("Firework 2");
fireworkChooser.add("Firework 3");
fireworkChooser.add("Firework 4");
fireworkChooser.add("Super Firework");
launchAngle.setMinimum(1);
launchAngle.setMaximum(90);
velocity.setMinimum(1);
velocity.setMaximum(50);
r.setMinimum(0);
r.setMaximum(255);
g.setMinimum(0);
g.setMaximum(255);
b.setMinimum(0);
b.setMaximum(255);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 200);
}
@Override
public void stateChanged(ChangeEvent e) {
// sets FW variables
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
canvas.setfType(fireworkChooser.getSelectedIndex()+1);
canvas.setExplosives();
canvas.repaint();
canvas.setExplosivesSet(false);
System.out.println("button fired");
}
}
public static void createAndShowGUI() {
GUI gui = new GUI();
gui.pack();
gui.setLocationRelativeTo(null);
gui.setVisible(true);
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fireworkCanvas canvas = new fireworkCanvas();
canvasFrame.pack();
canvasFrame.add(canvas);
canvasFrame.setLocationRelativeTo(null);
canvasFrame.setVisible(true);
canvasFrame.setSize(fWidth, fHeight);
canvasFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
首先:
public fireworkCanvas()
Class 名称应以大写字符开头。您代码中的所有其他 classes 都遵循此规则。通过实例学习。
private Choice fireworkChooser = new Choice();
选择一个 AWT 组件不要在 Swing 应用程序中混合使用 AWT 组件。使用 JComboBox
.
that my paintComponent() method does not run
fireworkCanvas canvas = new fireworkCanvas();
canvasFrame.pack();
canvasFrame.add(canvas);
你在 pack() 框架之后将 canvas 添加到框架,所以 canvas 的大小是 (0, 0) 并且没有任何东西可以绘制。
应该在 pack() 之前将 canvas 添加到框架中,并且您应该在 FireworkCanvas class 中实现 getPreferredSize()
以便 pack() 方法可以正常工作。
阅读有关 Custom Painting 的 Swing 教程部分,了解基础知识和工作示例,以帮助您入门。
我正在尝试制作一个使用两个 JFrame 的 JComponent 应用程序,一个框架带有可变滑块和文本字段,用于在第二个框架上显示烟花的图形。当按下 "fire" 按钮时,应该会出现烟花的效果图。但是,我发现通过放置战略打印语句,我的 paintComponent() 方法不会 运行 即使包装代码的条件语句得到满足。我还仔细检查了所有其他方法,以确保在正确的时间生成正确的值。在查看了我能找到的所有 JComponent 文献和问题后,恐怕我无法让它工作——这个问题很可能是由于我对该库不熟悉所致。话虽这么说,任何建议,无论多么基本,都将不胜感激。精简代码如下:
*也可能是摇摆计时器的问题,我不确定我是否使用正确
[fireworksCanvas.java]
public class fireworkCanvas extends JComponent implements ActionListener{
private static final long serialVersionUID = 1L;
private ArrayList<Ellipse2D> nodes = new ArrayList<Ellipse2D>();
private ArrayList<Line2D> cNodes = new ArrayList<Line2D>();
private ArrayList<QuadCurve2D> bCurves = new ArrayList<QuadCurve2D>();
private int[] arcX;
private int[] arcY;
private Color userColor;
private Random rand = new Random();
private int shellX, shellY, fType, theta, velocity;
private Timer timer;
private int time;
private double g = -9.8; //gravity in m/s
public boolean explosivesSet;
public fireworkCanvas() {
time = rand.nextInt(3000) + 2000;
timer = new Timer(time, this); // 5 seconds
timer.start();
fType = 0;
}
@Override
public void paintComponent(Graphics g){
if (explosivesSet) {
System.out.println("fType" + fType);
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g.setColor(Color.BLACK);
g.drawPolyline(arcX, arcY, arcX.length);
for (Ellipse2D e : nodes) {
System.out.println("painting nodes"); // NEVER PRINTS
g.setColor(userColor);
g.fillOval(shellX + (int) e.getX(), shellY + (int) e.getY(), (int) e.getWidth(), (int) e.getHeight());
}
for (Line2D l: cNodes) {
System.out.println("painting cNodes"); // NEVER PRINTS
g.setColor(determineColor("l"));
g.drawLine(shellX + (int) l.getX1(), shellY + (int) l.getY1(), shellX + (int) l.getX2(), shellY + (int) l.getY2());
}
for (QuadCurve2D c: bCurves) {
System.out.println("painting curves"); // NEVER PRINTS
g.setColor(determineColor("c"));
g2D.draw(c);
}
}
}
public Color determineColor(String type) {
// returns color
}
public void setExplosives() {
if (fType != 5 && fType != 0) {
nodes.clear(); // clears three array lists with FW components
cNodes.clear(); // these are the components to paint for the
bCurves.clear(); // firework explosion graphic
setArc(); // stores path of shell for a polyLine to be drawn
// builds and generates components for FW based on type chosen (fType)
setExplosivesSet(true);
repaint();
}
}
public void setArc() {
// builds int[] for shellX, shellY
}
@Override
public void actionPerformed(ActionEvent e) {
// nothing is here??
// should I use the action performed in some way?
}
[GUI.java]
public class GUI extends JFrame implements ActionListener, ChangeListener, ItemListener, MouseListener{
private static JFrame canvasFrame = new JFrame("Canvas");
private fireworkCanvas canvas = new fireworkCanvas();
private Choice fireworkChooser = new Choice();
private JSlider launchAngle = new JSlider();
private JSlider velocity = new JSlider();
private JSlider r = new JSlider();
private JSlider g = new JSlider();
private JSlider b = new JSlider();
private JPanel panel = new JPanel();
private JButton button = new JButton("Fire!");
private JLabel launchLabel = new JLabel("Launch Angle ");
private JLabel velocityLabel = new JLabel("Velocity ");
private JLabel rLabel = new JLabel("Red ");
private JLabel gLabel = new JLabel("Green ");
private JLabel bLabel = new JLabel("Blue ");
public static int fHeight = 500;
public static int fWidth = 500;
public GUI() {
this.add(panel);
panel.add(button);
panel.add(fireworkChooser);
panel.add(launchAngle);
panel.add(launchLabel);
panel.add(velocity);
panel.add(velocityLabel);
panel.add(r);
panel.add(rLabel);
panel.add(g);
panel.add(gLabel);
panel.add(b);
panel.add(bLabel);
addActionListener(this);
BoxLayout bl = new BoxLayout(getContentPane(), BoxLayout.Y_AXIS);
setLayout(bl);
fireworkChooser.addItemListener(this);
launchAngle.addChangeListener(this);
velocity.addChangeListener(this);
r.addChangeListener(this);
g.addChangeListener(this);
b.addChangeListener(this);
button.addActionListener(this);
fireworkChooser.add("Firework 1");
fireworkChooser.add("Firework 2");
fireworkChooser.add("Firework 3");
fireworkChooser.add("Firework 4");
fireworkChooser.add("Super Firework");
launchAngle.setMinimum(1);
launchAngle.setMaximum(90);
velocity.setMinimum(1);
velocity.setMaximum(50);
r.setMinimum(0);
r.setMaximum(255);
g.setMinimum(0);
g.setMaximum(255);
b.setMinimum(0);
b.setMaximum(255);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 200);
}
@Override
public void stateChanged(ChangeEvent e) {
// sets FW variables
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
canvas.setfType(fireworkChooser.getSelectedIndex()+1);
canvas.setExplosives();
canvas.repaint();
canvas.setExplosivesSet(false);
System.out.println("button fired");
}
}
public static void createAndShowGUI() {
GUI gui = new GUI();
gui.pack();
gui.setLocationRelativeTo(null);
gui.setVisible(true);
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fireworkCanvas canvas = new fireworkCanvas();
canvasFrame.pack();
canvasFrame.add(canvas);
canvasFrame.setLocationRelativeTo(null);
canvasFrame.setVisible(true);
canvasFrame.setSize(fWidth, fHeight);
canvasFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
首先:
public fireworkCanvas()
Class 名称应以大写字符开头。您代码中的所有其他 classes 都遵循此规则。通过实例学习。
private Choice fireworkChooser = new Choice();
选择一个 AWT 组件不要在 Swing 应用程序中混合使用 AWT 组件。使用 JComboBox
.
that my paintComponent() method does not run
fireworkCanvas canvas = new fireworkCanvas();
canvasFrame.pack();
canvasFrame.add(canvas);
你在 pack() 框架之后将 canvas 添加到框架,所以 canvas 的大小是 (0, 0) 并且没有任何东西可以绘制。
应该在 pack() 之前将 canvas 添加到框架中,并且您应该在 FireworkCanvas class 中实现 getPreferredSize()
以便 pack() 方法可以正常工作。
阅读有关 Custom Painting 的 Swing 教程部分,了解基础知识和工作示例,以帮助您入门。