I would like to do this without the use of the JComponent. The idea is to have multiple buttons for each a shape, by clicking a button, I can then draw the shape for that button. Unfortunately, I can't even draw the shapes right now.
public static void main(String[] args) {
JFrame frame = new JFrame();
JButton rect = new JButton("Rectangle");
ActionListener rListener = new RectangleNode();
rect.addActionListener(rListener);
MouseListener rMListener = new RectangleNode();
rect.addMouseListener(rMListener);
MouseMotionListener rMMListener = new RectangleNode();
rect.addMouseMotionListener(rMMListener);
JButton ellipse = new JButton("Ellipse");
JPanel panel = new JPanel();
panel.add(rect);
panel.add(ellipse);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 600);
frame.setTitle("Graph Draw");
frame.setVisible(true);
}
The RectangleNode class
public class RectangleNode implements ActionListener,MouseListener,MouseMotionListener {
private Point p1;
private Rectangle r;
private boolean rdraw;
#Override
public void actionPerformed(ActionEvent e) {
rdraw = true;
}
#Override
public void mousePressed(MouseEvent e) {
if(rdraw = true){
p1 = e.getPoint();
r = new Rectangle(p1.x, p1.y, p1.x - p1.x, p1.y - p1.y);
}
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseDragged(MouseEvent e) {
if(rdraw = true){
int x = Math.min(p1.x, e.getX());
int y = Math.min(p1.y, e.getY());
int width = Math.abs(p1.x - e.getX());
int height = Math.abs(p1.y - e.getY());
r.setBounds(x, y, width, height);
repaint();
}
}
#Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.draw(r); ;
}
}
I'm not sure how to use repaint, and the paintComponent method in this situation.
Check out Custom Painting Approaches for an example of how to dynamically draw Rectangles.
In your case you want the ability to draw a Rectangle or an Ellipse so you would need to make some changes:
The Java API supports a Shape class. A Shape can be a Rectangle, Ellipse, Polygon etc. So you would need to change the "ColoredRectangle" class to a "ColoredShape" class. This would allow you to store a Rectangle or an Ellipse.
Then in the paintComponent() code you would need to change the drawRect(..) method to be a draw( Shape ) so you can draw both Rectangles and Ellipses.
In the mouseDragged() logic you would need to modify the logic to check if you want to draw a Rectangle or an Ellispse. Then you would create the proper Shape and again use the draw( Shape ) method instead of the drawRect(...) method.
Then you would need to add a property to the class to control which Shape you want to paint. Then when you click the button you set the property. Or maybe instead of using a button you set up radio buttons for each Shape.
Anyway, play with the original code to understand how it works. That is start by converting the code to use the ColoredShape class just for Rectangles. Then once that works you can add the support for the Ellipse.
Related
I need to make a program that will draw multiple circles/squares, and when they are clicked, the colours change to another random colour. I am unsure how to do this. At the moment I have one circle on a JPanel which has a mouse listener to repaint when the panel is clicked within the bounds of the circle (although this creates a rectangular area to click in, not circular) and I need to extend this to add more shapes that have their own area to be clicked. Any help appreciated. Thanks.
public class CircleGUI extends JFrame {
int ovalWidth = 100;
int ovalHeight = 100;
int ovalX = 100;
int ovalY = 100;
public CircleGUI() {
super("Circle GUI");
this.setSize(500, 500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
go();
this.setVisible(true);
}
public void go() {
CPanel panel = new CPanel();
Container container = getContentPane();
container.add(panel);
panel.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
int radius = ovalWidth / 2;
int centerX = ovalX + radius;
int centerY = ovalY + radius;
if (((e.getX() >= centerX - radius && e.getX() <= centerX + radius) && e.getX() >= centerX - radius
&& e.getX() <= centerX + radius)) {
repaint();
}
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
});
}
public class CPanel extends JPanel {
public void paint(Graphics g) {
// random colour
g.setColor(new Color(Math.round(Math.random()), Math.round(Math.random()), Math.round(Math.random())));
g.fillOval(ovalX, ovalY, ovalWidth, ovalHeight);
}
}
}
I need to extend this to add more shapes that have their own area to be clicked
You need to keep a List of Objects that you want to paint. That object would contain information like shape and color.
In your paintComponent() method you iterate through the List and paint each shape.
You then add a MouseListener to your panel. When the mouse is clicked you then iterate through the List to find a shape that contains the point that was generated and you update the color of that object and then repaint the panel.
Check out the Draw On Component example from Custom Painting Approaches for an example of this approach. The example only paints Rectangles but should get you started.
I am trying to create some kind of Paint program. I created a BufferedImage and an Graphics2D but i cant draw on it. All what I can see is the BufferedImage itself without any changes.
public class paintapp implements ActionListener, MouseListener, MouseMotionListener
{
public static final int WIDTHBUFF=300;
public static final int HEIGHTBUFF=300;
BufferedImage buffimage=new BufferedImage(WIDTHBUFF,HEIGHTBUFF,BufferedImage.TYPE_INT_BGR);
JLabel imagelabel=new JLabel(new ImageIcon(buffimage));
int s=3;
Color curr_color=Color.BLACK;
int x,y;
public static final int WIDTH=700;
public static final int HEIGHT=700;
public paintapp()
{
Graphics2D g2d=buffimage.createGraphics();
g2d.setBackground(Color.WHITE);
g2d.fillRect(0, 0, WIDTHBUFF,HEIGHTBUFF);
JFrame frame=new JFrame("Painter");
frame.setSize(WIDTH, HEIGHT);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.setVisible(true);
Panel buttonpanel=new Panel();
Panel colors=new Panel();
Panel draw=new Panel();
draw.add(imagelabel);
frame.add(draw);
frame.pack();
}
public static void main(String[]args)
{
paintapp paint1=new paintapp();
}
#Override
public void mouseDragged(MouseEvent e) {
Graphics2D g2=buffimage.createGraphics();
g2.setColor(curr_color);
g2.setStroke(new BasicStroke(s));
g2.drawLine(x, y, e.getX(), e.getY());
x=e.getX();
y=e.getY();
}
#Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent e) {
x=e.getX();
y=e.getY();
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
I see you are poking through and you got things in jumbled up order. If you read the guides you will see how things go.
The first main thing is to add a MouseMotionListener to the drawing thing - be that JLabel JPanel whatever.
The second thing is that once you go outside of the constructor the JFrame is lost (unless you do some fancy things) and cant be accessed to be refreshed, so the system decides when to refresh and you will see - after you add the mouse listener - that your drawing will appear once you hide and show again the drawing window.
So you need to have JFrame as global - why dont you have you class extend JFrame and so no need to have some extra JFrame.
private class Board extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w=getWidth();
int h=getHeight();
Graphics2D g2d = (Graphics2D) g;
The following code draws the grid:
g2d.setPaint(Color.WHITE);
g2d.fill(new Rectangle2D.Double(0, 0, w, h));
g2d.setPaint(Color.BLACK);
g2d.setStroke(new BasicStroke(4));
g2d.draw(new Line2D.Double(0, h/3, w, h/3));
g2d.draw(new Line2D.Double(0, h*2/3, w, h*2/3));
g2d.draw(new Line2D.Double(w/3, 0, w/3, h));
g2d.draw(new Line2D.Double(w*2/3, 0, w*2/3, h));
The following code draws circles and xs by visiting elements in the array List:
for(Shape shape : shapes){
g2d.setPaint(Color.BLUE);
g2d.draw(shape);
}
}
}
public void addMouseListener(MouseListener ml){
// HOW CAN I ADD A MOUSE LISTENER HERE?
}
You can create a class that implements the MouseListener interface as so:
public class CustomMouseListener implements MouseListener{
public void mouseClicked(MouseEvent e) {
statusLabel.setText("Mouse Clicked: ("+e.getX()+", "+e.getY() +")");
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
}
You want define each of those methods based on the action the method represents (which are self explanatory). The MouseEvent object will have all the info you need related to the mouse (ex. x and y position of mouse).
Now you want to add this new MouseListener to a JPanel (which in this case is your Board class):
//JPanel panel = new JPanel();
Board panel = new Board();
panel.addMouseListener(new CustomMouseListener());
Source
Create your class which implements MouseListener, and pass it by addMouseListener method... ?
http://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html
you need to make the class implements MouseListener.
you need to add the unimplements methods.
and here you go :)
you got few new methods:
public void mouseClicked(MouseEvent e) // method calls when mouse clicked
public void mousePressed(MouseEvent e) // method calls when mouse pressed
public void mouseReleased(MouseEvent e) // method calls when mouse relesed
public void mouseEntered(MouseEvent e) // method calls when the mouse curser getting into the component's geometry
public void mouseExited(MouseEvent e) // method calls when mouse curser getting out of the component's geometry
hope it helped you :)
Basically I have an image loaded, and when I click a portion of the image, a rectangle (with no fill) shows up. If I click another part of the image again, that rectangle will show up once more. With each click, the same rectangle should appear.
So far I have this code, now I don't know how to make the image appear. My image from my file directory. I have already made the code to get the image from my file directory.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class MP2 extends JPanel implements MouseListener{
JFrame frame;
JPanel panel;
int x = 0;
int y = 0;
String input;
public MP2(){
}
public static void main(String[] args){
JFrame frame = new JFrame();
MP2 panel = new MP2();
panel.addMouseListener(panel);
frame.add(panel);
frame.setSize(200,200);
frame.setVisible(true);
}
public void mouseClicked(MouseEvent event) {
// TODO Auto-generated method stub
this.x = event.getX();
this.y = event.getY();
this.repaint();
input = JOptionPane.showInputDialog("Something pops out");
System.out.println(input);
}
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void paintComponent(Graphics g){
super.paintComponent(g);
// this.setBackground(Color.white); *Sets the bg color of the panel
g.setColor(new Color(255,0,0));
g.drawRect(x, y, 100, 100);
}
}
You may want to look at drawing the rectangle on The Glass Pane, as shown in GlassPaneDemo. For example, in paintComponent(), replace g.fillOval() with g.drawRect().
I don't know how to make the image appear.
This example shows how to display an image in a JLabel.
this.x and this.y refer to the x and y of your JPanel, not the rectangle you want to draw. You'll need to create two additional fields, rectX and rectY. These get set in mouseClicked and used by paintComponent().
EDIT
I'm sorry, my bad. I'm now confused. You do declare an x and y. These should still be renamed cause they can be confused with the x and y defined in Component, but they are not the problem. When I run your code and click, the red rectangle appears (along with a dialog). So I'm not sure what is the problem???
package test;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class test_bmp extends JPanel implements MouseListener,MouseMotionListener,ActionListener
{
static BufferedImage image;
Color color;
Point start=new Point();
Point end =new Point();
JButton elipse=new JButton("Elipse");
JButton rectangle=new JButton("Rectangle");
JButton line=new JButton("Line");
String selected;
public test_bmp()
{
color = Color.black;
setBorder(BorderFactory.createLineBorder(Color.black));
addMouseListener(this);
addMouseMotionListener(this);
}
public void paintComponent(Graphics g)
{
//super.paintComponent(g);
g.drawImage(image, 0, 0, this);
Graphics2D g2 = (Graphics2D)g;
g2.setPaint(Color.black);
if(selected=="elipse")
{
g2.drawOval(start.x, start.y, (end.x-start.x),(end.y-start.y));
System.out.println("Start : "+start.x+","+start.y);
System.out.println("End : "+end.x+","+end.y);
}
if(selected=="line")
g2.drawLine(start.x,start.y,end.x,end.y);
}
//Draw on Buffered image
public void draw()
{
Graphics2D g2 = image.createGraphics();
g2.setPaint(color);
System.out.println("draw");
if(selected=="line")
g2.drawLine(start.x, start.y, end.x, end.y);
if(selected=="elipse")
{
g2.drawOval(start.x, start.y, (end.x-start.x),(end.y-start.y));
System.out.println("Start : "+start.x+","+start.y);
System.out.println("End : "+end.x+","+end.y);
}
repaint();
g2.dispose();
}
public JPanel addButtons()
{
JPanel buttonpanel=new JPanel();
buttonpanel.setBackground(color.lightGray);
buttonpanel.setLayout(new BoxLayout(buttonpanel,BoxLayout.Y_AXIS));
elipse.addActionListener(this);
rectangle.addActionListener(this);
line.addActionListener(this);
buttonpanel.add(elipse);
buttonpanel.add(Box.createRigidArea(new Dimension(15,15)));
buttonpanel.add(rectangle);
buttonpanel.add(Box.createRigidArea(new Dimension(15,15)));
buttonpanel.add(line);
return buttonpanel;
}
public static void main(String args[])
{
test_bmp application=new test_bmp();
//Main window
JFrame frame=new JFrame("Whiteboard");
frame.setLayout(new BorderLayout());
frame.add(application.addButtons(),BorderLayout.WEST);
frame.add(application);
//size of the window
frame.setSize(600,400);
frame.setLocation(0,0);
frame.setVisible(true);
int w = frame.getWidth();
int h = frame.getHeight();
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
g2.setPaint(Color.white);
g2.fillRect(0,0,w,h);
g2.dispose();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent event)
{
start = event.getPoint();
}
#Override
public void mouseReleased(MouseEvent event)
{
end = event.getPoint();
draw();
}
#Override
public void mouseDragged(MouseEvent e)
{
end=e.getPoint();
repaint();
}
#Override
public void mouseMoved(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==elipse)
selected="elipse";
if(e.getSource()==line)
selected="line";
draw();
}
}
I need to create a paint application. When I draw ellipse by dragging mouse from left to right it displays nothing. Why? Should I use any other function here?
Your program does draw an ellipse when you drag the mouse down and to the right. It's dragging up and/or left that does not work, because Graphics.drawOval does not work with a negative width or height.
Try adding a method like this:
private Shape createEllipse() {
Ellipse2D e = new Ellipse2D.Double();
e.setFrameFromDiagonal(start, end);
return e;
}
Then call it from draw and paintComponent like this:
if(selected=="elipse") {
g2.draw(createEllipse());
}
Also you probably do not need the call to draw() at the end of actionPerformed. If you switch between line and ellipse mode it will draw an ellipse with the same coordinates as the most recent line or vice-versa.
And one coding style issue: Using string literals for selected is confusing (although it does work.) I would define an enum instead.