2015-11-17 5 views
0

Я хочу нарисовать многоугольник, а затем заполнить его. Мой код выглядит следующим образом:Как заполнить многоугольник после рисования

@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

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 для пользовательских живописи) все, что вам тогда нужно сделать, это перекрасить вызов(), чтобы обновить представление (не то, что вы должны нуждаться в данном случае) ,

Напомним, переопределить paintComponent() на JPanel, стек вашего drawPolygon/fillPolygon вызовы и если вы хотите, чтобы контролировать, когда отображается ваш многоугольник, обрабатывать, что путем добавления/удаления JPanel по мере необходимости из вашего приложения. Или установите флаг boolean, указывающий «toBeDrawn» или нет, и измените свой код paintComponent так, чтобы он рисовал только полигоны, если для этого параметра установлено значение true.


ОБНОВЛЕНИЕ: Пример работоспособный класс ниже продемонстрировал Таймер на основе 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; 
    } 

} 
+0

спасибо, но я хочу нарисовать многоугольник построчно, а не все сразу. – user5274714

+0

Итак, перед логикой 'fillPolygon()' поставить логику 'drawLine()' в том же цикле. Любой набор заказов на тиражирование выполняется в том порядке, в котором они написаны (и это не дорогостоящие операции, поэтому не должно быть задержки). – Gorbles

+0

Обновлен мой ответ! :) – Gorbles

Смежные вопросы