How to use graphics(Piant component) on any one layer of JLayeredPane - java

I am trying to draw a line at run time on any one layer of JlayeredPane. What i am currently facing is that line drawn getting erased automatically once i release the mouse. I want that drawn line to be there until i click the mouse again.
I am calling the below written class, this way
iDimension = new getDimension();
iDimension.setBounds(1, 12, 441, 380);
//iDimension.setOpaque(true);
iDimension.setBackground(new Color(0,0,0,100));
I have added iDimension With Layered pane in this way
layeredPane.add(iDimension, new Integer(1),0);
Here is the getDimension Class
public class getDimension extends JPanel {
public getDimension() {
setDoubleBuffered(true);
this.setBorder(UIManager.getBorder("ComboBox.border"));
this.repaint();
}
Point pointStart = null;
Point pointEnd = null;
{
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();
}
public void mouseReleased(MouseEvent e) {
pointStart = null;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
pointEnd = e.getPoint();
}
public void mouseDragged(MouseEvent e) {
pointEnd = e.getPoint();
repaint();
}
});
}
public void paint(Graphics g) {
super.paint(g);
if (pointStart != null) {
g.setColor(Color.GREEN);
g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);
// System.out.println("" + pointStart.x +"," + pointStart.y +"," + pointEnd.x +"," +pointEnd.y);
}
}
}
I am a newbie in java. Kindly correct if there is any ambiguity in my question.

What i am currently facing is that line drawn getting erased automatically once i release the mouse. I want that drawn line to be there until i click the mouse again.
The code is only doing what you tell it to do:
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();
}
public void mouseReleased(MouseEvent e) {
pointStart = null;
}
});
and:
public void paint(Graphics g) {
super.paint(g);
if (pointStart != null) { // *********
g.setColor(Color.GREEN);
g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);
}
}
Note that if pointStart is null, you don't draw the line -- but you set it to null on mouseReleased! Solution -- don't do that.
e.g.,
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
#SuppressWarnings("serial")
public class GetDimension extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private Point pointStart = null;
private Point pointEnd = null;
public GetDimension() {
this.setBorder(UIManager.getBorder("ComboBox.border"));
this.repaint();
MouseAdapter myMouse = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();
repaint();
}
public void mouseDragged(MouseEvent e) {
pointEnd = e.getPoint();
repaint();
}
};
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (pointStart != null && pointEnd != null) {
g.setColor(Color.GREEN);
g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
GetDimension mainPanel = new GetDimension();
JFrame frame = new JFrame("GetDimension");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}

Related

Why are drawn lines automatically erased?

I am building up a system with a canvas where user can draw lines by dragging the mouse in Java. I want all the strokes to be stored and displayed. However, when I press the mouse to draw a new line, previous lines are automatically erased, which is not what I was expecting. How can I solve this problem?
Here is my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FreeDrawing extends JPanel implements MouseListener, MouseMotionListener {
private int indexOfStroke = 0;
private int indexOfPoint = 0;
private Stroke[] strokes = new Stroke[50];
private Point[] currentPoints = new Point[500];
public FreeDrawing(String name) {
super();
this.addMouseListener(this);
this.addMouseMotionListener(this);
JFrame fr = new JFrame(name);
fr.add(this);
fr.setSize(500, 500);
setBackground(Color.GRAY);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.setVisible(true);
}
public void paintComponent(Graphics g) {
System.out.println("Paint");
super.paintComponents(g);
strokes[indexOfStroke] = new Stroke();
for (int i = 0; i < indexOfPoint - 1; i++) {
System.out.println("Really draw");
g.drawLine(currentPoints[i].x, currentPoints[i].y, currentPoints[i + 1].x, currentPoints[i + 1].y);
}
}
public void mouseDragged(MouseEvent e) {
System.out.println("Drag");
currentPoints[indexOfPoint] = new Point(e.getX(), e.getY());
indexOfPoint++;
repaint();
}
public void mousePressed(MouseEvent e) {
System.out.println("Press");
currentPoints[indexOfPoint] = new Point(e.getX(), e.getY());
indexOfPoint = 0;
repaint();
}
public void mouseReleased(MouseEvent e) {
indexOfPoint = 0;
indexOfStroke++;
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
public static void main(String[] args) {
FreeDrawing canvas = new FreeDrawing("Mouse");
}
}
class Stroke {
public Stroke() {
System.out.println("Stroke initiated");
points = new Point[500];
}
Point[] points;
}
Because, that's how painting works, see Painting in AWT and Swing and Performing Custom Painting for more details.
Basically, painting is destructive, meaning that each time paintComponent is called, you are expected to repaint the entire state of the component from scratch
One thing you might consider doing, is creating a class which contains the stroke, color and points you need to each line and store that in a List each time you click
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.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private List<Drawing> drawings;
private Drawing current;
private Random rnd = new Random();
public TestPane() {
drawings = new ArrayList<>(25);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
Stroke stroke = new BasicStroke(rnd.nextInt(9) + 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
Color color = new Color(rnd.nextInt(255), rnd.nextInt(255), rnd.nextInt(255));
current = new Drawing(stroke, color);
current.addPoint(e.getPoint());
drawings.add(current);
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
current.addPoint(e.getPoint());
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Drawing drawing : drawings) {
drawing.paint(g2d);
}
g2d.dispose();
}
}
public class Drawing {
private Stroke stroke;
private Color color;
private List<Point> points;
public Drawing(Stroke stroke, Color color) {
this.stroke = stroke;
this.color = color;
this.points = new ArrayList<>(25);
}
public void addPoint(Point p) {
points.add(p);
}
public void paint(Graphics2D g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(color);
g2d.setStroke(stroke);
if (!points.isEmpty()) {
Point from = points.get(0);
for (Point to : points.subList(1, points.size())) {
g2d.draw(new Line2D.Double(from, to));
from = to;
}
}
g2d.dispose();
}
}
}

Java - redraw background

I want to redraw background with different image. Here's a SSCCE example - I'd like to add an action to Listener that will repaint with another image.
package painting;
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseMotionAdapter;
public class SwingPaintDemo3 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
System.out.println("Created GUI on EDT? "+
SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
}
class MyPanel extends JPanel {
private int squareX = 50;
private int squareY = 50;
private int squareW = 20;
private int squareH = 20;
Image img;
public MyPanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});
}
private void moveSquare(int x, int y) {
int OFFSET = 1;
if ((squareX!=x) || (squareY!=y)) {
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
squareX=x;
squareY=y;
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
}
}
public Dimension getPreferredSize() {
return new Dimension(250,200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
try {
img = ImageIO.read(new File("graphics/close_0.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
g.drawImage(img, 0, 0, null);
g.drawString("This is my custom Panel!",10,20);
g.setColor(Color.RED);
g.fillRect(squareX,squareY,squareW,squareH);
g.setColor(Color.BLACK);
g.drawRect(squareX,squareY,squareW,squareH);
}
}
So what method should I call to redraw background with different image?
As much as I understand the question (which is 'very little') this source might lead you forward. Note that code should never attempt a potentially blocking operation (like loading an image) within the paint or paintComponent method.
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import java.util.Random;
public class SwingPaintDemo3 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
System.out.println("Created GUI on EDT? "+
SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
}
class MyPanel extends JPanel {
private int squareX = 50;
private int squareY = 50;
private int squareW = 20;
private int squareH = 20;
Image img;
Random r = new Random();
public MyPanel() {
img = new BufferedImage(40,40,BufferedImage.TYPE_INT_RGB);
setBorder(BorderFactory.createLineBorder(Color.black));
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
img = new BufferedImage(
r.nextInt(getWidth())+1,
r.nextInt(getHeight())+1,
BufferedImage.TYPE_INT_RGB);
moveSquare(e.getX(),e.getY());
}
});
}
private void moveSquare(int x, int y) {
int OFFSET = 1;
if ((squareX!=x) || (squareY!=y)) {
squareX=x;
squareY=y;
repaint();
}
}
public Dimension getPreferredSize() {
return new Dimension(250,200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, null);
g.drawString("This is my custom Panel!",10,20);
g.setColor(Color.RED);
g.fillRect(squareX,squareY,squareW,squareH);
g.setColor(Color.BLACK);
g.drawRect(squareX,squareY,squareW,squareH);
}
}

Object issues in Java

I'm attempting to implement the dragging functionality of shapes on a canvas. My Shape class inherits from JPanel.
Absolutely nothing happens when I click on a shape, drag it and let go of the mouse button. It just remains where it was originally. Any ideas?
You need a few basic things:
A field for the shape itself (you already had)
Fields to keep track of the offset of the click within the shape (already had)
A field to keep track of if you're dragging
Overwrite the paintComponent method to paint your shape
A MouseListener and MouseMotionListener added to the Panel (MouseAdapter does both of these)
Here's a basic working example.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DrawTest extends JPanel{
//Shape doesn't have a location field - you'd have to keep track of
//this yourself if you're set on using the shape interface
private Rectangle shape = new Rectangle(100, 100);
// The location within the shape you clicked
private int xOffset = 0;
private int yOffset = 0;
// To indicate dragging is happening
boolean isDragging = false;
public DrawTest(){
MouseAdapter listener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
// Starts dragging and calculates offset
if(shape.contains(e.getPoint())){
isDragging = true;
xOffset = e.getPoint().x - shape.x;
yOffset = e.getPoint().y - shape.y;
}
}
#Override
public void mouseReleased(MouseEvent e) {
// Ends dragging
isDragging = false;
}
#Override
public void mouseDragged(MouseEvent e) {
// Moves the shape - doesn't actually need to be a method
// but is because you had it as one
if(isDragging){
moveShape(e);
}
}
private void moveShape(MouseEvent e) {
Point newLocation = e.getPoint();
newLocation.x -= xOffset;
newLocation.y -= yOffset;
shape.setLocation(newLocation);
repaint();
}
};
//Add a mouse mostion listener (for dragging) and regular listener (for clicking)
addMouseListener(listener);
addMouseMotionListener(listener);
}
// So we have a play area to work with
public Dimension getPreferredSize(){
return new Dimension(400,300);
}
//Paints the shape
public void paintComponent(Graphics g){
super.paintComponent(g);
g.clearRect(0,0,getWidth(), getHeight());
g.fillRect(shape.x, shape.y, shape.width, shape.height);
}
public static void main(String[] args)
{
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DrawTest());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Tried a small simple example
Dragging the rectangle will make it move with the cursor it also checks the bounds so the rectangle cannot be dragged off screen:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ShapeMover {
public ShapeMover() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Shape Mover");
initComponents(frame);
frame.pack();
frame.setVisible(true);
}
public static void main(String s[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ShapeMover();
}
});
}
private void initComponents(JFrame frame) {
frame.getContentPane().add(new DragPanel());
}
}
class DragPanel extends JPanel {
Rectangle rect = new Rectangle(0, 0, 100, 50);
int preX, preY;
boolean isFirstTime = true;
Rectangle area;
boolean pressOut = false;
private Dimension dim = new Dimension(400, 300);
public DragPanel() {
setBackground(Color.white);
addMouseMotionListener(new MyMouseAdapter());
addMouseListener(new MyMouseAdapter());
}
#Override
public Dimension getPreferredSize() {
return dim;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if (isFirstTime) {
area = new Rectangle(dim);
rect.setLocation(50, 50);
isFirstTime = false;
}
g2d.setColor(Color.black);
g2d.fill(rect);
}
boolean checkRect() {
if (area == null) {
return false;
}
if (area.contains(rect.x, rect.y, 100, 50)) {
return true;
}
int new_x = rect.x;
int new_y = rect.y;
if ((rect.x + 100) > area.getWidth()) {
new_x = (int) area.getWidth() - 99;
}
if (rect.x < 0) {
new_x = -1;
}
if ((rect.y + 50) > area.getHeight()) {
new_y = (int) area.getHeight() - 49;
}
if (rect.y < 0) {
new_y = -1;
}
rect.setLocation(new_x, new_y);
return false;
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
preX = rect.x - e.getX();
preY = rect.y - e.getY();
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
} else {
pressOut = true;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (!pressOut) {
updateLocation(e);
} else {
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
} else {
pressOut = false;
}
}
public void updateLocation(MouseEvent e) {
rect.setLocation(preX + e.getX(), preY + e.getY());
checkRect();
repaint();
}
}
}
Reference:
http://www.java2s.com/Code/Java/Event/MoveShapewithmouse.htm

How to draw thin line with no gap while dragging the cursor?

I have this following class, which refresh a jpeg file in layer 0 and layer 1 is used to draw/paint/sketch up anything related to smash things. But in my drawing when I want to do a thin line, it breaks. Because the mouse cursor movement needs to be slower.
How to resolve on fast mouse move, that the line remains joined?
Annotation.java
package test;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Annotation {
// Image
private static Image backgroundImage;
private static BufferedImage _bufImage = null;
// Enum
public static enum Shape { RECTANGLE, OVAL, LINE }
private static enum State { IDLE, DRAGGING }
private static final Shape INIIIAL_SHAPE = Shape.RECTANGLE;
private static final Color INITIAL_COLOR = Color.RED;
private static Shape _shape = INIIIAL_SHAPE;
private static Color _color = INITIAL_COLOR;
private static State _state = State.IDLE;
private static Point _start = null;
private static Point _end = null;
// JPanel
private static JPanel p;
private static JPanel mp;
/* Run: */
public static void main(String args[]) {
c();
}
/* GUI */
public static void c() {
try {
backgroundImage = ImageIO.read(new File("/var/tmp/test.jpeg"));
} catch (IOException e) {
e.printStackTrace();
}
myTimer();
loadAnnotation();
loadBackground();
JFrame f;
f = new JFrame();
f.setLayout(new BorderLayout());
f.add(mp);
f.pack();
f.setVisible(true);
}
/* 5 seconds to load picture */
public static void myTimer() {
javax.swing.Timer t = new javax.swing.Timer(5000, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
try {
backgroundImage = ImageIO.read(new File("/var/tmp/test.jpeg"));
mp.repaint();
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
/* Layer 0:
* Load background picture */
public static void loadBackground() {
mp = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(backgroundImage, 0, 0, 1024, 600, null);
}
public Dimension getPreferredSize() {
return new Dimension(1024, 600);
}
};
mp.add(p);
}
/* Layer 1:
* Annotation: Draw on top of background picture anything! */
public static void loadAnnotation() {
p = new JPanel() {
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.RED);
if (_bufImage == null) {
int w = this.getWidth();
int h = this.getHeight();
_bufImage = new BufferedImage(1024,600, BufferedImage.TRANSLUCENT);
Graphics2D gc = _bufImage.createGraphics();
}
g2.drawImage(_bufImage, null, 0, 0);
if (_state == State.DRAGGING) {
g2.drawLine(_start.x, _start.y, _end.x , _end.y);
}
}
public Dimension getPreferredSize() {
return new Dimension(1024, 600);
}
};
p.setLayout(new FlowLayout());
p.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent me) {
}
#Override
public void mousePressed(MouseEvent me) {
}
#Override
public void mouseReleased(MouseEvent me) {
//_state = State.IDLE;
_state = State.IDLE;
}
#Override
public void mouseEntered(MouseEvent me) {
}
#Override
public void mouseExited(MouseEvent me) {
}
});
p.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent me) {
System.out.println("drag");
_state = State.DRAGGING;
_start = me.getPoint();
_end = _start;
if (_state == State.DRAGGING) {
Graphics2D g2 = _bufImage.createGraphics();
g2.setColor(Color.red);
g2.setStroke(new BasicStroke(90));
g2.fillOval(_start.x, _start.y, 10, 10);
p.repaint();
}
}
#Override
public void mouseMoved(MouseEvent me) {
System.out.println("move");
}
});
JButton pm = new JButton("+");
pm.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
}
});
p.add(pm);
p.setOpaque(true);
}
}
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Annotation {
// Image
private static Image backgroundImage;
private static BufferedImage _bufImage = null;
// Enum
public static enum Shape { RECTANGLE, OVAL, LINE }
private static enum State { IDLE, DRAGGING }
private static final Shape INIIIAL_SHAPE = Shape.RECTANGLE;
private static final Color INITIAL_COLOR = Color.RED;
private static Shape _shape = INIIIAL_SHAPE;
private static Color _color = INITIAL_COLOR;
private static State _state = State.IDLE;
private static Point _start = null;
private static Point _end = null;
// JPanel
private static JPanel p;
private static JPanel mp;
/* Run: */
public static void main(String args[]) {
c();
}
/* GUI */
public static void c() {
try {
URL url = new URL("http://pscode.org/media/stromlo2.jpg");
backgroundImage = ImageIO.read(url);
} catch (Exception e) {
e.printStackTrace();
}
loadAnnotation();
loadBackground();
JFrame f;
f = new JFrame();
f.setLayout(new BorderLayout());
f.add(mp);
f.pack();
f.setVisible(true);
}
/* Layer 0:
* Load background picture */
public static void loadBackground() {
mp = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), null);
}
public Dimension getPreferredSize() {
return new Dimension(backgroundImage.getWidth(this), backgroundImage.getHeight(this));
}
};
mp.add(p);
}
/* Layer 1:
* Annotation: Draw on top of background picture anything! */
public static void loadAnnotation() {
p = new JPanel() {
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.RED);
if (_bufImage == null) {
int w = this.getWidth();
int h = this.getHeight();
_bufImage = new BufferedImage(1024,600, BufferedImage.TRANSLUCENT);
Graphics2D gc = _bufImage.createGraphics();
}
g2.drawImage(_bufImage, null, 0, 0);
if (_state == State.DRAGGING) {
g2.drawLine(_start.x, _start.y, _end.x , _end.y);
}
}
public Dimension getPreferredSize() {
return new Dimension(1024, 600);
}
};
p.setLayout(new FlowLayout());
p.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent me) {
}
#Override
public void mousePressed(MouseEvent me) {
}
#Override
public void mouseReleased(MouseEvent me) {
//_state = State.IDLE;
_state = State.IDLE;
}
#Override
public void mouseEntered(MouseEvent me) {
}
#Override
public void mouseExited(MouseEvent me) {
}
});
p.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent me) {
_state = State.DRAGGING;
_end = me.getPoint();
if (_state == State.DRAGGING) {
Graphics2D g2 = _bufImage.createGraphics();
g2.setColor(Color.red);
g2.setStroke(new BasicStroke(2));
g2.drawLine(_start.x, _start.y, _end.x, _end.y);
p.repaint();
}
_start = _end;
}
#Override
public void mouseMoved(MouseEvent me) {
//System.out.println("move");
_start = me.getPoint();
}
});
JButton pm = new JButton("+");
pm.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
}
});
p.add(pm);
p.setOpaque(true);
}
}
I solved this problem by drawing rectangles between points, using the Stroke size (Basic Stroke) for height. It sounds like an icky solution but it does pretty well in reality

Applet not painting

I am having issues with my Applet not painting the required graphics.
For some reason, it updates the coloring in the graphics, as you can see this when it prints, it recognizes the mouse is being moved, the graphics are not null, but it still refuses to paint.
How can this be fixed?
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JApplet;
public class GameApplet extends JApplet implements MouseListener, MouseMotionListener{
/**
*
*/
private static final long serialVersionUID = -6796451079056583597L;
Graphics2D g;
Image image;
Point p = new Point(-100, -100);
public void init(){
init(1000, 900);
}
public void init(int x, int y){
setSize(x, y);
image = createImage(x, y);
g = (Graphics2D) image.getGraphics();
//if(Graphic.setGraphic(image.getGraphics())){
if(g != null)
System.out.println("Graphics made");
//}
g.setColor(Color.GREEN);
g.fillRect(0, 0, x, y);
System.out.println(g+", "+ (g != null));
addMouseListener(this);
addMouseMotionListener(this);
//Graphic.paint();
setVisible(true);
}
#Override
public void paint(Graphics g){
g.setColor(Color.red);
g.fillRect(0, 0, 500, 500);
}
public void update(Graphics g){
paint(g);
}
#Override
public Graphics getGraphics(){
return g;
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(e);
}
#Override
public void mousePressed(MouseEvent e) {
p = e.getPoint();
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
showStatus(e.toString());
g.fillOval(e.getPoint().x - 5, e.getPoint().y - 5, 10, 10);
p = e.getPoint();
repaint();
}
}
As per my recommendations, do all drawing in a JPanel or JComponent's paintComponent method. Get the image's Graphics object only when you need it and dispose of it when you're done with it. For example:
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
#SuppressWarnings("serial")
public class GameApplet2 extends JApplet {
protected static final int APP_WIDTH = 1000;
protected static final int APP_HEIGHT = 900;
#Override
public void init() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
GameAppletPanel panel = new GameAppletPanel(GameApplet2.this);
getContentPane().add(panel);
panel.init(APP_WIDTH, APP_HEIGHT);
setSize(APP_WIDTH, APP_HEIGHT);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
#SuppressWarnings("serial")
class GameAppletPanel extends JPanel {
Image image;
Point p = new Point(-100, -100);
private JApplet applet;
public GameAppletPanel(JApplet applet) {
this.applet = applet;
}
public void init() {
init(1000, 900);
}
public void init(int x, int y) {
setSize(x, y);
image = createImage(x, y);
Graphics2D g = (Graphics2D) image.getGraphics();
g.setColor(Color.GREEN);
g.fillRect(0, 0, x, y);
g.dispose();
System.out.println(g + ", " + (g != null));
MyMouseAdapter mmAdapter = new MyMouseAdapter();
addMouseListener(mmAdapter);
addMouseMotionListener(mmAdapter);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
g.setColor(Color.red);
g.fillRect(0, 0, 500, 500);
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(e);
}
#Override
public void mousePressed(MouseEvent e) {
p = e.getPoint();
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
applet.showStatus(e.toString());
Graphics2D g2 = (Graphics2D) image.getGraphics();
g2.fillOval(e.getPoint().x - 5, e.getPoint().y - 5, 10, 10);
p = e.getPoint();
g2.dispose();
repaint();
}
}
}
The "don't paint in top-level containers" still needs attending to, but it was not the immediate source(s) of the problem. Try this simpler code.
// <applet code='GameApplet' width=400 height=200></applet>
import java.awt.*;
import java.awt.event.*;
import javax.swing.JApplet;
public class GameApplet extends JApplet
implements MouseListener, MouseMotionListener{
Point p = new Point(-100, -100);
public void init(){
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
public void paint(Graphics g){
g.setColor(Color.red);
g.fillRect(0, 0, 500, 500);
g.setColor(Color.blue);
g.fillOval(p.x - 5, p.y - 5, 10, 10);
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(e);
}
#Override
public void mousePressed(MouseEvent e) {
p = e.getPoint();
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseDragged(MouseEvent e) {}
#Override
public void mouseMoved(MouseEvent e) {
showStatus(e.toString());
p = e.getPoint();
repaint();
}
}

Categories