繪製後如何填充多邊形 (How to fill a polygon after drawing)


問題描述

繪製後如何填充多邊形 (How to fill a polygon after drawing)

我想畫一個多邊形然後填充它。我的代碼如下所示:

@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")) {

            }

但我真的不知道怎麼做。請幫忙。

PS 沒有fillPolygon函數,還有其他方法可以填充多邊形嗎?


參考解法

方法 1:


UPDATE: added Timer‑based renderer to display the lines one at a time at the end of this answer.


Firstly, I recommend @Overriding paintComponent(), instead of paint().

Secondly, to draw a Polygon then fill a Polygon, you literally just stack the commands as the Graphics context will paint in order.

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());
}

If you override paintComponent() for your chosen object (I usually use a JPanel for custom painting) all you then have to do is call repaint() to refresh the view (not that you should need in this instance).

To recap, override paintComponent() on a JPanel, stack your drawPolygon / fillPolygon calls and if you want to control when your polygon is displayed, handle that by adding / removing the JPanel as necessary from your application. Or set a boolean flag that indicates "toBeDrawn" or not and modify your paintComponent code so that it only draws the polygons when this is set to true.


UPDATE: example runnable class below demonstrated Timer‑based drawLine() functionality.


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;
    }

}

(by user5274714Gorbles)

參考文件

  1. How to fill a polygon after drawing (CC BY‑SA 2.5/3.0/4.0)

#java #graphics #fill #polygon






相關問題

電子郵件地址中帶有 + 字符的 Java 郵件 (Java mail with + character in email address)

如何快速原型化 Java 代碼? (How to quickly prototype Java code?)

如何使用 Maven 在目標(SVN-)服務器上創建 Javadoc? (How to create Javadoc on the target (SVN-) server using Maven?)

為什麼檢查二叉樹有效性的解決方案不起作用? (Why the solution for checking the validity of binary tree is not working?)

Selenium webdriver通過第一個數字找到texy (Selenium webdriver find texy by first digits)

setOnClickListener 沒有在圖像視圖上被調用 (setOnClickListener is not getting called on image view)

繪製多邊形:找不到錯誤 (Drawing Polygon : unable to find error)

半透明 JButton:對像出現在背景中 (Semi-Transparent JButton: Objects appear in Background)

比較同一數組的元素 (Compare elements of the same array)

Java 屏幕截圖小程序 (Java screen capture applet)

Minecraft 1.8.9 Forge Modding 的Java 開發工具包,需要什麼JDK/JRE,代碼是否正確? (Java Development Kit with Minecraft 1.8.9 Forge Modding, What JDK/JRE Is Needed, Is Code Correct?)

java while (resultset.next()) 不返回同一列中的所有數據 (java while (resultset.next()) does not return all data in the same column)







留言討論