package com.ssaurel.swingpaint;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JComponent;
/**
* Component for drawing !
*
* #author sylsau
*
*/
public class DrawArea extends JComponent {
// Image in which we're going to draw
private Image image;
// Graphics2D object ==> used to draw on
private Graphics2D g2;
// Mouse coordinates
private int currentX, currentY, oldX, oldY;
public DrawArea() {
setDoubleBuffered(false);
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
// save coord x,y when mouse is pressed
oldX = e.getX();
oldY = e.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
// coord x,y when drag mouse
currentX = e.getX();
currentY = e.getY();
if (g2 != null) {
// draw line if g2 context not null
g2.drawLine(oldX, oldY, currentX, currentY);
// refresh draw area to repaint
repaint();
// store current coords x,y as olds x,y
oldX = currentX;
oldY = currentY;
}
}
});
}
protected void paintComponent(Graphics g) {
if (image == null) {
// image to draw null ==> we create
image = createImage(getSize().width, getSize().height);
g2 = (Graphics2D) image.getGraphics();
// enable antialiasing
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// clear draw area
clear();
}
g.drawImage(image, 0, 0, null);
}
// now we create exposed methods
public void clear() {
g2.setPaint(Color.white);
// draw white on entire draw area to clear
g2.fillRect(0, 0, getSize().width, getSize().height);
g2.setPaint(Color.black);
repaint();
}
public void red() {
// apply red color on g2 context
g2.setPaint(Color.red);
}
public void black() {
g2.setPaint(Color.black);
}
public void magenta() {
g2.setPaint(Color.magenta);
}
public void green() {
g2.setPaint(Color.green);
}
public void blue() {
g2.setPaint(Color.blue);
}
}
package com.ssaurel.swingpaint;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SwingPaint {
JButton clearBtn, markerBtn, blackBtn, blueBtn, greenBtn, redBtn, magentaBtn;
DrawArea drawArea;
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == clearBtn) {
drawArea.clear();
} else if (e.getSource() == blackBtn) {
drawArea.black();
} else if (e.getSource() == blueBtn) {
drawArea.blue();
} else if (e.getSource() == greenBtn) {
drawArea.green();
} else if (e.getSource() == markerBtn) {
drawArea.black();
} else if (e.getSource() == redBtn) {
drawArea.red();
} else if (e.getSource() == magentaBtn) {
drawArea.magenta();
}
}
};
public static void main(String[] args) {
new SwingPaint().show();
}
public void show() {
// create main frame
JFrame frame = new JFrame("Swing Paint");
Container content = frame.getContentPane();
// set layout on content pane
content.setLayout(new BorderLayout());
// create draw area
drawArea = new DrawArea();
// add to content pane
content.add(drawArea, BorderLayout.CENTER);
// create controls to apply colors and call clear feature
JPanel controls = new JPanel();
clearBtn = new JButton("Clear");
clearBtn.addActionListener(actionListener);
blackBtn = new JButton("Black");
blackBtn.addActionListener(actionListener);
blueBtn = new JButton("Blue");
blueBtn.addActionListener(actionListener);
greenBtn = new JButton("Green");
greenBtn.addActionListener(actionListener);
redBtn = new JButton("Red");
redBtn.addActionListener(actionListener);
magentaBtn = new JButton("Magenta");
magentaBtn.addActionListener(actionListener);
markerBtn = new JButton("Marker");
markerBtn.addActionListener(actionListener);
// add to panel
controls.add(markerBtn);
controls.add(greenBtn);
controls.add(blueBtn);
controls.add(blackBtn);
controls.add(redBtn);
controls.add(magentaBtn);
controls.add(clearBtn);
// add to content pane
content.add(controls, BorderLayout.NORTH);
frame.setSize(900, 720);
// can close frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// show the swing paint result
frame.setVisible(true);
}
}
the code here explains a drawing tool running on a java language using netbeans. what I would like is that the "Marker" to be thicker than default. It's thin to draw this way. well at least for me. anyways, I am lost on how to make it thicker.
Now that you have edited the post to explain that you want your lines to be drawn thicker (which is not the same as 'bold' - bold applies only to fonts) you need to look up Java "stroke styles".
Here is the official filling and stroking tutorial. There are plenty of others.
(Is not a good answer anymore because the op changed his post!)
You need to change your font.
So you need to call on your swing component
.setFont().deriveFont(Font.BOLD));
Or go with
.setFont(new Font("serif", Font.BOLD, 16))
To set a new font
Related
Hi Everyone I want to draw lines to Jlabel Icon with DrawLines() class but the program isn't drawing .When I use to frame.add(m) the program is drawing lines to frame .....
DrawLine m = new DrawLine();
frame.add(m);
but when I use to label.add(m) method .The program isn't working .I need to figure out this problem Why can't I draw lines to jlabelIcon and How can I fix this ?
This is my DrawLine Class
package com.company;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Line2D;
public class DrawLine extends JComponent {
public void paint(Graphics g) {
super.paintComponents(g);
g.drawLine(300, 152, 63, 185);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
g.drawLine(63, 185, 120, 198);
}
}
This is my main class
package com.company;
import com.sun.source.tree.Tree;
import jdk.swing.interop.SwingInterOpUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.awt.geom.Line2D;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
public class Main extends JFrame {
public static void main(String[] args) {
JFrame frame = new JFrame("Display Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = (JPanel) frame.getContentPane();
frame.setSize(1000,560);
JLabel label = new JLabel();
label.setSize(1000,560);
label.setIcon(new ImageIcon("myimage path"));
DrawLine m = new DrawLine();
label.add(m);
panel.add(label);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
If your goal is to draw lines and images together, then your best bet for the money is to get rid of ImageIcon and JLabel and instead is to draw them all within a single paintComponent. The images can be drawn as image sprite, and the lines as lines by calling Graphics#drawLine(...) or as Line2D objects as you have using Graphics2D#draw(...)
For example, say we had two BufferedImage objects, upImg and dnImg, and two Point objects that determined the location of these sprites, upPt and dnPt
public class Foo01 extends JPanel {
// .....
private Point upPt = new Point(300, 100);
private Point dnPt = new Point(700, 650);
private BufferedImage upImg, dnImg;
And say we wanted to draw a line that connected the two image sprites, then these could all be draw within the paintComponent method like so:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // tell the JPanel to do its house-keeping painting
// make sure that neither image is null
if (upImg != null && dnImg != null) {
// draw both images at their respective locations
g.drawImage(upImg, upPt.x, upPt.y, this);
g.drawImage(dnImg, dnPt.x, dnPt.y, this);
// to get a smooth line, use rendering hiints
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// to give the line some thickness
g2.setStroke(new BasicStroke(5f));
// calculate the end-points of the line
int x1 = upPt.x + upImg.getWidth() / 2;
int y1 = upPt.y + upImg.getHeight() / 2;
int x2 = dnPt.x + dnImg.getWidth() / 2;
int y2 = dnPt.y + dnImg.getHeight() / 2;
// and then draw it
g.drawLine(x1, y1, x2, y2);
}
}
Here is an example program that does just this -- draws two images with a line connecting. I've also added a MouseAdapter to allow the user to move the first image, the green up-arrow, showing that the line will move as well, since it is calculated within the painting method:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.URL;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class Foo01 extends JPanel {
private static final String UP_IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/7/7d/Green_circle_icon.jpg";
private static final String DN_IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/b/bc/Red_circle_icon.jpg";
private static final int GUI_W = 1000;
private static final int GUI_H = 800;
private Point upPt = new Point(300, 100);
private Point dnPt = new Point(700, 650);
private BufferedImage upImg, dnImg;
public Foo01() {
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
setBackground(Color.WHITE);
try {
URL url = new URL(UP_IMG_PATH);
upImg = ImageIO.read(url);
url = new URL(DN_IMG_PATH);
dnImg = ImageIO.read(url);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(GUI_W, GUI_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (upImg != null && dnImg != null) {
g.drawImage(upImg, upPt.x, upPt.y, this);
g.drawImage(dnImg, dnPt.x, dnPt.y, this);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(5f));
int x1 = upPt.x + upImg.getWidth() / 2;
int y1 = upPt.y + upImg.getHeight() / 2;
int x2 = dnPt.x + dnImg.getWidth() / 2;
int y2 = dnPt.y + dnImg.getHeight() / 2;
g.drawLine(x1, y1, x2, y2);
}
}
private class MyMouse extends MouseAdapter {
private Point p1 = null;
#Override
public void mousePressed(MouseEvent e) {
if (e.getX() < upPt.x || e.getX() > upPt.x + upImg.getWidth()) {
return;
}
if (e.getY() < upPt.y || e.getY() > upPt.y + upImg.getHeight()) {
return;
}
p1 = new Point(e.getX(), e.getY());
}
#Override
public void mouseReleased(MouseEvent e) {
if (p1 != null) {
moveSprite(e);
p1 = null;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (p1 != null) {
moveSprite(e);
}
}
private void moveSprite(MouseEvent e) {
Point p2 = new Point(e.getX(), e.getY());
int x = upPt.x + p2.x - p1.x;
int y = upPt.y + p2.y - p1.y;
upPt = new Point(x, y);
p1 = p2;
repaint();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()-> {
Foo01 foo01 = new Foo01();
JFrame frame = new JFrame("Draw Sprites");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(foo01);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
If the need is to add custom painting to a JLabel you can override its paintComponent:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
public class Main extends JFrame {
private static final String BUG = "https://www.growtopiagame.com/forums/attachment.php?attachmentid=141847&d=1477126665";
public static void main(String[] args) throws MalformedURLException {
JFrame frame = new JFrame("Display Image");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DrawLine m = new DrawLine("A crossed bug", new ImageIcon(new URL(BUG)));
frame.add(m);
frame.pack();
frame.setVisible(true);
}
}
class DrawLine extends JLabel {
DrawLine(String text, Icon icon) {
super(text, icon, SwingConstants.CENTER);
setVerticalTextPosition(SwingConstants.BOTTOM);
setHorizontalTextPosition(SwingConstants.CENTER);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.YELLOW);
g2d.setStroke(new BasicStroke(10));
int w = getWidth(); int h = getHeight();
g2d.drawLine(0, 0, w, h); //draw right to left diagonal
g2d.drawLine(0, h, w, 0); //draw left to right diagonal
}
}
Swing is a single Thread library. All painting tasks are executed in the Event Dispatcher Thread (EDT).
Running long processes (such as sleep) on the EDT makes keeps this thread busy, so it does not do other things like updating the gui. The gui becomes unresponsive (freezes).
If you want to add a line after a certain delay, use swing Timer for the job:
public class Main extends JFrame {
private static final String BUG = "https://www.growtopiagame.com/forums/attachment.php?attachmentid=141847&d=1477126665";
public static void main(String[] args) throws MalformedURLException {
JFrame frame = new JFrame("Display Image");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DrawLine m = new DrawLine("A crossed bug", new ImageIcon(new URL(BUG)));
frame.add(m);
frame.pack();
frame.setVisible(true);
}
}
class DrawLine extends JLabel {
private static final int DELAY = 1500; //millies
private boolean isDrawSecondDialgonal = false;
DrawLine(String text, Icon icon) {
super(text, icon, SwingConstants.CENTER);
setVerticalTextPosition(SwingConstants.BOTTOM);
setHorizontalTextPosition(SwingConstants.CENTER);
//use timer to enable painting of a second diagonal
javax.swing.Timer timer = new javax.swing.Timer(DELAY, e-> {
isDrawSecondDialgonal = true;
repaint();
});
timer.setRepeats(false);
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.YELLOW);
g2d.setStroke(new BasicStroke(10));
int w = getWidth(); int h = getHeight();
g2d.drawLine(0, 0, w, h); //draw right to left diagonal
if(isDrawSecondDialgonal) {
g2d.drawLine(0, h, w, 0);//draw left to right diagonal
}
}
}
I'm trying to make a paint program, and this class is the main area where you drag your mouse to paint. The problem is the clip has to be rectangular, so any other lines within that rectangle of the clip (the clip gets bigger the faster you move) will get covered by the new clip, however the new clip isn't all needed.
My ideas of solutions are:
To somehow set the clip to a line (but I think that clip would have to be set in the repaint method, not the setClip() in paint component)
To save the image currently on the paint component and set it to the backgroud
Possibly set the ocupancy of the clip lower in the areas without the line?
Thank you for looking at it, here is the code (with some parts left out for simpler reading) and if you know a solution I would love to hear it. Thanks!
public class Canvas extends JPanel implements MouseMotionListener, MouseListener{
int sizeX, sizeY;
String title;
int[] backColor = new int[3];
int brushSize=20;
Point currentP = new Point();
Point pastP = new Point();
Point paintP = new Point();
int diffX, diffY;
boolean initialize=true;
boolean initClip=true;
Canvas(){
backColor[0] = newProject.colorA;
backColor[1] = newProject.colorB;
backColor[2] = newProject.colorC;
if(backColor[0]>=255){
backColor[0]=255;
}
if(backColor[1]>=255){
backColor[1]=255;
}
if(backColor[2]>=255){
backColor[2]=255;
}
sizeX = newProject.sizeX;
sizeY = newProject.sizeY;
//System.out.println(sizeX + " " + sizeY);
setSize(sizeX,sizeY);
setBackground(Color.white);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(brushSize));
if(initialize){
g.setColor(new Color(backColor[0], backColor[1], backColor[2]));
g.fillRect(0, 0, sizeX, sizeY);
g.setColor(Color.red);
g.drawRect(0,0,50,50);
System.out.println("Initialize");
}
else{
g2.drawLine(currentP.x, currentP.y, pastP.x,pastP.y);
}
//System.out.println("Paint");
}
#Override
public void mouseDragged(MouseEvent e) {
if(initClip) //if mouse has been released since last dragged
currentP = e.getPoint(); //This causes PastP and CurrentP to be equal
initClip=false; //since pastP is set equal to CurrentP afterward
pastP = currentP;
currentP = e.getPoint();
diffX=Math.abs(currentP.x-pastP.x); //find the differences to find how big of
diffY=Math.abs(currentP.y-pastP.y); //a clip it needs
if(diffX==0){ //if no movement, set it to brush size so the
diffX=brushSize; //clip shows up
}
if(diffY==0){
diffY=brushSize;
}
initialize=false;
if(currentP.x-pastP.x>0){ //figures out which direction it moved
paintP.x=pastP.x; //sets the clip variable to the correct corner
}
else{
paintP.x=currentP.x;
}
if(currentP.y-pastP.y>0){
paintP.y=pastP.y;
}
else{
paintP.y=currentP.y;
}
System.out.println(paintP);
repaint(paintP.x, paintP.y, diffX, diffY); //repaint with point PaintP and the
//difference it moved
}
#Override
public void mouseReleased(MouseEvent arg0) {
initClip=true;
}
I'm not sure why you would bother. Each time paintComponent is called by the paint system, you are expected to repaint the entire component anyway.
Instead, simply paint what you need to paint, then paint the selection on top of it...
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawSelection {
public static void main(String[] args) {
new DrawSelection();
}
public DrawSelection() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage background;
private Rectangle clipRect;
public TestPane() {
try {
background = ImageIO.read(new File("/path/to/your/image"));
} catch (IOException ex) {
ex.printStackTrace();
}
MouseAdapter ma = new MouseAdapter() {
private Point cp;
#Override
public void mousePressed(MouseEvent e) {
cp = e.getPoint();
clipRect = null;
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
cp = null;
}
#Override
public void mouseDragged(MouseEvent e) {
Point p = e.getPoint();
int x = Math.min(p.x, cp.x);
int y = Math.min(p.y, cp.y);
int width = Math.max(p.x, cp.x) - x;
int height = Math.max(p.y, cp.y) - y;
clipRect = new Rectangle(x, y, width, height);
repaint();
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
#Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (background != null) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
}
if (clipRect != null) {
g2d.setColor(UIManager.getColor("List.selectionBackground"));
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.fill(clipRect);
}
g2d.dispose();
}
}
}
If you want to optimise the paint process, why not draw the parts of the image to a backing buffer and simply paint the buffer, then paint the selection or other dynamic parts on top of it within the paintComponent?
Some software uses the monitor as a clear white board to draw. The white board is transparent, and you can see the desktop underneath the clear white board
So how this is possible?
I mean in Java is it like making the JFrame to screen size and making it transparent to draw or how is this being done?
We have a similar requirement so we're trying to understand how to do this?
Here is one way to do it: you create a transparent window on which you put a JLabel displaying a BufferedImage. As the users presses and drags the mouse, you draw on the BufferedImage and repaint the label to update the content.
Some example code to get started:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class TestTransparentFrame extends JLabel {
private boolean drawing = false;
private Point lastPoint;
private BufferedImage image;
public TestTransparentFrame() {
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
updateImage();
}
});
MouseAdapter mouseAdapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
drawing = true;
lastPoint = e.getPoint();
}
#Override
public void mouseReleased(MouseEvent e) {
drawing = false;
lastPoint = null;
}
#Override
public void mouseExited(MouseEvent e) {
drawing = false;
lastPoint = null;
}
#Override
public void mouseDragged(MouseEvent e) {
if (drawing && lastPoint != null) {
Graphics graphics = image.getGraphics();
graphics.setColor(Color.RED);
((Graphics2D) graphics).setStroke(new BasicStroke(5.0f));
graphics.drawLine(lastPoint.x, lastPoint.y, e.getX(), e.getY());
repaint();
lastPoint = e.getPoint();
}
}
};
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
}
protected void updateImage() {
if (image == null || image.getWidth() < getWidth() || image.getHeight() < getHeight()) {
if (image == null) {
image = getGraphicsConfiguration().createCompatibleImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
} else {
BufferedImage newImage = getGraphicsConfiguration().createCompatibleImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
newImage.getGraphics().drawImage(image, 0, 0, null);
image = newImage;
}
} else {
image = image.getSubimage(0, 0, getWidth(), getHeight());
}
setIcon(new ImageIcon(image));
}
protected void initUI() {
JFrame frame = new JFrame(TestTransparentFrame.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
frame.setBackground(new Color(255, 255, 255, 1));
TestTransparentFrame comp = new TestTransparentFrame();
frame.setContentPane(comp);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
}
/**
* #param args
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestTransparentFrame().initUI();
}
});
}
}
And the result:
So, I'm trying to dynamically draw a Polygon starting from when I click the mouse until I stop dragging and release. Instead of, for the purpose of this question, a square outline being drawn when I click, drag down, then right-across, then up, then left-across, this is what happens: http://imgur.com/t8ZN3Pp
Any suggestions?
Notes:
model.addPolygon() creates a Polygon with starting points and adds it to an ArrayList called 'polys'
model.addPolygonPoint() adds points to this created polygon that is stored in 'polys'
my paint function iterates through polys to paint
public void mousePressed(MouseEvent e) {
oldX = e.getX();
oldY = e.getY();
model.addPolygon(oldX, oldY);
}
public void mouseDragged(MouseEvent e) {
currentX = e.getX();
currentY = e.getY();
model.addPolyPoint(currentX, currentY);
repaint();
}
.
.
. then in paintComponent:
for (ListIterator<Polys> iter =
model.polys.listIterator(model.polys.size());
iter.hasPrevious();){
graphics2D.draw(iter.previous().poly);
Full paintComponent:
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null) {
image = createImage(getSize().width, getSize().height);
graphics2D = (Graphics2D) image.getGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
g.drawImage(image, 0, 0, null);
for (ListIterator<Polys> iter =
model.polys.listIterator(model.polys.size());
iter.hasPrevious();){
graphics2D.draw(iter.previous().poly);
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
public class Testing {
private static int lastX;
private static int lastY;
private static int modX;
private static int modY;
private static final BasicStroke STROKE = new BasicStroke(2.0F);
private static final Point[] SHAPE = new Point[]{
new Point(10, 10),
new Point(10, 40),
new Point(60, 90),
new Point(50, 50)
};
public static void main(final String[] args) {
final JFrame frame = new JFrame("Polygon Movement");
final JPanel pane = new JPanel() {
#Override
public void paintComponent(final Graphics g1) {
final Graphics2D g = (Graphics2D) g1;
g.setColor(Color.RED);
g.translate(modX, modY);
g.setStroke(STROKE);
for (int i = 0; i < SHAPE.length; i++) {
g.drawLine(SHAPE[i].x, SHAPE[i].y, SHAPE[(i + 1) % SHAPE.length].x, SHAPE[(i + 1) % SHAPE.length].y);
}
}
};
pane.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
modX += e.getX() - lastX;
modY += e.getY() - lastY;
lastX = e.getX();
lastY = e.getY();
frame.repaint();
}
});
pane.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
lastX = e.getX();
lastY = e.getY();
}
});
pane.setPreferredSize(new Dimension(200, 200));
frame.add(pane);
frame.pack();
frame.setVisible(true);
}
}
As you can see, I make a basic shape with defined points. It is the most effective way to do this, unless you wish to change the basic shape (here it is static). In that case, you find the point the mouse it 'grabbing' and modify that one. Either way, no adding or removing of points is needed. I use the terms lastX instead of oldX just by preference.
The BasicStroke is quite optional, same with casting to a Graphics2D object.
The line:
g.drawLine(SHAPE[i].x, SHAPE[i].y, SHAPE[(i + 1) % SHAPE.length].x, SHAPE[(i + 1) % SHAPE.length].y);
Should make some sense if you've tried this thing before. It iterates through all the points, drawing a line from the current (SHAPE[i]) to the next (SHAPE[(i + 1) & SHAPE.length).
The reason behind that logic, is that say you have 4 points, as we do here. The last iteration through them, you will be given i = 3. Due to this and the array only containing 4 indexes (0-3), we must get that value back down to zero. For simplicity I use the % SHAPE.length so there wouldn't be a need for special cases.
I also opted to use adapters seeing as there were only 2 methods needed of the 7 possible ones.
If you have any questions feel free to ask me about this.
~Legend
If all you want to do is draw a polygon. You could simply use the Shape API
This will allow you to "add" points to the shape and allow the shape to paint itself.
Here I use a simple Path2D shape, as it allows me to append points over time. I keep a running list of shapes, which allows me to generate multiple polygons as required
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawPolygon {
public static void main(String[] args) {
new DrawPolygon();
}
public DrawPolygon() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PolyPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class PolyPane extends JPanel {
private MouseHandler mouseHandler;
private Path2D currentShape;
private List<Path2D> lstPloys;
private Point lastPoint;
private Point currentPoint;
public PolyPane() {
lstPloys = new ArrayList<>();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public void addNotify() {
super.addNotify();
addMouseListener(getMouseHandler());
addMouseMotionListener(getMouseHandler());
}
#Override
public void removeNotify() {
removeMouseListener(getMouseHandler());
removeMouseMotionListener(getMouseHandler());
super.removeNotify();
}
public MouseHandler getMouseHandler() {
if (mouseHandler == null) {
mouseHandler = new MouseHandler();
}
return mouseHandler;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (lastPoint != null) {
g2d.setColor(Color.RED);
g2d.fillOval(lastPoint.x - 2, lastPoint.y - 2, 4, 4);
}
if (currentShape != null) {
g2d.setColor(Color.RED);
g2d.draw(currentShape);
if (lastPoint != null && currentPoint != null) {
System.out.println(lastPoint + " - " + currentPoint);
g2d.setColor(new Color(255, 0, 0, 64));
g2d.draw(new Line2D.Float(lastPoint, currentPoint));
}
}
g2d.setColor(Color.BLACK);
for (Shape shape : lstPloys) {
g2d.draw(shape);
}
g2d.dispose();
}
public class MouseHandler extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
if (e.getClickCount() == 1) {
Point p = e.getPoint();
lastPoint = p;
if (currentShape == null) {
currentShape = new Path2D.Float();
currentShape.moveTo(p.x, p.y);
} else {
currentShape.lineTo(p.x, p.y);
}
repaint();
} else if (e.getClickCount() == 2) {
currentShape.closePath();
lstPloys.add(currentShape);
currentShape = null;
lastPoint = null;
repaint();
}
}
}
#Override
public void mouseMoved(MouseEvent e) {
if (currentShape != null) {
currentPoint = e.getPoint();
repaint();
} else {
currentPoint = null;
}
}
}
}
}
Take a look at Working with Geometry for more details
Language: Java.
Hi, I need to prevent drawing over the same location of a Graphics2D more than once. For example, if the user draws using a BasicStroke with a round cap and a width of 10 over a certain area, that same area cannot be drawn on a second time.
The reason I want to do this is so that the user can draw (free-hand) translucent colours over an image without drawing over the same stroke (thus increasing the density of the colour and reducing its translucency).
I've tried storing the shapes of all the strokes made by the user (as Area objects that subtract the shape) and then clipping the Graphics2D by the intersection of all those Area objects.
This almost works, but the 'shape' obtained by the clip is not quite the same as the 'shape' drawn by the stroke - it is out by a couple of pixels.
Does anyone have any other ideas that might work?
The concept is relatively simple, you need to have multiple layers onto which you can render...
There are multiple different ways to approach the problem. You could maintain a list of Points and on each paint cycle, render these points to a backing buffer, which you would then draw over the main content using a AlphaComposite.
You could (as this example does) draw directly to the backing buffer and repaint the content, again, using a AlphaComposite to render the higher layer.
You could have any number of layers...
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
public class PaintOver {
public static void main(String[] args) {
new PaintOver();
}
public PaintOver() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MapPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MapPane extends JPanel {
private BufferedImage background;
private BufferedImage foreground;
public MapPane() {
try {
background = ImageIO.read(getClass().getResource("/TreasureMap.png"));
foreground = new BufferedImage(background.getWidth(), background.getHeight(), BufferedImage.TYPE_INT_ARGB);
} catch (Exception e) {
e.printStackTrace();
}
MouseAdapter mouseHandler = new MouseAdapter() {
private Point startPoint;
#Override
public void mousePressed(MouseEvent e) {
startPoint = e.getPoint();
}
#Override
public void mouseReleased(MouseEvent e) {
startPoint = null;
}
#Override
public void mouseDragged(MouseEvent e) {
Point endPoint = e.getPoint();
Graphics2D g2d = foreground.createGraphics();
Point offset = getOffset();
Point from = new Point(startPoint);
from.translate(-offset.x, -offset.y);
Point to = new Point(endPoint);
to.translate(-offset.x, -offset.y);
g2d.setColor(Color.RED);
g2d.setStroke(new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2d.draw(new Line2D.Float(from, to));
g2d.dispose();
startPoint = endPoint;
repaint();
}
};
addMouseListener(mouseHandler);
addMouseMotionListener(mouseHandler);
}
#Override
public Dimension getPreferredSize() {
return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
}
protected Point getOffset() {
Point p = new Point();
if (background != null) {
p.x = (getWidth() - background.getWidth()) / 2;
p.y = (getHeight() - background.getHeight()) / 2;
}
return p;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Graphics2D g2d = (Graphics2D) g.create();
Point offset = getOffset();
g2d.drawImage(background, offset.x, offset.y, this);
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.drawImage(foreground, offset.x, offset.y, this);
g2d.dispose();
}
}
}
}