java - 在由单独的 GUI 更改的 JFrame Canvas 上使用 PaintComponent()

标签 java swing jframe paintcomponent jcomponent

我正在尝试创建一个 JComponent 应用程序,它使用两个 JFrame,一个框架具有可更改的 slider 和文本字段,用于在第二个框架上图形显示烟花。当按下“开火”按钮时,应该会出现烟花的渲染效果。但是,通过放置策略性打印语句,我发现即使满足包装代码的条件语句,我的 PaintComponent() 方法也不会运行。我还仔细检查了所有其他方法,以确保在正确的时间生成正确的值。在浏览了我能找到的所有 JComponent 文献和问题之后,我担心我无法让它工作 - 这个问题很可能是由于我对这个库不熟悉而导致的。话虽这么说,任何建议,无论多么基本,都将不胜感激。精简代码如下:

* Swing 计时器也可能是问题,因为我不确定我是否正确使用了它

[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()

类名称应以大写字符开头。代码中的所有其他类都遵循此规则。通过示例学习。

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) 并且没有任何内容可绘制。

Canvas 应该在 pack() 之前添加到框架中,并且您应该在 FireworkCanvas 类中实现 getPreferredSize() ,以便 pack() 方法可以正常工作。

阅读 Swing 教程中关于 Custom Painting 的部分了解帮助您入门的基础知识和工作示例。

关于java - 在由单独的 GUI 更改的 JFrame Canvas 上使用 PaintComponent(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47298471/

相关文章:

java - 如何识别 GUI 应用程序中的 java swing 按钮并在 eclipse 中使用另一个 Java 代码单击该按钮?

java - 当我设置新的 Synthetica 主题时,为什么我的 JFrame 没有重新绘制?

java - 如何将 netbeans 中的“确定”按钮设为空

java - 为什么这是垃圾收集

java - 如何使用 getWidth() 和 getHeight() 在 java 中使星形居中

Java:将类导入到 Jframe

java - 使用 CAS 代替同步

java - KeyTyped 方法说 TextField 为空...但实际上不是

java - JTable 中的乘法值

java - 关于在 Swing 页面上添加容器的问题