无法在同一JPanel上绘制Rectangle2D和Path2D,可能重叠?

时间:2015-04-03 19:51:32

标签: java swing awt graphics2d

好吧这可能是一个愚蠢的问题,也许我错过了一些东西。我不是Java新手,但我不是专家。长话短说,我写了一个空气压缩火箭轨迹模拟(不是它不是家庭作业)。这是我的嘿嘿我想学习Java所以让我试试这个"程序。它以图形方式模拟距离,最大高度等。现在我正在尝试添加第二个面板(JFrame)以显示战斗中的火箭稳定性。

我在JFrame中有一个JPanel。在其中,我有DrawPanel类来完成绘图。我想画一个火箭。所以我需要一个矩形体,鳍,鼻锥等。现在我已经编写了一个使用Rectangle2D对象绘制体的方法,以及一个使用Path2D对象绘制2个鳍的方法。现在,当我在我的绘画方法中同时使用它时,它只会绘制第一个。我已经翻过它们,它只会先画出任何东西。现在有些图形2D对象,他们有空白占据整个面板,或者我完全遗漏了一些东西。

我用与我的主程序相同的设计模式编写了一个测试程序,以便更好地尝试在不启动main的情况下解决这个问题。它比你们通常想要的要长一点但是如果问题不在DrawPanel类中,我将包含它并且它会编译并运行。此外,我确信我不是最有效的方式,所以任何提示或指针也是受欢迎的。谢谢你们

/*
* Test program to replicate issue with main program
* Trying to draw multiple shapes, one ends up overlapping the other
*/
package shapetest;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ShapeTest extends JFrame {
    private static final long serialVersionUID = 1L;

    JPanel panel = new JPanel();
    DrawPanel drawPanel = new DrawPanel();
    Rectangle2D rocket = new Rectangle2D.Double();
    Path2D.Double topFin = new Path2D.Double();
    Path2D.Double bottomFin = new Path2D.Double();

    int scaler = 20;
    double rocketX = 0;
    double rocketY = 0;

    class DrawPanel extends JPanel {
        private static final long serialVersionUID = 1L;
        double rocketLength = 36;
        double rocketWidth = 1.5;

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g.create();
            paint2D(g2);

            g2.dispose();
        }

        protected void paint2D(Graphics2D g2) {

            setBackground(Color.WHITE); // Set graph background color
            g2.setColor(Color.BLACK);
            g2.setStroke(new BasicStroke(1.0f));
            g2.setFont(new Font("SansSerif", Font.BOLD, 18));
            //If I reverse the order of these two methods, it will draw
            //the rocket tube and not the fin
            drawTwoFins(g2);
            drawRocketTube(g2, rocketLength, rocketWidth);
        }

        private void drawRocketTube(Graphics2D g, double rL, double rW) {            
            double rocketL = rL * scaler;
            double rocketW = rW * scaler;
            rocketX = ((drawPanel.getWidth() / 2) - ((rocketLength * scaler) / 2));
            rocketY = ((drawPanel.getHeight() / 2) - ((rocketWidth * scaler) / 2));

            rocket.setRect(rocketX, rocketY, rocketL, rocketW);
            g.draw(rocket);

            g.dispose();
        }

        private void drawTwoFins(Graphics2D g) {
            BasicStroke stroke = new BasicStroke(2.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL);
            g.setStroke(stroke);

            rocketX = ((drawPanel.getWidth() / 2) - ((rocketLength * scaler) / 2));
            rocketY = ((drawPanel.getHeight() / 2) - ((rocketWidth * scaler) / 2));

            double topStartX = (rocketX + (4 * scaler));
            double topStartY = rocketY;
            double bottomStartX = (rocketX + (4 * scaler));
            double bottomStartY = (rocketY + (rocketWidth * scaler));

            double xTopFin[] = {topStartX, (topStartX - (2 * scaler)), (topStartX - (5 * scaler)), (topStartX - (3 * scaler))};
            double yTopFin[] = {topStartY, (topStartY - (2 * scaler)), (topStartY - (2 * scaler)), topStartY};
            double xBottomFin[] = {bottomStartX, (bottomStartX - (2 * scaler)), (bottomStartX - (5 * scaler)), 
                               (bottomStartX - (3 * scaler))};
            double yBottomFin[] = {bottomStartY, (bottomStartY + (2 * scaler)), (bottomStartY + (2 * scaler)), bottomStartY};

            topFin.moveTo(xTopFin[0], yTopFin[0]);
            bottomFin.moveTo(xBottomFin[0], yBottomFin[0]);

            for (int i = 1; i < xTopFin.length; i++) {
                topFin.lineTo(xTopFin[i], yTopFin[i]);
                bottomFin.lineTo(xBottomFin[i], yBottomFin[i]);
            }

            g.draw(topFin);
            g.draw(bottomFin);
            g.dispose();
        }    
    }    

    private void initComponents() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        add(panel);
        panel.setPreferredSize(new Dimension(850, 300));
        panel.setLayout(new BorderLayout());
        panel.add(drawPanel, BorderLayout.CENTER);
        pack();
        setLocationRelativeTo(null);
    }

    public ShapeTest() {
        initComponents();
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new ShapeTest().setVisible(true);
            }
        });
    }  
}

1 个答案:

答案 0 :(得分:2)

所有绘图方法都以g.dispose()结尾,但是当你这样做时,下一个绘图方法完全没有运气,因为你已经有效地删除了 Graphics对象,所以他们无所事事。

解决方案:不要继续处理Graphics对象。

一些一般规则

  • 永远不要丢弃JVM提供给您的Graphics对象。
  • 处理使用它们时创建的Graphics对象,但仅在完成时才处理。你在每个方法的最后处理它们,完全擦除它以用于下一个方法。在这里,你只应该在g2和paintComponent方法的末尾调用一次dispose。
  • 您应该在paintComponent方法的末尾处理创建的g2变量一次

就此而言,我不确定你是否需要复制Graphics对象,如果你不通过create()方法复制它,那么根本不应该处理它。 / p>