Java : Draw Rectangles on mouse click - java

I want to draw a rectangle every time user clicks on the "Rectangle" button and then clicks on the JFrame based on the event x and y coordinates. I have a component class the draws the rectangle and I have another class that has JFrame mouse press listener.
My Code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JComponent;
public class RectangleComponent extends JComponent
{
Rectangle box;
RectangleComponent()
{
box = new Rectangle(5, 10, 20, 30);
repaint();
}
RectangleComponent(int x, int y)
{
box = new Rectangle(x, y, 20, 30);
}
public void paintComponent(Graphics g)
{
// Recover Graphics2D
Graphics2D g2 = (Graphics2D) g;
// Change the color
Color c = new Color(1.0F,0.0F,1.0F);
g2.setColor(c);
// Draw a rectangle
g2.draw(box);
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Test2
{
static boolean isPressed = false;
public static void main(String[] args)
{
final JFrame frame = new JFrame();
final int FRAME_WIDTH = 400;
final int FRAME_HEIGHT = 400;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("Test 2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel panel = new JPanel();
frame.add(panel,BorderLayout.NORTH);
final JButton btnRectangle = new JButton("Rectangle");
panel.add(btnRectangle);
class RectangleButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
isPressed = true;
}
}
ActionListener rectButtonListener = new RectangleButtonListener();
btnRectangle.addActionListener(rectButtonListener);
class MousePressListener implements MouseListener
{
public void mousePressed(MouseEvent event)
{
int x = event.getX() ;
int y = event.getY() ;
if(isPressed)
{
RectangleComponent rc = new RectangleComponent(x, y);
frame.add(rc);
}
}
public void mouseReleased(MouseEvent event){}
public void mouseClicked(MouseEvent event){}
public void mouseEntered(MouseEvent event){}
public void mouseExited(MouseEvent event){}
}
MousePressListener mListener = new MousePressListener();
frame.addMouseListener(mListener);
frame.setVisible(true);
}
}
Now it seems to be doing what I want, but in very strange way. If I click rectangle and click on the frame I see nothing but then if I maximize the frame the rectangle appears where I click. Why is this happening and what is the fix?

To start off with, when using paintComponent() you need to Override it and call it's super method like so:
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
Secondly, Here is your RectangleComponent Class with some slight modifications:
public class RectangleComponent extends JComponent
{
int x, y;
RectangleComponent(int x, int y)
{
this.x = x;
this.y = y;
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Color c = new Color(1.0F,0.0F,1.0F);
g.setColor(c);
g.drawRect(x, y, 50, 50);
}
}
I took the x and y variables and made them member variables so we can access them in the paintComponent() method. I also removed the whole "box" idea and did all the drawing and such in the paintCompnent()
There's also some slight modifications that you should make to your Test2 Class;
Personal recommendation, I suggest switching your drawing code to the mouseReleased event. Along with calling revalidate() and repaint() on your JFrame.
public void mouseReleased(MouseEvent event)
{
int x = event.getXOnScreen();
int y = event.getYOnScreen();
if(isPressed)
{
RectangleComponent rc = new RectangleComponent(x, y);
frame.add(rc);
frame.revalidate();
frame.repaint();
}
}
My results:

Maximizing your frame calls repaint() automatically. It would probably be easiest to call repaint() after adding the RectangleComponent to the frame.
if(isPressed)
{
RectangleComponent rc = new RectangleComponent(x, y);
frame.add(rc);
rc.repaint();
}

I figured instead of adding new component upon click, why not just update a component that already exist by adding more content to it and then repainting it.
Here how this was fixed:
import javax.swing.JComponent ;
import java.awt.event.MouseListener ;
import java.awt.event.MouseEvent ;
import java.awt.Component;
import java.awt.Graphics2D ;
import java.awt.Graphics ;
import java.awt.Shape ;
import java.util.ArrayList ;
public class ShapeComponent extends JComponent
{
private ArrayList<Shape> shapes ;
public ShapeComponent(ArrayList<Shape> shapes1)
{
shapes = shapes1;
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
for (Shape shape : shapes)
{
g2.draw(shape);
}
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Test3
{
static boolean isPressed = false;
static ArrayList<Shape> shapes = new ArrayList<Shape>() ;
public static void main(String[] args)
{
final JFrame frame = new JFrame();
final int FRAME_WIDTH = 400;
final int FRAME_HEIGHT = 400;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("Test 2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel panel = new JPanel();
frame.add(panel,BorderLayout.NORTH);
final JButton btnRectangle = new JButton("Rectangle");
panel.add(btnRectangle);
class RectangleButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
isPressed = true;
}
}
ActionListener rectButtonListener = new RectangleButtonListener();
btnRectangle.addActionListener(rectButtonListener);
final JComponent component = new ShapeComponent(shapes) ;
frame.add(component);
class MousePressListener implements MouseListener
{
public void mousePressed(MouseEvent event)
{
int x = event.getX() ;
int y = event.getY() ;
System.out.println("you have press the mouse at X : " + x + " and Y : " + y);
if(isPressed)
{
Rectangle rnew = new Rectangle(x, y, 20, 30);
shapes.add(rnew);
component.repaint();
System.out.println("the button is pressed");
}
else
{
System.out.println("the button is NOT pressed");
}
}
public void mouseReleased(MouseEvent event){}
public void mouseClicked(MouseEvent event){}
public void mouseEntered(MouseEvent event){}
public void mouseExited(MouseEvent event){}
}
MousePressListener mListener = new MousePressListener();
frame.addMouseListener(mListener);
frame.setVisible(true);
}
}

Related

Mouse Drawing Application: Nothing shows up

This is a word-for-word example straight out of the book Java How to Program by Paul and Harvey Deitel.
PaintPanel.java
// Using class MouseMotionAdapter
import java.awt.Point;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JPanel;
public class PaintPanel extends JPanel {
private int pointCount = 0;
// array of 10,000 java.awt.Point references
private Point[] points = new Point[10000];
// set up gui and register mouse event handler
public PaintPanel() {
addMouseMotionListener(new MouseMotionAdapter() {
// store drag coordinates and repaint
public void MouseDragged(MouseEvent e) {
if (pointCount < points.length) {
points[pointCount] = e.getPoint();
pointCount++;
repaint();
} // end if
}
}
);
}
// draw ovals in a 4 x 4 bounding box at specified location on the window
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g); // clear drawing area
g.setColor(Color.BLUE);
// draw all points in the array
for(int i = 0; i < pointCount; i++)
g.fillOval(points[i].x, points[i].y, 4, 4);
}
}
Driver program Painter.java
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Painter {
public static void main(String[] args) {
JFrame app = new JFrame("A Simple Paint Program");
PaintPanel pp = new PaintPanel();
app.add(pp, BorderLayout.CENTER);
app.add(new JLabel("Drag the rat to draw"), BorderLayout.SOUTH);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(400, 200);
app.setVisible(true);
}
}
When I run it, it shows the drawing panel but nothing happens when I try to draw on it with the mouse. All code is copied verbatim from the book. What gives?
Java is case sensitive. It's mouseDragged, not MouseDragged. This is why you should always use #Override on methods you "think" you're overriding, this way you get compile time protection.
Runnable example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new PaintPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPanel extends JPanel {
private int pointCount = 0;
// array of 10,000 java.awt.Point references
private Point[] points = new Point[10000];
// set up gui and register mouse event handler
public PaintPanel() {
addMouseMotionListener(new MouseMotionAdapter() {
// store drag coordinates and repaint
#Override
public void mouseDragged(MouseEvent e) {
if (pointCount < points.length) {
points[pointCount] = e.getPoint();
pointCount++;
repaint();
} // end if
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
// draw ovals in a 4 x 4 bounding box at specified location on the window
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // clear drawing area
g.setColor(Color.BLUE);
// draw all points in the array
for (int i = 0; i < pointCount; i++) {
g.fillOval(points[i].x, points[i].y, 4, 4);
}
}
}
}

How to display floating tool tip text on a polygon

I have written a Java code to draw a polygon on an image. When I put my cursor inside the polygon it prints "Inside" otherwise "Outside". So the detection of the points inside the polygon is working fine.
But I want to implement the effect of setToolTipText inside the polygon i.e. at the time of mouse hover inside the polygon, it will show the floating text "Inside".
Similar to the effect in this image:
http://www.java2s.com/Code/Java/Swing-JFC/WorkingwithTooltipText.htm
What are the minimal changes to be made in the following code to get the desired effect?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.image.*;
import java.awt.Graphics.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
class page1 extends JFrame implements MouseListener,MouseMotionListener ,ActionListener
{
JFrame f;
JLabel l;
JPanel p1;
ImageIcon ii;
Image img;
int height;
int width;
Container c;
int pixels[];
PixelGrabber pg;
JPanel panel;
Graphics2D gg;
Polygon pp1=new Polygon();
boolean startHovercurrent,startHoverprev=false;
page1()
{
f=new JFrame("Sample Page");
ii=new ImageIcon("sample.jpg");
img=ii.getImage();
height=ii.getIconHeight();
width=ii.getIconWidth();
pixels=new int[ii.getIconWidth()*ii.getIconHeight()];
pg=new PixelGrabber(img,0,0,ii.getIconWidth(),ii.getIconHeight(),pixels,0,ii.getIconWidth());
try
{
pg.grabPixels();
}
catch(InterruptedException k)
{
}
//add points of polygon
pp1.addPoint(300,300);
pp1.addPoint(380,300);
pp1.addPoint(380,220);
pp1.addPoint(300,220);
l=new JLabel(ii,JLabel.CENTER);
c=f.getContentPane();
JDesktopPane desk = new JDesktopPane();
JInternalFrame p = new JInternalFrame("Image Frame",false, false, true, false);
JScrollPane scroll = new JScrollPane(l);
p.setContentPane(scroll);
p.setBounds(0, 0, 740, 600);
desk.add(p);
p.setVisible(true);
l.addMouseListener(this);
l.addMouseMotionListener(this);
c.add(desk, BorderLayout.CENTER);
f.setSize(1024,738);
f.setVisible(true);
}
public static void main(String args[])
{
new page1();
}
public void mouseClicked(MouseEvent me)
{
}
public void mouseEntered(MouseEvent me)
{
}
public void mouseExited(MouseEvent me)
{
}
public void mousePressed(MouseEvent me)
{
}
public void mouseReleased(MouseEvent me)
{
}
public void mouseMoved(MouseEvent me)
{
boolean contain1;
int mx,my;
gg=(Graphics2D)l.getGraphics();
gg.setColor(new Color(255,0,0) );
gg.fillPolygon(pp1);
mx = me.getX();
my = me.getY();
//check if mouse cursor is inside polygon or not
// do not print anything if next cursor position is in same state
contain1=pp1.contains(mx,my);
if (contain1) {
startHovercurrent = true;
if(startHovercurrent!=startHoverprev)
System.out.println("Inside");
startHoverprev=startHovercurrent;
}
else {
startHovercurrent = false;
if(startHovercurrent!=startHoverprev)
System.out.println("Outside");
startHoverprev=startHovercurrent;
}
}
public void mouseDragged(MouseEvent me)
{
}
public void actionPerformed(ActionEvent ae)
{
}
}
For this usage, How to Use Tool Tips suggests overriding the getToolTipText() method of the enclosing JComponent. This answer outlines the approach for JMapViewer and ChartPanel. In the example below, getToolTipText() simply returns the name of any Shape that contains() the triggering mouse event. For comparison, the JLabel at window's bottom gets a conventional too tip via setToolTipText().
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.ToolTipManager;
/**
* #see https://stackoverflow.com/a/53609066/230513
* #see https://stackoverflow.com/a/25944439/230513
*/
public class ShapeToolTip {
private static class ShapePanel extends JPanel {
private final List<Shape> list = new ArrayList<>();
public ShapePanel() {
Polygon p = new Polygon();
p.addPoint(500, 100);
p.addPoint(500, 400);
p.addPoint(200, 400);
list.add(p);
list.add(new Ellipse2D.Double(100, 100, 200, 200));
ToolTipManager.sharedInstance().registerComponent(this);
}
#Override
public String getToolTipText(MouseEvent e) {
for (Shape shape : list) {
if (shape.contains(e.getX(), e.getY())) {
return shape.getClass().getName();
}
}
return "Outside";
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.blue);
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(2));
for (Shape shape : list) {
g2d.draw(shape);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
}
private void display() {
JFrame f = new JFrame("ShapeToolTip");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new ShapePanel());
JLabel title = new JLabel("Shape Tool Tip", JLabel.CENTER);
title.setToolTipText("Title");
title.setFont(title.getFont().deriveFont(Font.BOLD, 24));
f.add(title, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new ShapeToolTip()::display);
}
}

Adding multiple JPanel extended components to a JFrame

I'm new to Java and I've recently been trying to make an Atari Breakout game. I managed to get the player moving and the ball to bounce but not at the same time in the JFrame (the component that was added the latest is the one that is being shown). I made two seperate classes for the player and the ball (both extending from JPanel) and I think that might be the problem, though I don't really know.
Anyway, this is the code for the player:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Player extends JPanel implements ActionListener, KeyListener{
Timer t = new Timer(5,this);
int x=200,vel=0;
boolean outOfBoundsR = true, outOfBoundsL = true;
public Player(){
t.start();
addKeyListener(this);
setFocusable(true);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Rectangle r= g2.getClipBounds();
r.x = x;
g2.setColor(Color.blue);
g2.fill(new Rectangle2D.Double(r.getX(),350,100,5));
if(r.getX()>385){
vel=0;
outOfBoundsR = false;
}else if(r.getX()<0){
vel=0;
outOfBoundsL = false;
}
}
public void actionPerformed(ActionEvent e){
repaint();
x+=vel;
}
public void right(){
vel = 1;
}
public void left(){
vel = -1;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT&&outOfBoundsR){
outOfBoundsL=true;
right();
} else if(key == KeyEvent.VK_LEFT&&outOfBoundsL){
outOfBoundsR=true;
left();
}
}
public void keyReleased(KeyEvent e) {vel = 0;}
public void keyTyped(KeyEvent e) {}
}
This is the code for the ball:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import javax.print.attribute.standard.Media;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Ball extends JPanel implements ActionListener{
Timer t = new Timer(5,this);
double velx = 0, vely = -1, x = 250, y = 330;
public Ball(){
t.start();
setFocusable(true);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Rectangle r = g2.getClipBounds();
r.x = (int) x;
r.y = (int) y;
g2.fill(new Ellipse2D.Double(r.getX(), r.getY(), 8, 8));
if(r.getY() < 0 || r.getY() > 355){
vely -= (vely*2);
}else if(r.getX() < 0 || r.getX() > 480){
velx -= (velx*2);
}
}
public void actionPerformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}
}
And this is the code for the GUI:
import javax.swing.JFrame;
public class Gui extends JFrame{
public static void main(String[] args) {
JFrame f= new JFrame(); // the frame
Ball b = new Ball(); // the ball
Player p = new Player();// the player
f.getContentPane().add(p);
f.getContentPane().add(b);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500,400);
f.setVisible(true);
}
}
Thanks in advance! (I know this was a bit long...)
I don't know how you want your Ball and Player objects to interact, but in your example f.getContentPane().add(...) translates to f.getContentPane().add(..., BorderLayout.CENTER). Therefore, p is replaced by b in the subsequent call to add - the content pane of JFrame makes use of a BorderLayout by default.
Have a look at the Swing layout manager tutorial for more information.
I think that better way to do it is make player and ball as component and make next object which can be JPanel as a game. But your way should work too. Problem can be with chosen layout in your frame. I can suggest this changes for you.
public static void main(String[] args) {
JFrame f= new JFrame(); // the frame
Ball b = new Ball(); // the ball
Player p = new Player();// the player
f.getContentPane().add(p, BorderLayout.CENTRE);
f.getContentPane().add(b, BorderLayout.EAST);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500,400);
f.setVisible(true);
}

Drawing on JPanel behind GlassPane when clicking on GlassPane

Okay So I looked through multiple forums and Google and couldn't find an answer to my specific problem. So I have two panels stacked on top of each other and the one on top is a glassPane. When you drag your mouse around the glassPane it draws a vertical red line at the cursor,which works, but when I click on the glassPane I want it it draw a black line at the cursor position on the panel below the glassPane. I can get it to redirect the mouseClick to the bottom panel but it wont draw the line. It just makes the redline disappear until you move the mouse again. Also If I set the glassPane invisible and click on the bottom panel the line is drawn so the drawing code works just fine. Thanks in advance.
Main Class
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Robot;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
public class LiveField extends JPanel {
/**
* Create the panel.
*/
static JFrame frame;
static JPanel ContentPane;
private JPanel panel;
private MyGlassPane glassPane;
public static void main(String[] args) throws AWTException
{
LiveField live = new LiveField();
frame.setVisible(true);
}
public LiveField() throws AWTException {
frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 433);
setLayout(new BorderLayout(0, 0));
ContentPane = new JPanel();
frame.setContentPane(ContentPane);
ContentPane.setLayout(new BorderLayout(0, 0));
panel = new JPanel()
{
public void paintComponent(Graphics g) {
super.paintComponent(g);
panel.setBackground(new Color(50,160,55));
}
};
glassPane = new MyGlassPane(panel);
frame.setGlassPane(glassPane);
glassPane.setVisible(true);
panel.addMouseListener(new MouseAdapter() {
int[] pos = new int[2];
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Handles click event");
Graphics g = panel.getGraphics();
g.setColor(new Color(50,165,55));
g.drawLine(pos[0], pos[1], 0+pos[0], 0);//to top
g.drawLine(pos[0], pos[1], 0+pos[0], panel.getHeight());//to bottom
int y = e.getYOnScreen();
int x = e.getXOnScreen();
pos[0]= x;
pos[1] = y;
g.setColor(new Color(0,0,0));
g.drawLine(x, y, 0+x, 0);//to top
g.drawLine(x, y, 0+x, panel.getHeight());//to bottom
g.dispose();
}
});
ContentPane.add(panel, BorderLayout.CENTER);
}
GlassPane Class
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JComponent;
class MyGlassPane extends JComponent implements ItemListener {
Point point;
protected void paintComponent(Graphics g) {
}
public void setPoint(Point p) {
point = p;
}
public MyGlassPane(final Container contentPane) throws AWTException {
final Component glass = this;
addMouseMotionListener(new MouseMotionListener()
{
ArrayList<Integer> line = new ArrayList<Integer>();
Robot rb = new java.awt.Robot();
#Override
public void mouseMoved(MouseEvent e) {
//System.out.println("Moving");
Graphics g = glass.getGraphics();
if(!line.isEmpty())
{
//System.out.println("line is not empty");
g.setColor(new Color(50,160,55));
g.drawLine(line.get(0), line.get(1), 0+line.get(0), 0);//to top
g.drawLine(line.get(0), line.get(1), 0+line.get(0), contentPane.getHeight());//to bottom
}
//System.out.println("draw line");
int x = e.getXOnScreen();
int y = e.getYOnScreen();
Color col = rb.getPixelColor(x, y);
//System.out.println(col.toString() + " : " + Color.white.toString());
//System.out.println(col.equals(new Color(255,255,255)));
if(!col.equals(new Color(255,255,255)) && !inEndZone(x))
{
g.setColor(new Color(255,0,0));
line = new ArrayList<Integer>();
line.add(x);line.add(y);
g.drawLine(x, y, 0+line.get(0), 0);//to top
g.drawLine(x, y, 0+line.get(0), contentPane.getHeight());//to bottom
}
g.dispose();
}
private boolean inEndZone(int x) {
int ends = contentPane.getWidth()/10;
//System.out.println(x + " : " + ends);
if(x<ends)
{
//System.out.println("In endzone");
return true;
}
else if(x>contentPane.getWidth()-ends)
{
return true;
}
else
{
return false;
}
}
#Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
}
});
addMouseListener(new CBListener(this,contentPane));
}
#Override
public void itemStateChanged(ItemEvent e) {
// TODO Auto-generated method stub
setVisible(e.getStateChange() == ItemEvent.SELECTED);
}
}
Listener Class ( for dispatching the mouse click)
import java.awt.Component;
import java.awt.Container;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;
class CBListener extends MouseInputAdapter {
Toolkit toolkit;
Robot rb;
MyGlassPane glassPane;
Container contentPane;
public CBListener(MyGlassPane glassPane, Container contentPane) {
toolkit = Toolkit.getDefaultToolkit();
this.glassPane = glassPane;
this.contentPane = contentPane;
}
#Override
public void mouseClicked(MouseEvent e) {
redispatchMouseEvent(e, false);
}
// A basic implementation of redispatching events.
private void redispatchMouseEvent(MouseEvent e, boolean repaint) {
Point glassPanePoint = e.getPoint();
Container container = contentPane;
Point containerPoint = SwingUtilities.convertPoint(glassPane,
glassPanePoint, contentPane);
if (containerPoint.y < 0) { // we're not in the content pane
} else {
// The mouse event is probably over the content pane.
// Find out exactly which component it's over.
Component component = SwingUtilities.getDeepestComponentAt(
container, containerPoint.x, containerPoint.y);
if ((component != null) && (component.equals(contentPane))) {
System.out.println("contentPane");
// Forward events over the check box.
Point componentPoint = SwingUtilities.convertPoint(glassPane,
glassPanePoint, component);
component.dispatchEvent(new MouseEvent(component, e.getID(), e
.getWhen(), e.getModifiers(), componentPoint.x,
componentPoint.y, e.getClickCount(), e
.isPopupTrigger()));
}
}
// Update the glass pane if requested.
if (repaint) {
glassPane.setPoint(glassPanePoint);
glassPane.repaint();
}
}
}
I can get it to redirect the mouseClick to the bottom panel but it
wont draw the line. It just makes the redline disappear until you move
the mouse again
No, It is drawing black line indeed. But the line is drawn above the red line that makes the red line to vanish till the mouse is moved again . I Guess you are looking for something like this:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class DoublePanel extends JFrame
{
JPanel mainPanel;
int x1;
public void prepareAndShowGUI()
{
setTitle("DoublePanel");
mainPanel = new JPanel()
{
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLACK);
g.drawLine(x1,0,x1,this.getHeight());
}
};
mainPanel.setBackground(new Color(50,160,55));
mainPanel.setLayout(new BorderLayout());
mainPanel.add(new upperPanel(this));
setContentPane(mainPanel);
setSize(500,600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
}
public void setXValue(int x)
{
this.x1 = x;
mainPanel.repaint();
}
class upperPanel extends JPanel
{
int x; int y;
DoublePanel dp;
upperPanel(DoublePanel d)
{
this.dp = d;
setOpaque(false);
addMouseMotionListener(new MouseAdapter()
{
#Override
public void mouseMoved(MouseEvent evt)
{
x = evt.getX();
y = evt.getY();
repaint();
}
});
addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent evt)
{
dp.setXValue(evt.getX());
}
});
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.RED);
g.drawLine(x,0,x,this.getHeight());
}
}
public static void main(String st[])
{
SwingUtilities.invokeLater( new Runnable()
{
public void run()
{
DoublePanel dp = new DoublePanel();
dp.prepareAndShowGUI();
}
});
}
}
You need to call the bottom panel's repaint().

Moving images in Java

I want to make an image that I drew in the paint class move left across my JFrame as a timer ticks. But I don't know how to do that. Also, I am trying to get my program to make the image disappear when the image is clicked upon.
movingball class
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JPanel;
import javax.swing.Timer;
public class movingball extends JPanel{
private int move=50;
private Timer timer = new Timer(move, new TimerListener());
private int radius = 10;
private int x = 300;
private int y = 0;
public movingball() {
timer.start();
}
private class TimerListener implements ActionListener{
public void actionPerformed(ActionEvent e){
x=x-20;
repaint(); }//trying to get the oval to move left 20
}
protected void paintComponent(Graphics2D g){
super.paintComponent(g);
g.fillOval(x, 100 , radius * 2, radius * 2); }
}
movingControl class
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
public class movingControl extends JPanel {
private movingball ball= new movingball();
public movingControl(){
JPanel panel = new JPanel();
ball.setBorder(new javax.swing.border.LineBorder(Color.red));
panel.addMouseListener(new movingballListener());
setLayout(new BorderLayout());
add(ball, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
}
}
SnniperGameApp class
I know I spelled sniper wrong
import javax.swing.JApplet;
public class SnniperGameApp extends JApplet {
static final long serialVersionUID = 2777718668465204446L;
//i dont know what this serial thing is. But my program wont start without it
public SnniperGameApp(){
add(new movingControl());
}
}
ClickingEvent class
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
class movingballListener extends MouseAdapter{
public void mouseReleased(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON1_DOWN_MASK) != 0) {
System.out.println( (e.getPoint()));}}
}
You haven't over-ridden paintComponent() properly.
From the javadoc, the signature of paintComponent() is:
protected void paintComponent(Graphics g)
but you have:
protected void paintComponent(Graphics2D g)
The method signatures must match - you can safely cast the Graphics to a Graphics2D inside the method if needed.
Adding the #Override annotation to a method is a good way to get the compiler to check that you really are over-riding a method, not just writing a method that looks the same!
Here's a working SSCCE (I have inlined some of the constants to save space, don't take that as good practice for real code!):
public class MovingBall extends JPanel
{
private Timer timer = new Timer(50, new TimerListener());
private int x = 300;
public MovingBall()
{
timer.start();
}
private class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
x -= 20;
repaint();
}
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillOval(x, 100, 20, 20);
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.add(new MovingBall());
frame.setSize(500, 500);
frame.setVisible(true);
}
}

Categories

Resources