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);
Related
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.
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);
}
});
}
}
This is a really general question, but how should I add an animated background for a JPanel. I want the background to be behind all the panel's components and graphics. Right now, I have two separate classes (one for the main panel and the other for the background). The background class uses repaint() to animate a grid moving across the screen. I've tried to make the main panel background transparent, but that hasn't gotten me anywhere.
Even more info:
My main panel is part of a CardLayout and it has many different classes in it. So when I'm adding my main panel to my main frame, I'm doing frame.getContentPane().add(cards, BorderLayout.CENTER)
cards is a JPanel which acts as a container for the mainpanel and all the panels inside main panel.
Can anybody help me out in getting a panel animated background?
You can use Toolkit.getImage() to load animated image and then draw the image in container's paintComponent. Make sure the ImageObserver is set (not null) in order to update animation frames properly. For details how image is loaded, observed and updated see How Images are Loaded appendix in Java AWT Reference.
Here is a simple example:
import java.awt.*;
import javax.swing.*;
import java.net.URL;
class AnimatedPanelDemo {
static class ImagePanel extends JPanel {
private Image image;
ImagePanel(Image image) {
this.image = image;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image,0,0,getWidth(),getHeight(),this);
}
}
private static void createAndShowUI() {
try {
JFrame frame = new JFrame("Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
Image image = Toolkit.getDefaultToolkit().getImage(new URL(
"http://duke.kenai.com/iconSized/duke.running.gif"));
ImagePanel imagePanel = new ImagePanel(image);
imagePanel.add(new JLabel("Some label"));
frame.add(imagePanel);
frame.setSize(100, 100);
frame.setVisible(true);
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
Well, this is my first answer on stackoverflow.
Will try to help with my learning curve with this complex AWT and Swift API.
Below there's the contructor that extends JFrame
package xpto;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowStateListener;
import java.awt.image.ImageObserver;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import sun.java2d.SunGraphicsEnvironment;
import java.awt.Graphics;
import java.awt.Graphics2D;
public class FrameLuckyRaffle extends JFrame {
/**
*
*/
private JLabel backgroundLabel;
private ImageIcon imageIcon;
private Image bgImage;
/**
* Constructor of this frame.
*/
public FrameLuckyRaffle(String background, final String dbname) {
try {
setTitle("Lucky Raffle of "+ dbname);
GraphicsConfiguration config = this.getGraphicsConfiguration();
Rectangle usableBounds = SunGraphicsEnvironment.
getUsableBounds(config.getDevice());
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setBounds(100, 100, (int)(usableBounds.getWidth()*0.8),
(int)(usableBounds.getHeight()*0.8));
setMinimumSize(new Dimension(1024, 700));
setResizable(true);
setDefaultLookAndFeelDecorated(true);
backgroundLabel = new JLabel() {
public void paintComponent(Graphics g) {
// alternative --> g.drawImage(bgImage, 0, 0, null);
// I prefer to control the new ImageObserver parameter as bellow
g.drawImage(bgImage, 0, 0, new ImageObserver() {
#Override
public boolean imageUpdate(Image img, int infoflags,
int x, int y, int width, int height) {
img.getScaledInstance(getWidth(),getHeight(),
Image.SCALE_FAST);
return true;
}
});
// this is used to have easier control on
// image manipulation on my application
Graphics2D g2d = (Graphics2D)g;
super.paintComponent(g2d);
revalidate();
repaint();
}
};
backgroundLabel.setBounds(0, 0, 0, 0);
// this is necessary if you want more child
// components to be visible on the JFrame afterwards
backgroundLabel.setOpaque(false);
setContentPane(backgroundLabel);
addWindowListener(new WindowListener() {
#Override
public void windowOpened(WindowEvent e) {
// Set Frame Background
imageIcon = new ImageIcon(Toolkit.getDefaultToolkit().
createImage(FrameBusinessPure.class.getResource(background)));
bgImage = imageIcon.getImage().
getScaledInstance(getWidth(),getHeight(), Image.SCALE_FAST);
}
// Even after closing the window, JVM didn't Garbage Collected the instanced
// objects, for some reason. Forcing the objects to null helped on that.
#Override
public void windowClosed(WindowEvent e) {
backgroundLabel = null;
imageIcon = null;
bgImage = null;
System.gc();
}
});
addWindowStateListener(new WindowStateListener() {
#Override
public void windowStateChanged(WindowEvent e) {
// if you flush the object on runtime you will surpass the
// memory leak on using GIFs and most complex graphics
bgImage.flush();
bgImage = imageIcon.getImage().
getScaledInstance(getWidth(),getHeight(), Image.SCALE_FAST);
}
});
addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent e) {
// if you flush the object on runtime you will surpass the
// memory leak on using GIFs and most complex graphics
bgImage.flush();
bgImage = imageIcon.getImage().
getScaledInstance(getWidth(),getHeight(), Image.SCALE_FAST);
});
}catch (Exception e) {
e.printStackTrace();
}
}
}
Feel free to learn more on below link
https://www.oracle.com/java/technologies/painting.html
I want to draw the lines between 2 JScrollPanes (first scroll pane on the left side, second on the right). These JScrollPanes contain images. I want to draw lines between these 2 images (use some layers, use some trick etc.). I tried do it different ways, but i failed. Is it possible? (if not, i will have to make 2 images in one JScrollPane and it won't be nice).
EDIT
I want to draw between 2 images - throught components - get some points from images and draw lines between them. I apologize for poorly formulated question.
In order to accomplish this, I believe you'll need to make use of the Glass Pane. The Glass Pane sits on top of everything in the JRootPane and fills the entire view. This particular position allows two distinct capabilities:
Intercepting mouse and keyboard events
Drawing over the entire user interface
I believe your question is addressed by the second capability. The following is an example implementation, which you can later tailor to meet your own needs. Note that I've left out a lot of detail with regard to Glass Pane that you'll need to research on your own.
CODE
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GlassPaneDemo {
private static BufferedImage bi;
public static void main(String[] args){
try {
loadImages();
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
createAndShowGUI();
}
});
} catch (IOException e) {
// handle exception
}
}
private static void loadImages() throws IOException{
bi = ImageIO.read(new File("src/resources/person.png"));
}
private static void createAndShowGUI(){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setGlassPane(new CustomGlassPane());
frame.getContentPane().add(getButtonPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.getGlassPane().setVisible(true);
frame.setVisible(true);
}
private static final JPanel getButtonPanel(){
#SuppressWarnings("serial")
final JPanel panel = new JPanel(){
#Override
protected void paintComponent(Graphics g){
Graphics gCopy = g.create();
gCopy.setColor(Color.BLUE.darker());
gCopy.fillRect(0, 0, getWidth(), getHeight());
gCopy.dispose();
}
};
final JLabel labelOne = new JLabel();
labelOne.setIcon(new ImageIcon(bi));
final JLabel labelTwo = new JLabel();
labelTwo.setIcon(new ImageIcon(bi));
panel.add(labelOne);
panel.add(labelTwo);
return panel;
}
#SuppressWarnings("serial")
private static class CustomGlassPane extends JComponent{
private Point p1;
private Point p2;
private boolean lineDrawn;
public CustomGlassPane(){
addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e){
if(p1 == null || lineDrawn){
if(lineDrawn){
p1 = null;
p2 = null;
lineDrawn = false;
}
p1 = e.getPoint();
}else{
p2 = e.getPoint();
repaint(); // not optimal
lineDrawn = true;
}
}
});
// Block all other input events
addMouseMotionListener(new MouseMotionAdapter(){});
addKeyListener(new KeyAdapter(){});
addComponentListener(new ComponentAdapter(){
#Override
public void componentShown(ComponentEvent e){
requestFocusInWindow();
}
});
setFocusTraversalKeysEnabled(false);
}
#Override
protected void paintComponent(Graphics g){
if(p1 != null && p2 != null){
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.RED);
g2.drawLine((int)p1.getX(), (int)p1.getY(), (int)p2.getX(), (int)p2.getY());
g2.dispose();
}
}
}
}
OUTPUT
EXPLANATION
In this example, I clicked two arbitrary points within each JLabel, and then drew a connecting line.
This should be very possible. You will need to create a custom component that is aware of both vertical ScrollBars. It should add itself as an AdjustmentListener to each scroll bar in order to detect changes and repaint the lines between the two.
See:
addAdjustmentListener method in the API
You can use this
http://java-sl.com/connector.html
as an example of such code.
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.