My code is basically about having a frame and it has a button. You press the button you can draw rectangles, getting coordinates from the mouse press and the mouse release.
Now, if you remove the button the code works perfectly, here is the code.
//testing file
package ActionTest;
import java.awt.*;
import javax.swing.*;
public class MouseTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new MouseFrame();
frame.setTitle("MouseTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500,500);
}
});
}
}
My frame, calls on the mouse component
package ActionTest;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class MouseFrame extends JFrame
{
public MouseFrame()
{
add(new MouseComponent());
}
}
The component class: handles mouse clicks and drawing the rectangle
package ActionTest;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
public class MouseComponent extends JComponent
{
Point first;
Point second;
private ArrayList<Rectangle2D> rectangles;
public MouseComponent()
{
rectangles = new ArrayList<>();//contains rectangles
addMouseListener(new MouseHandler());
}
//paint method of the component, simply re-paint the array
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
for (Rectangle2D r : rectangles)
g2.draw(r);
}
/**
* creates a rectangle and adds it to the rectangles ArrayList
* then repaint the component
* inside some operations to deal with rectangle drawing nothing to do with the issue
* #param p1: first coordinates
* #param p2: second coordinates
*/
public void addRec(Point2D p1, Point2D p2)
{
double w, h, x, y;
double x1 = p1.getX();
double y1 = p1.getY();
double x2 = p2.getX();
double y2 = p2.getY();
if(x1 <= x2){
x = x1;
w = x2-x1;
}
else{
x = x2;
w = x1-x2;
}
if (y1 <= y2){
y = y1;
h = y2-y1;
}
else{
y = y2;
h = y1-y2;
}
rectangles.add(new Rectangle2D.Double(x, y, w, h));
repaint();
}
//records mouse click and mose release
//you press the mouse that is the 1st coordinates
//you release it that is the 2nd coordinates
//pass both to the addRec method
private class MouseHandler extends MouseAdapter
{
#Override
public void mousePressed(MouseEvent event)
{
first = event.getPoint();
}
#Override
public void mouseReleased(MouseEvent event)
{
second = event.getPoint();
addRec(first, second);
}
}
}
It works perfectly. However, going back to the original problem, if I add a button, and then when the button pressed go ahead and begin drawing rectangles it doesn't work.
Here is the modified frame class
package ActionTest;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class MouseFrame extends JFrame
{
private JPanel buttonPanel;
public MouseFrame()
{
JFrame frame = this;
buttonPanel = new JPanel();
JButton rec = new JButton("Rectangle");
rec.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event)
{
System.out.println("pressed");
frame.add(new MouseComponent());
}});
buttonPanel.add(rec);
add(buttonPanel);
}
}
Thanks in advance.
frame.add(new MouseComponent());
The size of a newly created component is (0, 0) so there is nothing to paint. So you need to invoke the layout manager when you add a component to a visible GUI.
frame.add(new MouseComponent());
frame.revalidate();
frame.repaint();
Note this will only work if the layout manager allows you to add multiple components to the frame. The default layout manager for a frame is the BorderLayout and only a single components can be added to the CENTER of the BorderLayout.
So maybe you need to add the button using:
frame.add(button, BorderLayout.PAGE_START);
Read the section from the Swing tutorial on How to Use Layout Managers for more information and working examples.
Also, any time you do custom painting you need to override the getPreferredSize() method of the custom component so the layout managers can do their job.
Related
I am trying to use the color chooser to select a color to draw with. I can get it to display color selection and draw in black but I'm stuck after that.
package sketch;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
*
* #author Brittany
*/
public class Sketch extends JPanel{
/**
* Keeps track of the last point to draw the next line from.
*/
private Point lastPoint;
/**
* Constructs a panel, registering listeners for the mouse.
*/
public Sketch() {
Color drawColor = Color.BLACK;
// When the mouse button goes down, set the current point
// to the location at which the mouse was pressed.
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
lastPoint = new Point(e.getX(), e.getY());
}
});
// When the mouse is dragged, draw a line from the old point
// to the new point and update the value of lastPoint to hold
// the new current point.
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
Graphics g = getGraphics();
g.setColor(drawColor);
g.drawLine(lastPoint.x, lastPoint.y, e.getX(), e.getY());
lastPoint = new Point(e.getX(), e.getY());
g.dispose();
}
});
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
JFrame frame = new JFrame("Simple Sketching Program");
JButton colorBtn = new JButton("Color");
colorBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
Color newColor = JColorChooser.showDialog(frame,"Choose Color",Color.BLACK);
if(newColor != null){
}
}
});
frame.getContentPane().add(new Sketch(), BorderLayout.CENTER);
frame.getContentPane().add(colorBtn, BorderLayout.NORTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setVisible(true);
}
}
Graphics g = getGraphics(); is NOT how custom painting works. getGraphics can return null and is nothing more than a snapshot of the previous paint pass, which will be replaced on the next paint pass.
Start by taking a look at Performing Custom Painting and Painting in AWT and Swing for more details about how painting works and how you should with it.
You then have two choices. You can either use a BufferedImage as your primary drawing surface, and then paint that to the component, or you can keep track of what's been painted (and in what color) and reproduce it each time a paint cycle occurs. Both have pros and cons and which you would use will depend on you needs.
To answer your question. You need some way to pass the new color to an instance of Sketch.
I'd start by creating a setter in Sketch which can be used to other classes to change the color...
public Sketch() {
private Color drawColor = Color.BLACK;
public void setDrawColor(Color color) {
if (color == null) {
drawColor = Color.BLACK;
} else {
drawColor = colorl
}
}
Then you would use this method to pass the new color to it...
public static void main(String[] args) {
JFrame frame = new JFrame("Simple Sketching Program");
JButton colorBtn = new JButton("Color");
Sketch sketch = new Sketch();
colorBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
Color newColor = JColorChooser.showDialog(frame,"Choose Color",Color.BLACK);
if(newColor != null){
sketch.setDrawColor(newColor);
}
}
});
frame.getContentPane().add(new Sketch(), BorderLayout.CENTER);
I'm trying to make a program that can pretty much draw rectangles, shapes on the screen. So far I've made a GUI that has a menu bar and toolbar with some buttons (which aren't functioning yet).
Now I'm stuck with this problem that my rectangles aren't showing up on my drawing panel and I'm thinking it's due to JPanels who overlap on each other that my DrawRectangle class. But I'm not sure.
This is my DrawRectangle class where I wan't to draw rectangles and then put them in to my DrawingPanel (if that's possible).
package Shapes;
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawRectangle extends JPanel
{
private static final long serialVersionUID = 1L;
public int old_x;
public int old_y;
public int new_x;
public int new_y;
public DrawRectangle(int old_x, int old_y, int new_x, int new_y)
{
this.old_x = old_x;
this.old_y = old_y;
this.new_x = new_x;
this.new_y = new_y;
repaint();
}
public void paintComponent(Graphics g)
{
g.drawRect(old_x, old_y, new_x, new_y);
}
}
This is my DrawingPanel class where I would like to store all the painted graphics from my DrawRectangle class
package Panel;
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import Shapes.DrawRectangle;
public class DrawingPanel
{
private JPanel drawPanel;
private int tool = 1;
int currentX, currentY, oldX, oldY;
public DrawingPanel()
{
drawPanel = new JPanel();
drawPanel.setBackground(Color.WHITE);
drawPanel.setBorder(BorderFactory.createLineBorder(Color.black));
// Testing, neither of them are showing up (trying without mouse)
new DrawRectangle(100,100,100,100);
new DrawRectangle(200,200,300,100);
drawPanel.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent evt){
drawPanelMousePressed(evt);
}
public void mouseReleased(MouseEvent evt){
drawPanelMouseReleased(evt);
}
});
drawPanel.addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent evt){
drawPanelMouseDragged(evt);
}
});
}
public JPanel getDrawPanel()
{
return drawPanel;
}
private void drawPanelMouseDragged(MouseEvent evt) {
if (tool == 1) {
currentX = evt.getX();
currentY = evt.getY();
oldX = currentX;
oldY = currentY;
System.out.println(currentX + " " + currentY);
System.out.println("PEN!!!!");
}
}
private void drawPanelMousePressed(MouseEvent evt) {
oldX = evt.getX();
oldY = evt.getY();
System.out.println(oldX + " " + oldY);
}
private void drawPanelMouseReleased(MouseEvent evt) {
currentX = evt.getX();
currentY = evt.getY();
}
}
Also I'm considering my JPanel container that might be responsible for my DrawingPanel content not showing up. Here's my ContainerPanel class
package Panel;
import java.awt.BorderLayout;
import javax.swing.JPanel;
public class ContainerPanel
{
private JPanel containerPanel;
public ContainerPanel()
{
containerPanel = new JPanel(new BorderLayout());
containerPanel.setOpaque(true);
containerPanel.add(new DrawingPanel().getDrawPanel(), BorderLayout.CENTER);
containerPanel.add(new ToolBarPanel().getToolBarPanel(), BorderLayout.NORTH);
}
public JPanel getContainerPanel()
{
return containerPanel;
}
}
First time in stackoverflow :)
drawPanel = new JPanel();
When you create a panel, you assign it to a variable so you can use the variable in the getDrawPanel() method.
new DrawRectangle(100,100,100,100);
Here you create a DrawRectangle but you don't do anything with it. You don't add it to the drawPanel or anything so it will never get painted.
and I'm thinking it's due to JPanels who overlap on each other that my DrawRectangle class.
Even if you fix the above problem and add your DrawRectangle class to the DrawPanel you will still have problems:
A JPanel is opaque so the last painted panel will cover the bottom panel.
Your DrawRectangle panel doesn't have a preferredSize since you didn't override the getPreferredSize() method so the size will be 0 so there is nothing to paint
A JPanel uses a FlowLayout so each component will be positioned on the panel based on the rules of the layout manager, so your Rectangle will not paint at the location you think it should be.
You need to start by reading the Swing Tutorial for Swing basics. Maybe section on:
Custom Painting - will show you how to properly override the paintCompnent() method and implement a getPreferredSize() method
Doing Without a Layout Manager - because you will want to place the components at a specific location (ie. the x/y of the Rectangle).
Having said all that an easier solution to do custom painting of all the Rectangle on a single panel. Check out Custom Painting Approaches. It has working examples to demonstrate the two common ways to do this:
Add object you want to paint to a List and then the painting method will iterate through the List to paint each object.
Paint directly to a BufferedImage and then just paint the BufferedImage either by using a JLabel of by custom painting.
I'm creating a sort of paint application. The user can move a circle in a JPanel by pressing/dragging the mouse.
I have a JCheckBoxMenuItem in one of my JMenus:
JCheckBoxMenuItem checkitem = new JCheckBoxMenuItem("Draw mode",false);
When it is not activated, the circle can only be moved (by dragging/pressing) and the previous circle will be erased.
When it is activated, the circle can only be moved, but the previous circle will not be erased when dragging/pressing the mouse ( This works the same way as a paint program )
Shortened version of my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class GUI extends JFrame implements MouseListener, MouseMotionListener, ActionListener, ItemListener
{
JPanel mainPan, colorPan;
Color color = Color.BLACK;
JCheckBoxMenuItem checkitem;
boolean clear = true;
public GUI(String header)
{
maker();
mainPan.addMouseListener(this);
mainPan.addMouseMotionListener(this);
add(mainPan , BorderLayout.CENTER);
add(colorPan, BorderLayout.PAGE_END);
}
public void maker()
{
colorPan = new JPanel();
colorPan.setLayout(new GridLayout(1, 0));
mainPan = new JPanel(){
#Override
public void paintComponent(Graphics g)
{
//g.setColor(Color.WHITE);
//g.fillRect(0,0,getWidth(),getHeight());
if(clear)
super.paintComponent(g); //Do the same thing as above(Clear JPanel)
g.setColor(color);
g.fillOval(x,y,50,50); //x and y are integer variables that I use in my full program
}
};
checkitem = new JCheckBoxMenuItem("Draw mode",false);
//After adding this to a JMenu,
checkitem.addItemListener(this);
}
public void itemStateChanged(ItemEvent e)
{
if(e.getStateChange() == ItemEvent.SELECTED)
{
clear = false;
}
else
{
clear = true;
}
}
}
The below screenshot shows the output of my full program:
colorPan is the JPanel full of JButtons of different colors. The top of it is mainPan.
Right now, the "Draw mode" doesn't work as expected. I had always thought that super.paintComponent(g); was the one that clears/resets the screen when repaint() is called. But I removed that and was quite surprised to see the program behave the same way.
Basically, my problem is here:
if(clear)
super.paintComponent(g);
I need to prevent everything from being cleared when repaint() is called. How do I achieve what I want?
It is not in this code where changes should be made. And it is not paint method which should be changed. Paint paints whenever is required either by your or by system. When window is resized or moved or partially covered - it uses paint to paint picture again.
What you should really do is to stop updating coordinates for your painted oval. It could be done in mouse listener or in coordinates setter or, better, in control part which manages these coordinates. Your checkbox should control ability to change your model. It should not control painting.
There is commonly used pattern Model-View-Controller - look at it. Maybe it could look like overkill for such small application but even Swing itself is built on this pattern so you already follow it. Issues rise when you try to break it. So - don't.
You can't "prevent the JPanel from being updated;" paintComponent() will be called asynchronously, as required by the system. Instead, condition attributes of your view class in a way that allows your implementation of paintComponent() to render everything whenever it is called.
In the example below, the foreground color is changed with each mouse click and paintComponent() uses the revised setting. In the more elaborate example cited here, ClearAction clears the List<Node> and List<Edge> that define the graph's model. Absent a call to super.paintComponent(g), otherwise required for an opaque component, a call to fillRect() in paintComponent() cleans up any leftover selection artifacts.
public void actionPerformed(ActionEvent e) {
nodes.clear();
edges.clear();
repaint();
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
/** #see https://stackoverflow.com/a/5312702/230513 */
public class MouseDragTest extends JPanel {
private static final String TITLE = "Drag me!";
private static final Random r = new Random();
private static final int W = 640;
private static final int H = 480;
private Point textPt = new Point(W / 2, H / 2);
private Point mousePt;
private Color color = Color.black;
public MouseDragTest() {
this.setFont(new Font("Serif", Font.ITALIC + Font.BOLD, 32));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mousePt = e.getPoint();
setColor(Color.getHSBColor(r.nextFloat(), 1, 1));
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
int dx = e.getX() - mousePt.x;
int dy = e.getY() - mousePt.y;
textPt.setLocation(textPt.x + dx, textPt.y + dy);
mousePt = e.getPoint();
repaint();
}
});
}
public void setColor(Color color) {
this.color = color;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(W, H);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
int w2 = g.getFontMetrics().stringWidth(TITLE) / 2;
g.drawString(TITLE, textPt.x - w2, textPt.y);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame(TITLE);
f.add(new MouseDragTest());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
I have two separate class and driver files, and in the class file I create the paint method:
public void paint(Graphics g){
g.drawLine(......
....
//along with all of my other draw commands
}
Further down in the code, I create a JButton and within this button's action listener I don't know how to use a Graphics object to create more graphics in the JFrame. Should I be adding something to my driver to make this happen, or is there a way to use these graphics within my action listener? Thank you, and any help is appreciated.
You need to draw everything within the paint method. The actionPerformed should only change the state of something already in the paint method, and then call repaint. For example
boolean drawHello = true;
boolean drawWorld = false;
protected void paintComponent(Graphics g) {
super.paintCompoent(g);
if (drawHello)
g.drawString("Hello", 50, 50);
if (drawWorld)
g.drawString("World", 10, 10);
}
Then in your actionPerformed, you can change the state of drawWorld to true and call repaint().
public void actionPerformed(ActionEvent e) {
drawWorld = true;
repaint();
}
So as you can see, everything should be drawn in the paintComponent method. You can just hide and paint renderings, and make them "visible" from a action command. You should already have predefined what could posibly be drawn. Then just change the state of it rendering
And as #MadPrgrammer pointed out, you should not be painting on top-level containers like JFrame. Instead paint on a custom JPanel or JComponent and override the paintComponent method, instead of JFrame and paint
Here's an example where I draw a new square every time the button is pressed. If look at the code, you will see that in the paintComponent method, I loop through a list of Squares and draw them, and in the actionPerformed all I do is add a new Square to the List and call repaint()
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class AddSquares {
private int R = 0;
private int G = 0;
private int B = 0;
private int xLoc = 0;
private int yLoc = 0;
List<Square> squares = new ArrayList<>();
private JButton addSquare = new JButton("Add Square");
private RectsPanel panel = new RectsPanel();
public AddSquares() {
addSquare.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
Color color = new Color(R, G, B);
squares.add(new Square(xLoc, yLoc, color));
panel.repaint();
R += 10;
G += 20;
B += 30;
xLoc += 20;
yLoc += 20;
}
});
JFrame frame = new JFrame("Draw Squares");
frame.add(panel, BorderLayout.CENTER);
frame.add(addSquare, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private class RectsPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Square square : squares) {
square.drawSquare(g);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(250, 250);
}
}
private class Square {
int x = 0;
int y = 0;
Color color;
public Square(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
public void drawSquare(Graphics g) {
g.setColor(color);
g.fillRect(x, y, 75 ,75);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
AddSquares addSquares = new AddSquares();
}
});
}
}
It's difficult to be 100%, but it would seem as you don't understand how custom painting is performed in Swing.
Start by taking a look at Performing Custom Painting and Painting in AWT and Swing.
Essentially, painting is arranged by the Repaint Manager, which decides what and when something should be painted. It then calls (through a chain of methods) the paint method of the components it thinks need to be updated, passing it a reference to a Graphics context that should be used to actually paint on.
Basically, when ever your paint method is called, you should create paint the current state of your painting.
You should avoid overriding paint and instead use paintComponent from classes the extend JComponent
Your question is a little on the vague side as to what you are actually wondering about but generally speaking:
We don't override paint in Swing, we override paintComponent.
If you are already aware of this, you may be overriding paint because you are doing it on a JFrame and you found that JFrame does not have a paintComponent method. You shouldn't override paint on a JFrame. Instead, create a JPanel or something to put inside the frame and override paintComponent on the panel.
Question about the ActionListener.
It sounds like you are wanting to do painting outside of paintComponent in which case probably the best way is to do painting to a separate Image. Then you paint the Image on to the panel in paintComponent. You can also put an Image in a JLabel as an ImageIcon. Here is a very simple drawing program using MouseListener that demonstrates this (taken from here):
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
class PaintAnyTime {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new PaintAnyTime();
}
});
}
final BufferedImage image = (
new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB)
);
final JFrame frame = new JFrame();
final JLabel label = new JLabel(new ImageIcon(image));
final MouseAdapter drawer = new MouseAdapter() {
Graphics2D g2D;
#Override
public void mousePressed(MouseEvent me) {
g2D = image.createGraphics();
g2D.setColor(Color.BLACK);
}
#Override
public void mouseDragged(MouseEvent me) {
g2D.fillRect(me.getX(), me.getY(), 3, 3);
label.repaint();
}
#Override
public void mouseReleased(MouseEvent me) {
g2D.dispose();
g2D = null;
}
};
PaintAnyTime() {
label.setPreferredSize(
new Dimension(image.getWidth(), image.getHeight())
);
label.addMouseListener(drawer);
label.addMouseMotionListener(drawer);
frame.add(label);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
#MadProgrammer has already linked to the articles that I was going to link to.
I am trying to write a program in Java Swing that outputs a 10 x 10 grid of geometric rectangles filled with randoms colors. However, when the user clicks on one of the rectangles within the display window the rectangle should repaint() and change to another color.
Thus far I have the rudimentary program running, but I can't figure out how to implement a mouseListener to it in order to have the rectangles' color change when a user clicks inside. At this point, the rectangles only repaint when the display window is expanded and minimized. Any advice/help would be greatly appreciated! Thanks!
Here is what I have so far...
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.*;
public class ColorGrid extends JPanel {
int w, x, y, z;
Color c = new Color((int)(Math.random() * 0xFFFFFF));
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
setLayout(new GridLayout(10,10));
int w = x = y = z = 0;
for(int i=0;i<100;i++){
Color c = new Color((int)(Math.random() * 0xFFFFFF));
w+=10;
x+=10;
y+=50;
z+=15;
g2.drawRect(w+10,x+30,y,z);
g2.drawRect(w+10,x+30,y,z);
g2.fillRect(w+10,x+30,y,z);
g2.setPaint(c);
}
}
public static void main(String[] args) {
JFrame f= new JFrame();
f.setTitle("ColorGrid Display Window");
f.setSize(200,200);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Container contentPane = f.getContentPane();
contentPane.add(new ColorGrid());
f.show();
}
}
Any Component can have a MouseListener. JLabel is nice for a colored rectangle, as long as you make it opaque.
Addendum: Having recommended MouseAdapter elsewhere, I should mention that one instance is enough.
Addendum: This update adds the mouse listener in the ColorLabel constructor.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
/** #see http://stackoverflow.com/questions/5136859 */
public class ColorLabel extends JLabel {
private static final int N = 10;
private static final Random random = new Random();
private static final MouseAdapter listener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
ColorLabel label = (ColorLabel) e.getSource();
label.setBackground(new Color(random.nextInt()));
}
};
public ColorLabel() {
this.setOpaque(true);
this.setBackground(new Color(random.nextInt()));
this.setPreferredSize(new Dimension(32, 32));
this.addMouseListener(listener);
}
private void displayGrid() {
JFrame f = new JFrame("ColorGrid");
f.setLayout(new GridLayout(N, N));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
for (int i = 0; i < N * N; i++) {
final ColorLabel label = new ColorLabel();
f.add(label);
}
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ColorLabel().displayGrid();
}
});
}
}
Instead of having a JPanel that you draw your grid of colors on, how about you have a grid of buttons. You override the drawing mechanism for the button so that it just renders as it's current color. Then you have functionality built in to listen for clicks to occur in a specific section of your grid.
This is what I came up with.
Note: I'm still studying Java in University, so this might not be the exact way to do this but it worked when I did it.
public class ColorGrid extends JPanel implements MouseListener {
this.addMouseListener(this);
addMouseListener(this);
That's the first part, the second part is to have these methods in your code.
public void mouseClicked(MouseEvent arg0) {
}
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
public void mousePressed(MouseEvent arg0) {
}
public void mouseReleased(MouseEvent arg0) {
}
Then, depending on what you want, (i.e. Mouse clicked or pressed), just type in:
repaint();
Hope this helped.
Assuming you have a 2d array of colors, you can simply use the x and y the mouselistener gives you when you click to calculate the indices of that rectangle. Just divide the x and y by the size of the rectangle using integer division. After changing the color use repaint() to show it.