Lines
The Java 2D api provides classes for drawing points, lines, cursves, and rectangles. These geometry classes are part of the java.awt.geom package. A line is a graphics primitive that connects two points.
import java.awt.*;
import java.awt.geom.Line2D;
import javax.swing.*;
public class App extends JFrame {
public static void main(String[] args) {
App frame = new App();
frame.setBounds(200, 200, 400, 300);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
}
public App() {
JPanel p = new JPanel(){
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// Vertical line * Look Here
g2.setColor(Color.black); // color black default
g2.draw(new Line2D.Double(50, 10, 50, 100));
// x1, y1, x2, y2
// Oblique line
g2.setColor(Color.blue);
g2.draw(new Line2D.Double(100, 10, 120, 100));
// Graph
for (int i=0; i<100; i += 10) {
g2.setColor(Color.red);
g2.setStroke(new BasicStroke(5));
int x1 = 150 + i;
int x2 = x1;
int y1 = 10 + i;
int y2 = 150;
g2.draw(new Line2D.Double(x1, y1, x2, y2));
}
}
};
add(p);
}
}
Gradient
To draw a gradient use GradientPaint class.
import java.awt.*;
import java.awt.geom.Line2D;
import javax.swing.*;
public class App extends JFrame {
public static void main(String[] args) {
App frame = new App();
frame.setBounds(200, 200, 400, 300);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
}
public App() {
add( new JPanel() {
@Override
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
Graphics2D g = (Graphics2D) g1;
g.setPaint( // Look Here
new GradientPaint(50, 50, Color.green, 50, 150, Color.red)
);
g.setStroke(new BasicStroke(3));
int start = 50;
int height = 150;
int x1 = 50;
int x2 = 50;
int y1 = 50;
int y2 = 150;
for (int i=0; i<200; i += 10) {
x1 = start + i;
x2 = x1;
y1 = (i < 100) ? start + i : y1 - 10;
y2 = y2;
g.draw(new Line2D.Double(x1, y1, x2, y2));
}
}
});
}
}
Chart
Chat with grid and numbers.
import java.awt.*;
import java.awt.geom.Line2D;
import javax.swing.*;
public class App extends JFrame {
public static void main(String[] args) {
App frame = new App();
frame.setBounds(200, 200, 350, 250);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setTitle("Chart with Grid & Numbers");
frame.setVisible(true);
}
public App() {
add( new JPanel() {
@Override
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
Graphics2D g = (Graphics2D) g1;
int[][] data = new int[][]{ // Look Here
{1, 5},
{3, 15},
{4, 10},
{6, 13},
{7, 17},
};
addAxisGrid(g, data); // Axis & Grids
addChart(g, data); // Chart
}
});
}
private void addAxisGrid(Graphics2D g, int[][] data) {
int x = 20;
int y = 20;
int h = 200;
int w = 320;
g.setStroke(new BasicStroke(1));
g.setColor(Color.gray);
g.draw(new Line2D.Double(x, x, x, h)); // vertical ax
g.draw(new Line2D.Double(x, h, w, h)); // horizontal ax
for (int i=0; i<18; i++) {
// horizontal (grid) and vertical (numbers)
g.setColor(Color.decode("#dddddd")); // Look Here
g.draw(new Line2D.Double(x+2, h - 10 - i*10, w, h - 10 - i*10));
// horizontal ax
g.setColor(Color.gray);
if (i%5 == 0 && i > 0) {
g.setFont(new Font("Arial", 1, 10));
g.drawString(String.valueOf(i), i<10 ? 10 : 5, h+5-i*10);
// Look Here
}
}
for (int i=0; i<=30; i++) { // horizontal numbers
g.setColor(Color.gray);
if (i%5 == 0) {
g.setFont(new Font("Arial", 1, 10));
g.drawString(String.valueOf(i), i<10 ? x+i*10 : x+i*10-5, h+15);
}
}
}
// Look Here
private void addChart(Graphics2D g, int[][] data) {
g.setPaint(
new GradientPaint(50, 50, Color.green, 50, 150, Color.red)
);
g.setStroke(new BasicStroke(3));
int start = 30;
int height = 150;
int x1 = 20;
int x2 = 20;
int y1 = 20;
int y2 = 198;
for (int i=0; i<data.length; i++) {
int[] row = data[i];
int day = row[0];
int cnt = row[1];
x1 = start - 10 + day*10;
x2 = x1;
y1 = y2 - cnt*10;
y2 = y2;
g.draw(new Line2D.Double(x1, y1, x2, y2)); // Look Here
}
}
}
Add and delete records to the chart.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.*;
public class App extends JFrame {
private int x = 20;
private int y = 20;
private int height = 220;
private int weight = 320;
private int step = 0;
private Map<Integer, Integer> data =
new LinkedHashMap<Integer, Integer>(){{
put(1, 5);
put(3, 15);
put(4, 10);
put(6, 13);
put(7, 17);
}};
private JLabel labelDay = new JLabel("Day");
private JTextField textDay = new JTextField("5");
private JLabel labelNo = new JLabel("No");
private JTextField textNo= new JTextField("30");
private JButton buttonAdd = new JButton("Add");
private JButton buttonDelete = new JButton("Delete");
public static void main(String[] args) {
App frame = new App();
frame.setBounds(200, 200, 350, 320);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setTitle("Chart with Grid & Numbers");
frame.setVisible(true);
}
public App() {
setStep();
// Components
JPanel chart = new JPanel() {
@Override
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
Graphics2D g = (Graphics2D) g1;
addAxisAndGrid(g);
paintChart(g);
}
};
// Set font
Font font = new Font("Arial", Font.PLAIN, 12);
labelDay.setFont(font);
textDay.setFont(font);
labelNo.setFont(font);
textNo.setFont(font);
// Look Here
buttonAdd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addNewRecord();
setStep();
repaint();
}
});
// Look Here
buttonDelete.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int i = Integer.parseInt(textDay.getText());
System.out.println(i);
data.remove(i); // remove day
setStep();
repaint();
}
});
// Layout
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup()
.addComponent(chart)
.addGroup(layout.createSequentialGroup()
.addGap(20)
.addComponent(labelDay).addGap(5)
.addComponent(textDay).addGap(5)
.addComponent(labelNo).addGap(5)
.addComponent(textNo).addGap(5)
.addComponent(buttonAdd)
.addComponent(buttonDelete)
.addGap(20)
)
);
layout.setVerticalGroup(
layout.createSequentialGroup()
.addComponent(chart, 250, 250, 250)
.addGroup(
layout.createParallelGroup(GroupLayout.Alignment.CENTER
)
.addComponent(labelDay)
.addComponent(textDay)
.addComponent(labelNo)
.addComponent(textNo)
.addComponent(buttonAdd)
.addComponent(buttonDelete)
)
.addGap(20)
);
}
private void addNewRecord() {
int day = Integer.valueOf(textDay.getText());
int no = Integer.valueOf(textNo.getText());
data.put(day, no);
}
private void setStep() {
int max = 0;
for (Object i : data.keySet()) {
int cnt = data.get(i);
if (cnt > max) max = cnt;
}
step = 200/max;
}
private void addAxisAndGrid(Graphics2D g) {
g.setStroke(new BasicStroke(1));
g.setColor(Color.gray);
g.draw(new Line2D.Double(x, x, x, height)); // vertical ax
g.draw(new Line2D.Double(x, height, weight, height)); // horizontal ax
int noOfGrids = (height-y)/step;
for (int i=0; i<noOfGrids; i++) { // Horizontal Grid
if (i < noOfGrids) { // skip last
g.setColor(Color.decode("#dddddd"));
g.draw(new Line2D.Double(
x+2, height-step-i*step, weight, height-step-i*step)
); // horizontal ax
}
}
for (int i=0; i<=noOfGrids; i++) { // Vertical Numbers
if (i%5 == 0 && i > 0) {
g.setColor(Color.gray);
g.setFont(new Font("Arial", 1, 10));
g.drawString(
String.valueOf(i), i<10 ? x-10 : x-15, height+5-i*step
);
}
}
for (int i=0; i<=30; i++) { // horizontal numbers (30 days)
g.setColor(Color.gray);
if (i%5 == 0) {
g.setFont(new Font("Arial", 1, 10));
g.drawString(
String.valueOf(i), i<10 ? x+i*10 : x+i*10-5, height+15
);
}
}
}
private void paintChart(Graphics2D g) {
g.setPaint(new GradientPaint(x, y, Color.green, x, height, Color.red));
g.setStroke(new BasicStroke(3));
for (Object i : data.keySet()) {
int day = (Integer) i;
int cnt = data.get(i);
int x1 = x + day*10;
int x2 = x1;
int y2 = height-2;
int y1 = y2 - cnt*step;
g.draw(new Line2D.Double(x1, y1, x2, y2));
}
}
}
Add a line using mouse (drag mouse up), double click on line to delete it.
Drag window to resize graph.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import java.util.*;
import javax.swing.*;
public class App extends JFrame {
final static private App frame = new App();
public static void main(String[] args) {
frame.setBounds(200, 200, 350, 280);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setTitle("Chart (mouse dragged to draw line)");
frame.setVisible(true);
}
public App() {
final Chart chart = new Chart();
add(chart);
getRootPane().addComponentListener(new ComponentAdapter() {
// Look Here
@Override public void componentResized(ComponentEvent e) {
Dimension d = frame.getSize();
chart.step = (d.height - 80)/20;
chart.height = d.height - 60;
chart.width = d.width - 30;
chart.stepMonth = (chart.width)/chart.days;
}
});
}
}
class Chart extends JPanel {
private int x = 20;
private int y = 20;
public int height = 220;
public int width = 320;
public int days = 30;
private int currDay = 0;
public int step = 10;
public int stepMonth = (width - 20)/days;
private int stroke = 3;
private final Map<Integer, Integer> data =
new LinkedHashMap<Integer, Integer>(){{
put(1, 5);
put(3, 15);
put(4, 10);
put(6, 13);
put(7, 17);
}};
{
addMouseListener(new MouseAdapter(){
// Look Here
@Override public void mousePressed(MouseEvent e) {
currDay = (e.getX() - x)/stepMonth;
if (e.getButton() == 1) { // Left clicked
if (data.get(currDay) == null) { // Not exists
if (e.getY() == height - y) {
addNewRecord(String.valueOf(currDay), "1");
repaint();
}
}
}
if (e.getClickCount() == 2) { // Double click
if (data.get(currDay) != null) { // If exists
deleteRecord(currDay); // Delete it
repaint();
}
}
}
});
// Look Here
addMouseMotionListener(new MouseMotionAdapter(){
@Override public void mouseDragged(MouseEvent e) {
if (currDay > 0) {
data.put(currDay, (height - e.getY())/step);
repaint();
}
}
});
}
@Override
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
Graphics2D g = (Graphics2D) g1;
addAxisAndGrid(g);
paintChart(g);
}
private void addAxisAndGrid(Graphics2D g) {
g.setStroke(new BasicStroke(1));
g.setColor(Color.gray);
g.draw(new Line2D.Double(x, x, x, height)); // Vertical ax
g.draw(new Line2D.Double(x, height, width, height)); // Horizontal ax
int noOfGrids = (height-y)/step;
for (int i=0; i<noOfGrids; i++) { // Horizontal Grid
if (i < noOfGrids) { // skip last
g.setColor(Color.decode("#dddddd"));
g.draw(new Line2D.Double(
x+2, height-step-i*step, width, height-step-i*step)
); // Horizontal grids
}
}
for (int i=0; i<=noOfGrids; i++) { // Vertical Numbers
if (i%5 == 0 && i > 0) {
g.setColor(Color.gray);
g.setFont(new Font("Arial", 1, 10));
g.drawString(
String.valueOf(i), i<10 ? x-10 : x-15, height+5-i*step
);
}
}
for (int i=0; i<=days; i++) { // Horizontal numbers (30 days)
g.setColor(Color.gray);
g.setFont(new Font("Arial", 1, 10));
if (i%2 == 0) {
g.drawString(
String.valueOf(i),
i<10 ? x+i*stepMonth : x+i*stepMonth-5, height+15
);
}
}
}
private void paintChart(Graphics2D g) { // Chart
g.setPaint(new GradientPaint(x, y, Color.green, x, height, Color.red));
g.setStroke(new BasicStroke(stroke));
for (Object i : data.keySet()) { // Vertical lines (chart values)
int day = (Integer) i;
int cnt = data.get(i);
int x1 = x + day*stepMonth;
int x2 = x1;
int y2 = height-2;
int y1 = y2 - cnt*step;
g.draw(new Line2D.Double(x1, y1, x2, y2));
}
}
public void addNewRecord(String d, String n) {
int day = Integer.valueOf(d);
int no = Integer.valueOf(n);
data.put(day, no);
}
public void deleteRecord(int day) {
data.remove(currDay);
}
}
Mouse Line
Mouse events notify when the user uses the mouse. The MouseListener interface implements mousePressed and mouseReleased functions.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.*;
public class App extends JFrame {
public static void main(String[] args) {
App frame = new App();
frame.setBounds(200, 200, 300, 200);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setTitle("Draw line with the mouse");
frame.setVisible(true);
}
public App() {
JPanel p = new JPanel() {
Point start = null; // Look Here
Point end = null;
{
addMouseListener(new MouseAdapter() { // Look Here
@Override public void mousePressed(MouseEvent e) {
start = e.getPoint();
}
@Override public void mouseReleased(MouseEvent e) {
start = null;
end = null;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override public void mouseDragged(MouseEvent e) {
end = e.getPoint();
repaint();
}
});
}
@Override public void paint(Graphics g) {
super.paint(g);
if (start != null) {
g.setColor(Color.red); // Look Here
g.drawLine(start.x, start.y, end.x, end.y);
}
}
};
add(p);
}
}
Mouse gradient
Drawing gradient line with the mouse (chart).
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Line2D;
import javax.swing.*;
public class App extends JFrame {
public static App frame = new App();
public static void main(String[] args) {
frame.setBounds(200, 200, 350, 320);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setTitle("Chart with Grid & Numbers");
frame.setVisible(true);
}
public App() {
final Chart chart = new Chart();
chart.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) { // * Look Here * //
chart.drawLine(e.getY());
frame.repaint();
}
});
add(chart);
}
}
class Chart extends JPanel {
public int x = 50;
public int y = 50;
public int height = 200;
public int weight = 30;
public Line2D line = new Line2D.Double(x, y, x, height);
@Override
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
Graphics2D g = (Graphics2D) g1;
g.setPaint(new GradientPaint(x, y, Color.green, x, height, Color.red));
g.setStroke(new BasicStroke(weight));
g.draw(line);
}
public void drawLine(int yy) {
line = new Line2D.Double(50, yy, 50, height);
}
}