I am trying to make a simple game which displays circles on a frame and when clicked the circle should disappear. I am learning how Java Swing works and managed to draw a circle (Wow such an achievement) and figured out how events work. I added an mouseListener to the circle and when clicked for now I want a to get a console log that it has been clicked but the end result is not as expected. No matter where I click I always get the "click" console log. When I try to add a listener to a JButton for example I get the end result. Are events different for graphics?
import javax.swing.*;
import javax.swing.event.MouseInputListener;
import java.awt.*;
import java.awt.event.*;
import java.sql.SQLOutput;
public class CirclePop {
JFrame frame;
Circle circle;
public static void main(String[] args) {
CirclePop circlePop = new CirclePop();
circlePop.drawFrame();
}
public void drawFrame() {
frame = new JFrame();
circle = new Circle();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(circle);
circle.addMouseListener(new Click());
frame.setSize(300, 300);
frame.setVisible(true);
}
class Click implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("Pressed");
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
}
import java.awt.*;
import javax.swing.*;
class Circle extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.red);
g.fillOval(150, 140, 30, 30);
}
}
First of all, you may want to extend MouseAdapter instead of implementing MouseListener. This way you don't have "implement" all these empty methods.
Then, in your mousePressed method you just have to calculate if the click happened inside the circle. This is basically just Pythagoras:
static class ClickListener extends MouseAdapter {
private final Circle circle;
public ClickListener(Circle circle) {
this.circle = circle;
}
#Override
public void mousePressed(MouseEvent e) {
int centerX = circle.getCenterX();
int centerY = circle.getCenterY();
int radius = circle.getRadius();
int clickX = e.getX();
int clickY = e.getY();
// inside circle: (clickX - centerX)^2 + (clickY - centerY)^2 < radius^2
double xSquare = Math.pow(clickX - centerX, 2);
double ySquare = Math.pow(clickY - centerY, 2);
if (xSquare + ySquare < radius * radius) {
System.out.println("pressed");
}
}
}
I've added some fields to Circle class to get access to the properties you need for the calculation:
class Circle extends JPanel {
private final int radius = 30;
private final int centerX = 150;
private final int centerY = 140;
public void paintComponent(Graphics g) {
g.setColor(Color.red);
g.fillOval(centerX, centerY, radius, radius);
}
// getter, etc.
}
You have to implement the MouseListener interface indeed, and after a mouse click, you have to check whether the mouse position is contained in the region of your circle. You could do this manually, by comparing coordinates, but this could be a bit too much work. I think it's easier to rather create a Shape object(Infact this is a good time to learn about it since you're just starting out) that you fill with the respective color, and then just check whether the circle contains the mouse position.
Also, check out the Shape class docs when you've got some spare time.
I've gone ahead and made changes to your code, it now uses an instance of Shape class to create a circle.
Also, instead of implementing the MouseListener interface, I recommend extending MouseAdapter since you're not actually providing any meaningful implementation to any method of the interface except the mousePressed() method.
Lastly, notice the shape.contains(event.getPoint()) in the mousePressed() method, that is what does the trick for checking the coordinates.
The rest of the code should be familiar.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class CirclePop {
JFrame frame;
Circle circle;
public static void main(String[] args) {
CirclePop circlePop = new CirclePop();
circlePop.drawFrame();
}
public void drawFrame() {
frame = new JFrame();
circle = new Circle();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(circle);
circle.addMouseListener(new Click());
frame.setSize(300, 300);
frame.setVisible(true);
}
class Click extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
if (circle.shape.contains(e.getPoint())) {
System.out.println("Pressed");
}
}
}
}
class Circle extends JPanel {
Shape shape;
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
shape = new Ellipse2D.Double(150, 140, 30, 30);
g2.setColor(Color.red);
g2.fill(shape);
}
}
Okay, so, this isn't going to be short
Let's start with ....
frame = new JFrame();
circle = new Circle();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(circle);
circle.addMouseListener(new Click());
frame.setSize(300, 300);
frame.setVisible(true);
Okay, seems simple enough, but, one thing you've missed is the fact that JFrame, by default, uses a BorderLayout - this means, it will make the child component (and the centre/default position) fill all the available space of the frames viewable space
You can see this if you do something like...
frame = new JFrame();
circle = new Circle();
circle.setBackground(Color.RED);
You will now see that the Circle component occupies the entire frame, so when you click on it, you're clicking the Circle component itself.
This isn't bad, but, you might want to change tact a little. Instead of adding the MouseListener independently of the Circle, have the Circle component make use of its own MouseListener, for example...
class Circle extends JPanel {
public Circle() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
// More to come...
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillOval(150, 140, 30, 30);
}
}
This means you get to control much of the logic internally to the class, makes it easier to access some of the more critical information without needing to make a bunch of, potentially, dangerous casts.
So, now we just need to add the logic in to determine if the mouse was clicked within the desirable location or not...
public void mouseClicked(MouseEvent e) {
Point point = e.getPoint();
if (point.x >= 150 && point.x <= 150 + 30 && point.y >= 140 && point.y <= 140 + 30) {
System.out.println("You clicked me :(");
}
}
Okay, that's ... basic
We can simplify it a little and make use of the available functionality within the wider API by making use of the "shapes" API, for example...
class Circle extends JPanel {
private Ellipse2D dot = new Ellipse2D.Double(150, 140, 30, 30);
public Circle() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
Point point = e.getPoint();
if (dot.contains(point)) {
System.out.println("You clicked me :(");
}
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.red);
g2d.fill(dot);
g2d.dispose();
}
}
The benefit of this, apart from contains, is we can change the position of the shape relatively easily and our if statement contains to work 🎉
I do, highly, recommend also having a look at
Performing Custom Painting
Painting in AWT and Swing
2D Graphics Trail
Working with Geometry
I'm trying to draw a shape multiple times inside a JPanel to mimic an animation (a moving shape across it). The problem is that the shape is being redrawn and thus appearing on the screen multiple times on different places, when all i pretend is that only one shape is visible at a time when it's being redrawn.
The method super.paintComponent() should be responsible for repainting JPanel's background and thus, only one shape should be visible when the redrawing is being performed.
I have the following code (it has been reduced/simplified for the sake of simplicity and better understanding):
public class Animated_Shape_Test extends JFrame
{
public static void main(String args[]) throws IOException
{
new Animated_Shape_Test();
}
public Animated_Shape_Test() throws IOException
{
this.setSize(500, 500);
this.setPreferredSize(new Dimension(500, 500));
this.setLocation(new Point(430, 150));
this.setTitle("Database Launcher v1.0");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setVisible(true);
DBPanel panel = new DBPanel();
getContentPane().add(panel, BorderLayout.CENTER);
}
}
final class DBPanel extends JPanel implements Runnable
{
int musicShapePosX = 85;
int musicShapePosY = 100;
int SEGMENT_SHAPE_LENGTH = 50;
int SHAPE_HEIGHT = 10;
float SHAPE_SPEED = 7.5f;
CustomShapeButton musicShapeButton = new CustomShapeButton(musicShapePosX, musicShapePosY, SEGMENT_SHAPE_LENGTH, SHAPE_HEIGHT);
private ArrayList<Shape> shapes = null;
protected DBPanel() throws IOException
{
shapes = new ArrayList();
shapes.add(musicShapeButton);
this.setOpaque(true);
this.setFocusable(true);
startThread();
}
public void startThread()
{
Thread t = new Thread(this);
t.start();
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(getBackground().darker());
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setColor(Color.BLACK);
g2.draw(musicShapeButton);
}
public void delay(int milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (InterruptedException e)
{
}
}
#Override
public void run()
{
while (true)
{
delay(35);
animateButtonShapeMusic();
repaint();
}
}
public void animateButtonShapeMusic()
{
if (musicShapePosY < 228)
{
musicShapePosY = (int)(musicShapePosY + SHAPE_SPEED);
musicShapeButton.drawShape(musicShapePosX, musicShapePosY, SEGMENT_SHAPE_LENGTH, SHAPE_HEIGHT);
}
}
}
I'm getting several shapes being redrawn across the screen (animation).
I expect a single shape being redrawn across the screen (animation).
Thank you in advance.
class MyPanel extends JPanel implements Observer, MouseMotionListener, MouseListener {
private MyModel model;
private View view;
private String mode;
private Rectangle rectangle;
private Square square;
public MyPanel(MyModel model, View view) {
this.setBackground(Color.black);
this.setPreferredSize(new Dimension(300, 300));
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.model = model;
this.model.addObserver(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
ArrayList<Rectangle> rectangles = this.model.getRectangles();
for (Rectangle r : getRectangles()) {
int width = Math.abs(r.getStartPoint().getX() - r.getEndPoint().getX());
int height = Math.abs(r.getStartPoint().getY() - r.getEndPoint().getY());
}
ArrayList<Square> squares = this.model.getSquares();
for (Square sqr : getSquares()) {
int xPosition = Math.min(sqr.getStartPoint().getX(), sqr.getEndPoint().getX());
int yPosition = Math.min(sqr.getStartPoint().getY(), sqr.getEndPoint().getY());
int width = Math.abs(sqr.getStartPoint().getX() - sqr.getEndPoint().getX());
int height = Math.abs(sqr.getStartPoint().getY() - sqr.getEndPoint().getY());
}
g2d.dispose();
}
public void update(Observable o, Object arg) {
this.repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
if (this.mode.equals("Rectangle")) {
this.rectangle.setEndPoint(e.getX(), e.getY());
this.model.addRectangle(this.rectangle);
}
else if (this.mode.equals("Square")) {
// What code should I add here?
this.model.addSquare(this.square);
}
}
// MouseListener below
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {
if (this.mode.equals("Rectangle")) {
this.rectangle = new Rectangle(e.getX(), e.getY());
}
else if (this.mode.equals("Square")) {
this.square = new Square(e.getX(), e.getY());
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (this.mode.equals("Rectangle")) {
this.rectangle.setEndPoint(e.getX(), e.getY());
this.model.addRectangle(this.rectangle);
this.rectangle = null;
}
else if (this.mode.equals("Square")) {
this.model.addSquare(this.square);
this.square = null;
}
}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
}
The user chooses a mode, rectangle or square. Then they can draw a square or a rectangle with their mouse (live feedback is shown). Here is my drawing panel class. I was successfully able to implement the rectangle mode. The user can draw a rectangle and as they move their mouse, the rectangle is shown in mid construction. I want to do the same for the square mode. For some reason, I'm having a hard time doing this. How would I show a perfect square in mid construction when the user is moving their mouse and how would I draw it once released? What code should I add to my paintComponent method, mouseDragged, mousePressed and mouseReleased method to do this? It was easy for a rectangle because there was no constraint but I'm not sure how to do it for a square with my current implementation.
int width = Math.abs(r.getStartPoint().getX() - r.getEndPoint().getX());
int height = Math.abs(r.getStartPoint().getY() - r.getEndPoint().getY());
I would guess that the "size" of the square would be the maximum of the above two values.
Then I would think you would just use:
r.drawStyle(g2d, xPosition, yPosition, size, size);
I'm creating a java game. In the game there are a hero and a bubble. The hero is supposed to move when I press the arrow keys and the bubble is supposed to have continuous diagonal movement. When I add the hero or the bubble directly into to the JFrame separately I get the desired behavior, but when I add them both I just get a very small square! I tried to add them to the same JPanel and after add that JPanel to the JFrame but it is not working. Probably I have to define some type of layout to the JPanels.
What am I doing wrong?
Code:
public class Pang {
public static void main(String[] args) {
JFrame f=new JFrame();
JPanel gamePanel=new JPanel();
gamePanel.setPreferredSize(new Dimension(800, 600));
DrawHero d=new DrawHero();
DrawBubble bubble=new DrawBubble();
gamePanel.add(d);
gamePanel.add(bubble);
f.add(gamePanel);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
}
}
public class DrawHero extends JPanel implements ActionListener, KeyListener {
Timer myTimer = new Timer(5, this);
int x = 0, y = 0, dx = 0, dy = 0, step = 10;
private transient Image imageHero = null;
public DrawHero() {
myTimer.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
imageHero = getHeroImage();
g2.drawImage(imageHero, x, y, 40, 40, null);
}
public Image getHeroImage() {
Image image = null;
image = getImage("hero.png");
return image;
}
public Image getImage(String path) {
Image tempImage = null;
try {
URL heroiURL = DrawHero.class.getResource(path);
tempImage = Toolkit.getDefaultToolkit().getImage(heroiURL);
} catch (Exception e) {
System.out.println("Error loading hero image! - "
+ e.getMessage());
}
return tempImage;
}
public void actionPerformed(ActionEvent e) {
repaint();
}
public void moveUp() {
y = y - step;
}
public void moveDown() {
y = y + step;
}
public void moveLeft() {
x = x - step;
}
public void moveRight() {
x = x + step;
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP) {
moveUp();
}
if (keyCode == KeyEvent.VK_DOWN) {
moveDown();
}
if (keyCode == KeyEvent.VK_LEFT) {
moveLeft();
}
if (keyCode == KeyEvent.VK_RIGHT) {
moveRight();
}
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
}
public class DrawBubble extends JPanel implements ActionListener, KeyListener {
Timer myTimer = new Timer(5, this);
int x = 100, y = 200, dx = 0, dy = 0, step = 10;
private transient Image imageHero = null;
public DrawBubble() {
myTimer.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 40, 40));
}
public void actionPerformed(ActionEvent e) {
x=x+dx;
y=y+dy;
repaint();
}
public void moveBubble() {
dy=2;
dx=2;
}
public void keyPressed(KeyEvent e) {
moveBubble();
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
}
I recommend that neither the DrawHero nor DrawBubble (which should be called Hero nor Bubble respectively) should extend any JComponent. Instead each should simply know how to draw itself to a Graphics object passed to it, when requested to do so.
Then a single GameField or PlayingArea class should keep references to all the Bubble objects and the Hero and draw call the draw(Graphics) method of those objects.
Using this approach it is not necessary to worry about layouts within the GameField component (they become irrelevant).
That is the basic strategy I pursue for rendering the stationary objects in this answer to [Collision detection with complex shapes.
When I add the hero or the bubble directly into to the JFrame separately I get the desired behavior, but when I add them both i just get a very small square!
The default layout manager for a JFrame is a BorderLayout. When you use add(component) without a constraint the component goes to the CENTER. Only one component can be added to the CENTER, so only the last one added is displayed.
I tried to add them to the same JPanel and after add that JPanel to the JFrame but it is not working.
The default layout manager for a JPanel is the FlowLayout which respects the preferred size of component. The problem is you don't override the getPreferredSize() method so the size is (0, 0) and there is nothing to paint.
Probably I have to define some type of layout to the JPanels.
Actually since you want random motion you need to use a null layout on the panel and then use the setSize() and setLocation() method of your components to position the components.
Then when you do this the custom painting should always be done at (0, 0) instead of (x, y) since the location will control where the component is painted on the panel.
I have a 3x3 check board-like image rendered on a JPanel which is added onto a JFrame. Then I have 9 more JPanels (1 on top of each square) and on click something needs to be drawn on the corresponding square. My problem is that it only works for the top-left square. The rest of the drawings seem to be drawn below the checkboard image. So if I comment out the part that loads the checkboard image,and click as if they were there then the drawings appear correctly. I get the same result with a layered pane. Absolute positioning is used and the coordinates seem to be correct since if I remove the checkboard image then the drawings appear where they should and the drawings do not occupy more than a square.
My code is structured as follows:
'main' class creates the frame and adds an instance of another class which extends JPanel and which also draws the checkboard image using paintComponent(Graphics g).
'main' class has also 9 instances added of a class that extends JPanel and draws something on a mouse click using paintComponent(Graphics g). Each instance is placed on top of a square
Please note that because I was going to do it with just Rectangles I named the second class Rectangles but it is rectangualar JPanels not java Rectangle instances
Code:
public class Main3
{
private JFrame frame=new JFrame("");
private Rectangles rect00=new Rectangles(0,0,129,129);
private Rectangles rect01=new Rectangles(136,0,129,129);
private Rectangles rect02=new Rectangles(268,0,129,129);
private Rectangles rect10=new Rectangles(0,136,129,129);
private Rectangles rect11=new Rectangles(134,136,129,129);
private Rectangles rect12=new Rectangles(269,137,129,129);
private Rectangles rect20=new Rectangles(0,270,129,129);
private Rectangles rect21=new Rectangles(136,269,129,129);
private Rectangles rect22=new Rectangles(269,270,129,129);
public void Display()
{
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(null);
frame.setSize(600,400);
sub inter=new sub();
inter.setLayout(null);
inter.setBounds(0,0,600,400);
inter.setSize(600,400);
rect00.setBounds(rect00.getX(),rect00.getY(),rect00.getWidth(),rect00.getHeight());
rect01.setBounds(rect01.getX(),rect01.getY(),rect01.getWidth(),rect01.getHeight());
rect02.setBounds(rect02.getX(),rect02.getY(),rect02.getWidth(),rect02.getHeight());
rect10.setBounds(rect10.getX(),rect10.getY(),rect10.getWidth(),rect10.getHeight());
rect11.setBounds(rect11.getX(),rect11.getY(),rect11.getWidth(),rect11.getHeight());
rect12.setBounds(rect12.getX(),rect12.getY(),rect12.getWidth(),rect12.getHeight());
rect20.setBounds(rect20.getX(),rect20.getY(),rect20.getWidth(),rect20.getHeight());
rect21.setBounds(rect21.getX(),rect21.getY(),rect21.getWidth(),rect21.getHeight());
rect22.setBounds(rect22.getX(),rect22.getY(),rect22.getWidth(),rect22.getHeight());
rect00.setOpaque(false);
rect01.setOpaque(false);
rect02.setOpaque(false);
rect10.setOpaque(false);
rect11.setOpaque(false);
rect12.setOpaque(false);
rect20.setOpaque(false);
rect21.setOpaque(false);
rect22.setOpaque(false);
inter.add(rect00);
inter.add(rect01);
inter.add(rect02);
inter.add(rect10);
inter.add(rect11);
inter.add(rect12);
inter.add(rect20);
inter.add(rect21);
inter.add(rect22);
frame.add(inter);
frame.setResizable(false);
frame.setVisible(true);
}
public static void main(String args[])
{
new main().Display();
}
private class sub extends JPanel
{
private BufferedImage image;
public sub ()
{
try
{
image=ImageIO.read(new File("image.jpg"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(600,400));
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
}
}
This is the other class
public class Rectangles extends JPanel implements MouseListener
{
private int Posx;
private int Posy;
private int width;
private int height;
private boolean selected=false;
public Rectangles(int Posx,int Posy,int width,int height)
{
this.Posx=Posx;
this.Posy=Posy;
this.width=width;
this.height=height;
this.addMouseListener(this);
}
#Override
protected void paintComponent(Graphics g)
{
if(selected==true)
{
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g2);
g2.setColor(new Color(250, 235, 215));
g2.drawRect(Posx,Posy,width,height);
Graphics2D g3=(Graphics2D)g;
g2.setColor(new Color(0,0,0));
g3.setStroke(new BasicStroke(20));
g3.drawLine(Posx,Posy,Posx+width,Posy+height);
g3.drawLine(Posx+width,Posy,Posx,Posy+height);
}
}
public int getX()
{
return Posx;
}
public int getY()
{
return Posy;
}
public int getWidth()
{
return width;
}
public int getHeight()
{
return height;
}
public void setSelected()
{
selected=true;
}
#Override
public void mouseClicked(MouseEvent arg0)
{
}
#Override
public void mouseEntered(MouseEvent arg0)
{
}
public void mouseExited(MouseEvent arg0)
{
}
#Override
public void mousePressed(MouseEvent arg0)
{
}
#Override
public void mouseReleased(MouseEvent arg0)
{
selected=true;
repaint();
}
}
1) You dont honor the components paint chain.
As per java docs for paintComponent(Graphics g):
Further, if you do not invoker super's implementation you must honour
the opaque property, that is if this component is opaque, you must
completely fill in the background in a non-opaque color. If you do not
honor the opaque property you will likely see visual artifacts.
2) super.paintComponent would in most cases be the first call in the method.
3) But there is more, your cast to Graphics2D twice, that should not be done:
Graphics2D g2 = (Graphics2D) g;
...
Graphics2D g3=(Graphics2D)g;
omit the g3 its not needed you already have casted to a Graphics2D object
4) Another problem lies here in sub class. You do this in your main code:
inter.add(rect00);
inter.add(rect01);
...
but in inter which is your variable name for the instance of sub class you only have:
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
Thus it will only draw a single image no matter how many rectangles you add!
Also dont do
g2.drawLine(Posx, Posy, Posx + width, Posy + height); rather
g2.drawLine(0, 0, Posx + width, Posy + height); as the JPanel has been added at co-ordinates x and y on its container, when you draw on the JPanel we want to start at the top left i.e 0,0, changing the value would move the image further down on its conatiner
See fixed code here:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
private JFrame frame = new JFrame("");
private Rectangles rect00 = new Rectangles(0, 0, 129, 129);
private Rectangles rect01 = new Rectangles(136, 0, 129, 129);
private Rectangles rect02 = new Rectangles(268, 0, 129, 129);
private Rectangles rect10 = new Rectangles(0, 136, 129, 129);
private Rectangles rect11 = new Rectangles(134, 136, 129, 129);
private Rectangles rect12 = new Rectangles(269, 137, 129, 129);
private Rectangles rect20 = new Rectangles(0, 270, 129, 129);
private Rectangles rect21 = new Rectangles(136, 269, 129, 129);
private Rectangles rect22 = new Rectangles(269, 270, 129, 129);
public void Display() {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(null);
frame.setSize(600, 400);
sub inter = new sub();
inter.setLayout(null);
inter.setBounds(0, 0, 600, 400);
inter.setSize(600, 400);
rect00.setBounds(rect00.getX(), rect00.getY(), rect00.getWidth(), rect00.getHeight());
rect01.setBounds(rect01.getX(), rect01.getY(), rect01.getWidth(), rect01.getHeight());
rect02.setBounds(rect02.getX(), rect02.getY(), rect02.getWidth(), rect02.getHeight());
rect10.setBounds(rect10.getX(), rect10.getY(), rect10.getWidth(), rect10.getHeight());
rect11.setBounds(rect11.getX(), rect11.getY(), rect11.getWidth(), rect11.getHeight());
rect12.setBounds(rect12.getX(), rect12.getY(), rect12.getWidth(), rect12.getHeight());
rect20.setBounds(rect20.getX(), rect20.getY(), rect20.getWidth(), rect20.getHeight());
rect21.setBounds(rect21.getX(), rect21.getY(), rect21.getWidth(), rect21.getHeight());
rect22.setBounds(rect22.getX(), rect22.getY(), rect22.getWidth(), rect22.getHeight());
rect00.setOpaque(false);
rect01.setOpaque(false);
rect02.setOpaque(false);
rect10.setOpaque(false);
rect11.setOpaque(false);
rect12.setOpaque(false);
rect20.setOpaque(false);
rect21.setOpaque(false);
rect22.setOpaque(false);
inter.addPanel(rect00);
inter.addPanel(rect01);
inter.addPanel(rect02);
inter.addPanel(rect10);
inter.addPanel(rect11);
inter.addPanel(rect12);
inter.addPanel(rect20);
inter.addPanel(rect21);
inter.addPanel(rect22);
frame.add(inter);
frame.setResizable(false);
frame.setVisible(true);
}
public static void main(String args[]) {
new Test().Display();
}
private class sub extends JPanel {
private BufferedImage image;
private ArrayList<Rectangles> rects = new ArrayList<>();
public sub() {
try {
image = ImageIO.read(new File("c:/image.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return (new Dimension(600, 400));
}
void addPanel(Rectangles r) {
rects.add(r);
add(r);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Rectangles r : rects) {
g.drawImage(image, r.getX(), r.getY(), null);
}
}
}
}
class Rectangles extends JPanel implements MouseListener {
private int Posx;
private int Posy;
private int width;
private int height;
private boolean selected = false;
public Rectangles(int Posx, int Posy, int width, int height) {
this.Posx = Posx;
this.Posy = Posy;
this.width = width;
this.height = height;
this.addMouseListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (selected == true) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(250, 235, 215));
g2.drawRect(0,0, width, height);
g2.setColor(new Color(0, 0, 0));
g2.setStroke(new BasicStroke(20));
g2.drawLine(0,0, width,height);
g2.drawLine(getWidth(),0, 0, height);
}
}
public int getX() {
return Posx;
}
public int getY() {
return Posy;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void setSelected() {
selected = true;
}
#Override
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
}
#Override
public void mouseReleased(MouseEvent arg0) {
selected = true;
repaint();
}
}
A few other pointers:
Dont use Absolute/Null layout. A GridLayout or GridBagLayout would suit your needs fine. (see here for more.)
Dont do JFrame#setSize(...); rather use Correct LayoutManager and call pack() on JFrame before setting it visible.
Dont call setSize on your Rectangles instances, simply override getPreferredSize like you did with sub panel??
No need for implementing MouseListener, just use MouseAdapter thus giving you the freedom to choose which methods to override and not just override all.
Have a read on Concurrency in Swing especailly Event-Dispatch-Thread