如何在绘制

时间:2015-11-17 11:19:43

标签: java graphics polygon fill

我想绘制一个多边形,然后填充它。我的代码如下所示:

@Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;

        if (polygons.isEmpty()) {
            return;
        }

        for (int j = 0; j < polygons.size(); j++) {

            ArrayList<Point> ActPoint = polygons.get(j);

            if (ActPoint.isEmpty()) {
                return;
        }

        Point a = new Point();
        a = ActPoint.get(0);
        for (int p = 0; p < ActPoint.size(); p++) {
            Point b = ActPoint.get(p);
            Line2D.Double line = new Line2D.Double(a, b);
            g2d.draw(line);
            a = b;
        }

    }


    for (int j = 0; j < polygons.size(); j++) {
        ArrayList<Integer> listX = new ArrayList<>();  
        ArrayList<Integer> listY = new ArrayList<>();

        for (int p = 0; p < polygons.get(j).size(); p++) {
         listX.add(polygons.get(j).get(p).x );
         listY.add(polygons.get(j).get(p).y );
        }
        g.fillPolygon(convertIntegers(listX),convertIntegers (listY), polygons.get(j).size());
    }
}

我不知道如何制作代码,只有在我完成绘制后才填充多边形。就像我想要一个有5个边的多边形一样,只有在我完成所有边的绘制后才能填充多边形。此外,我只想在我按下按钮时填充多边形。我试图创建一个函数

public void fill (Graphics g){
for (int j = 0; j < polygons.size(); j++) {
            ArrayList<Integer> listX = new ArrayList<>();  
            ArrayList<Integer> listY = new ArrayList<>();

            for (int p = 0; p < polygons.get(j).size(); p++) {
             listX.add(polygons.get(j).get(p).x );
             listY.add(polygons.get(j).get(p).y );
            }
                g.fillPolygon(convertIntegers(listX),convertIntegers (listY), polygons.get(j).size());


} 

我试着在这里打电话

if (e.getActionCommand().equals("Fill")) {

            }

但我真的不知道怎么做。请帮忙。

P.S。是否还有其他方法可以在没有fillPolygon函数的情况下填充多边形?

1 个答案:

答案 0 :(得分:1)

UPDATE :添加了基于计时器的渲染器,以便在此答案结束时一次显示一行。

首先,我建议使用@Overriding paintComponent(),而不是paint()

其次,要绘制Polygon然后填充Polygon,您只需将命令堆叠起来,Graphics上下文将按顺序绘制。

for(int j = 0; j < polygons.size(); j++) {
    ArrayList<Integer> listX = new ArrayList<>();  
    ArrayList<Integer> listY = new ArrayList<>();

    for (int p = 0; p < polygons.get(j).size(); p++) {
        listX.add(polygons.get(j).get(p).x);
        listY.add(polygons.get(j).get(p).y);
    }

    // this may need slight conversion depending on parameters required
    g.drawPolygon(convertIntegers(listX), convertIntegers(listY), polygons.get(j).size());
    g.fillPolygon(convertIntegers(listX), convertIntegers(listY), polygons.get(j).size());
}

如果您为所选对象覆盖paintComponent()(我通常使用JPanel进行自定义绘制),那么您只需调用repaint()来刷新视图(不是您应该需要的)在这个例子中)。

回顾一下,覆盖paintComponent()上的JPanel,堆叠drawPolygon / fillPolygon个来电,如果要控制多边形的显示时间,请通过添加来处理/从您的申请中删除JPanel设置一个boolean标记,指示“toBeDrawn”,并修改您的paintComponent代码,使其仅在设置为true时绘制多边形。

更新:下面的示例runnable类演示了基于计时器的drawLine()功能。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test extends JPanel {

    private static final long serialVersionUID = 1L;

    private Timer lineTimer;

    private Polygon toBeFilled;
    private ArrayList<Point[]> inactiveLines;
    private ArrayList<Point[]> activeLines;
    private boolean toBeDrawn = false;

    public static void main(String[] args) {
        JFrame frame = new JFrame("Test");
        frame.getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));

        Test test = new Test();
        frame.add(test);
        frame.pack();
        frame.setVisible(true);

        test.getLineTimer().start();
    }

    public Test() {
        super();

        setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
        setPreferredSize(new Dimension(480, 340));
        setBackground(Color.BLACK);

        int midpointX = getPreferredSize().width / 2;
        int midpointY = getPreferredSize().height / 2;
        int lineWidth = 20;

        // let's make a square
        toBeFilled = new Polygon();
        // let's centre this square nicely
        toBeFilled.addPoint(midpointX - (lineWidth / 2), midpointY - (lineWidth / 2)); // top-left
        toBeFilled.addPoint(midpointX + (lineWidth / 2), midpointY - (lineWidth / 2)); // top-right
        toBeFilled.addPoint(midpointX + (lineWidth / 2), midpointY + (lineWidth / 2)); // bottom-right
        toBeFilled.addPoint(midpointX - (lineWidth / 2), midpointY + (lineWidth / 2)); // bottom-left

        inactiveLines = new ArrayList<Point[]>();
        activeLines = new ArrayList<Point[]>();
        for(int n = 0; n < 4; n++) {
            Point[] points = new Point[2];
            if(n < 3) {
                points[0] = new Point(toBeFilled.xpoints[n], toBeFilled.ypoints[n]);
                points[1] = new Point(toBeFilled.xpoints[n + 1], toBeFilled.ypoints[n + 1]);
            } else {
                // loop back to the first point in the array
                points[0] = new Point(toBeFilled.xpoints[n], toBeFilled.ypoints[n]);
                points[1] = new Point(toBeFilled.xpoints[0], toBeFilled.ypoints[0]);
            }

            inactiveLines.add(points);
        }

        ActionListener lineAction = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(inactiveLines.get(inactiveLines.size() - 1) != null) {
                    int count = 0;
                    for(Point[] pArray : inactiveLines) {
                        if(pArray != null) {
                            activeLines.add(new Point[] { pArray[0], pArray[1] });
                            inactiveLines.set(count, null);
                            repaint();
                            break;
                        }

                        count++;
                    }
                } else {
                    // we've exhausted the line array, so now it's time to fill it
                    toBeDrawn = true;
                    lineTimer.stop();
                    repaint();
                }
            }           
        };

        lineTimer = new Timer(1000, lineAction);
    }

    @Override
    public void paintComponent(Graphics g) {
        // useful for animation
        Toolkit.getDefaultToolkit().sync();
        super.paintComponent(g);
        if(toBeDrawn) {
            doFillPainting(g);
        } else {
            doLinePainting(g);
        }
    }

    private void doFillPainting(Graphics g) {
        // Graphics2D is more advanced than the older Graphics API, and more reliable
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.WHITE);
        if(toBeFilled != null) {
            g2d.fillPolygon(toBeFilled);
        }
    }

    private void doLinePainting(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.WHITE);
        for(Point[] activeLine : activeLines) {
            g2d.drawLine(activeLine[0].x, activeLine[0].y, activeLine[1].x, activeLine[1].y);
        }
    }

    public Timer getLineTimer() {
        return lineTimer;
    }

    public void setLineTimer(Timer lineTimer) {
        this.lineTimer = lineTimer;
    }

    public Polygon getToBeFilled() {
        return toBeFilled;
    }

    public void setToBeFilled(Polygon toBeFilled) {
        this.toBeFilled = toBeFilled;
    }

    public boolean isToBeDrawn() {
        return toBeDrawn;
    }

    public void setToBeDrawn(boolean toBeDrawn) {
        this.toBeDrawn = toBeDrawn;
    }

}