Is there any benefit to calling drawPolyline()
versus iterating through each line and calling drawLine()
in the Graphics2D
class?
For example:
graphics2d.drawPolyline(xPoints, yPoints, nPoints);
versus:
for (MyBean line : myBeans) {
graphics2d.drawLine(line.getX1Point(), line.getY1Point(), line.getX2Point(), line.getY2Point());
}
Is the first a convenience method for the second?
Fairly new to AWT. (I realize that the first one may be more concise.)
Edit: I call BufferedImage.createGraphics()
for the implementation of Graphics2D
.
There is an important difference: With drawPolyline
you are drawing a single polyline. With drawLine
you are drawing individual lines. So far, so obvious. But what does it mean?
The difference mainly shows up when assigning a "non-trivial" Stroke
to the graphics object - usually, a certain BasicStroke
. This receives several parameters in the constructor. The important one regarding your question is the join
parameter. It can be JOIN_BEVEL
, JOIN_METER
and JOIN_ROUND
. It determines how two connected lines are joined. And this, obviously, can only be applied when it is known that the lines are connected, which is only the case in the drawPolyline
call. It simply can not be applied for individual drawLine
calls.
The following is a screenshot showing this difference. It uses a stroke with a witdh of 15 and a join=BasicStroke.JOIN_ROUND
. The left part is drawn with drawPolyline
, and the right one is drawn as individual lines:
drawPolyline
anyhow...... because it is somehow out-dated and has several shortcomings. First of all, it is a hassle to create the arrays that are required for calling it. And importantly, it only accepts int[]
arrays.
The whole Java 2D painting infrastructure was originally focussing on int
coordinates, like in Graphics#drawLine(int,int,int,int)
. This has been generalized, and the Graphics2D
methods allow a much greater flexibility here. So the usual way to draw a polyline nowadays would be to create a Shape
object containing the polyline. In most cases, this will be a Path2D
instance:
Path2D path = new Path2D.Double();
path.moveTo(x0,y0);
path.lineTo(x1,y1);
path.lineTo(x2,y2);
...
graphics2D.draw(path);
However, just for reference, here is the code that was used to create the above image:
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DrawLineVsDrawPolyline
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame("");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new BorderLayout());
class Line
{
int x1, y1, x2, y2;
Line(int x1, int y1, int x2, int y2)
{
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public int getX1Point()
{
return x1;
}
public int getY1Point()
{
return y1;
}
public int getX2Point()
{
return x2;
}
public int getY2Point()
{
return y2;
}
}
int xPoints[] = new int[] { 100, 150, 200 };
int yPoints[] = new int[] { 100, 250, 100 };
int nPoints = xPoints.length;
List<Line> lines = new ArrayList<Line>();
for (int i0=0; i0<nPoints-1; i0++)
{
int i1 = i0+1;
int x1 = xPoints[i0];
int y1 = yPoints[i0];
int x2 = xPoints[i1];
int y2 = yPoints[i1];
lines.add(new Line(x1,y1,x2,y2));
}
JPanel panel = new JPanel()
{
@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
g.setColor(Color.RED);
g.setStroke(new BasicStroke(20.0f,
BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND));
g.drawPolyline(xPoints, yPoints, nPoints);
g.translate(200, 0);
for (Line line : lines) {
g.drawLine(
line.getX1Point(), line.getY1Point(),
line.getX2Point(), line.getY2Point());
}
}
};
f.getContentPane().add(panel, BorderLayout.CENTER);
f.setSize(500,500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}