So I'm trying to draw a circle where a user clicks, which can then be re-sized by the bar down below. Everything works except for that the circle won't draw where I want it to. Any suggestions?
Here is my Panel
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import javax.swing.event.*;
public class TestClass extends JFrame {
private JSlider slide;
private MainClass myPanel;
public int x1=0;
public int y1=0;
public TestClass(){
super("The Title");
myPanel = new MainClass();
myPanel.setBackground(Color.YELLOW);
slide = new JSlider(SwingConstants.HORIZONTAL, 0, 200, 10);
slide.setMajorTickSpacing(10);
slide.setPaintTicks(true);
slide.addChangeListener(
new ChangeListener(){
public void stateChanged(ChangeEvent e){
myPanel.checkDiameter(slide.getValue());
}
}
);
HandlerClass handler = new HandlerClass();
slide.addMouseListener(handler);
add(slide, BorderLayout.SOUTH);
add(myPanel, BorderLayout.CENTER);
}
public int setX1(){
return x1;
}
public int setY1(){
return y1;
}
private class HandlerClass implements MouseListener{
#Override
public void mouseClicked(MouseEvent event) {
// TODO Auto-generated method stub
x1=event.getX();
y1=event.getY();
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(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
}
}
}
Here is the other important class which creates a window and call TestClass;
import java.awt.*;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class MainClass extends JPanel{
private int d = 10;
public void paintComponent(Graphics g){
super.paintComponent(g);
TestClass values = new TestClass();
g.setColor(Color.CYAN);
g.fillOval(values.setX1()+50, values.setY1(), d, d);
}
public void checkDiameter(int newD)
{
//New format for if statements
d = (newD >= 0 ? newD //if
: 10//else
);
repaint();
}
public Dimension getPreferredSize(){
return new Dimension(200,200);
}
public Dimension getMinimumSize(){
return getPreferredSize();
}
}
Hey Guys I found a way to get it working.
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import javax.swing.event.*;
public class TestClass extends JFrame {
private JSlider slide;
private MainClass myPanel;
public static int x1=0,y1=0;
public TestClass(){
super("The Title");
myPanel = new Panel();
myPanel.setBackground(Color.YELLOW);
//Allows you to re-size the drawn circle
slide = new JSlider(SwingConstants.HORIZONTAL, 0, 200, 10);
slide.setMajorTickSpacing(10);
slide.setPaintTicks(true);
slide.addChangeListener(
new ChangeListener(){
public void stateChanged(ChangeEvent e){
myPanel.checkDiameter(slide.getValue());
}
}
);
//Create a way to handle user mouse events
HandlerClass handler = new HandlerClass();
myPanel.addMouseListener(handler);
add(slide, BorderLayout.SOUTH);
add(myPanel, BorderLayout.CENTER);
}
private class HandlerClass implements MouseListener{
#Override
public void mouseClicked(MouseEvent event) {
// TODO Auto-generated method stub
Right here is what is new with the code, this method gets the x and y coordinates of a click and sends it to MainClass object myPanel which has the setPosition method; class show before.
myPanel.setPosition(event.getX(),event.getY());
repaint(); }
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(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
}
}
}
Here is the MainClass class, it is poorley named as it's not actually the main class...
import java.awt.;
import javax.swing.;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Panel extends JPanel{
private int x1,y1;
private int d = 10;
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.CYAN);
g.fillOval(x1, y1, d, d);
}
public void checkDiameter(int newD)
{
//New format for if statements
d = (newD >= 0 ? newD //if
: 10//else
);
repaint();
}
public void setPosition(int newX, int newY) {
this.x1 = newX;
this.y1 = newY;
repaint();
}
public Dimension getPreferredSize(){
return new Dimension(200,200);
}
public Dimension getMinimumSize(){
return getPreferredSize();
}
}
Related
I finally learned how to get graphics to work in java thanks to the guy who helped me on my previous question, but now I can't get key bindings to work. I know that the graphics method is called as I need it to, and I think that I have declared my key bindings properly, but the 'actionPerformed()' method won't call. I tried using the singleton pattern to get my player object across classes and I feel that it somehow screwed everything else up. I tried looking through quite a few other questions relating to my issue but I still couldn't figure it out, unless I'm overloooking something obvious. I'd REALLY appreciate if one of you majestic programming wizards could crack this one:
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
public class Player {
private int xLoc, yLoc;
private boolean isFiring;
private String filename;
private ImageIcon imageicon;
private URL imgURL;
private static Player player;
public Player(int xl, int yl, boolean fire, String name){
xLoc = xl;
yLoc = yl;
isFiring = fire;
filename = name;
imgURL = getClass().getResource(name);
imageicon = new ImageIcon(imgURL);
}
public static Player getInstance(){
if(player == null){
player = new Player(0,0,false,"Dog.jpg");
}
return player;
}
public void fire(){
}
public int getX(){
return xLoc;
}
public int getY(){
return yLoc;
}
public void newX(int x){
xLoc = x;
}
public ImageIcon getImg() {
return imageicon;
}
public void newImg(ImageIcon ii){
imageicon = ii;
}
public URL getURL(){
return imgURL;
}
public void newURL(String n){
imgURL = getClass().getResource(n);
}
public void updateObject(){
imageicon = new ImageIcon(imgURL);
}
}
.
import java.awt.Graphics;
import java.net.URL;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class GamePanel extends JPanel{
int nameSwap = 0;
Player player;
public GamePanel(){
player = Player.getInstance();
repaint();
System.out.println("Repaint method called");
this.getInputMap().put(KeyStroke.getKeyStroke("A"), "moveLeft");
this.getActionMap().put("moveLeft", new MoveLR(-1));
this.getInputMap().put(KeyStroke.getKeyStroke("D"), "moveRight");
this.getActionMap().put("moveRight", new MoveLR(1));
this.getInputMap().put(KeyStroke.getKeyStroke("S"), "fire");
this.getActionMap().put("fire", new Fire());
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(player.getImg().getImage(), player.getX(), player.getY(), 50, 50, null);
//System.out.println("Graphics method called");
}
}
.
import java.awt.Color;
import javax.swing.JFrame;
public class Window {
public Window() {
JFrame frame = new JFrame("Epic Game");
frame.setSize(800,600);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GamePanel panel = new GamePanel();
frame.add(panel);
frame.setVisible(true);
while(true){
panel.repaint();
}
}
public static void main(String[] args){
Window window = new Window();
}
}
.
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;
import javax.swing.Action;
public class MoveLR implements Action{
private int moveVal;
Player player;
public MoveLR(int mv){
moveVal = mv;
player = Player.getInstance();
System.out.println("New MoveLR object made");
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
player.newX(player.getX() + 1);
System.out.println("actionPerformed() called");
}
#Override
public void addPropertyChangeListener(PropertyChangeListener arg0) {
// TODO Auto-generated method stub
}
#Override
public Object getValue(String arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return false;
}
#Override
public void putValue(String arg0, Object arg1) {
// TODO Auto-generated method stub
}
#Override
public void removePropertyChangeListener(PropertyChangeListener arg0) {
// TODO Auto-generated method stub
}
#Override
public void setEnabled(boolean arg0) {
// TODO Auto-generated method stub
}
}
You're using the wrong InputMap. Use the getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW). This way you'll bind to keys that are active when the JPanel doesn't have focus but is displayed in a window that does. The default InputMap is the one used for JComponent.WHEN_FOCUSED which is only valid when the bound component has focus, which is not what you want to do or use.
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"),
"moveLeft");
Also use classes that extend AbstractAction, not ones that implement Action as your Actions are not fully wired. And yes, you can repaint at the end of the actionPerformed as long as you have a reference to the JPanel, which the ActionEvent can get you.
Test program:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class Window {
public Window() {
JFrame frame = new JFrame("Epic Game");
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GamePanel panel = new GamePanel();
frame.add(panel);
frame.setVisible(true);
// !! while (true) {
// panel.repaint();
// }
}
public static void main(String[] args) {
new Window();
}
}
#SuppressWarnings("serial")
class GamePanel extends JPanel {
int nameSwap = 0;
Player player;
public GamePanel() {
player = Player.getInstance();
repaint();
System.out.println("Repaint method called");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"), "moveLeft");
this.getActionMap().put("moveLeft", new MoveLR(-1));
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("D"), "moveRight");
this.getActionMap().put("moveRight", new MoveLR(1));
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("S"), "fire");
this.getActionMap().put("fire", new Fire());
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(player.getImg().getImage(), player.getX(), player.getY(), 50,
50, null);
// System.out.println("Graphics method called");
}
}
class Player {
private int xLoc, yLoc;
private boolean isFiring;
private String filename;
private ImageIcon imageicon;
// !! private URL imgURL;
private static Player player;
public Player(int xl, int yl, boolean fire, String name) {
BufferedImage img = new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.red);
g2.fillOval(2, 2, 16, 16);
g2.dispose();
imageicon = new ImageIcon(img);
xLoc = xl;
yLoc = yl;
isFiring = fire;
filename = name;
// !! imgURL = getClass().getResource(name);
// imageicon = new ImageIcon(imgURL);
}
public static Player getInstance() {
if (player == null) {
player = new Player(0, 0, false, "Dog.jpg");
}
return player;
}
public void fire() {
}
public int getX() {
return xLoc;
}
public int getY() {
return yLoc;
}
public void newX(int x) {
xLoc = x;
}
public ImageIcon getImg() {
return imageicon;
}
public void newImg(ImageIcon ii) {
imageicon = ii;
}
// !! public URL getURL(){
// return imgURL;
// }
// !! public void newURL(String n){
// imgURL = getClass().getResource(n);
// }
public void updateObject() {
// !! imageicon = new ImageIcon(imgURL);
System.out.println("update object called");
}
}
class MoveLR extends AbstractAction {
private int moveVal;
Player player;
public MoveLR(int mv) {
moveVal = mv;
player = Player.getInstance();
System.out.println("New MoveLR object made");
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
player.newX(player.getX() + moveVal);
((JPanel) e.getSource()).repaint();
System.out.println("actionPerformed() called");
}
}
class Fire extends AbstractAction {
public Fire() {
System.out.println("Fire created");
}
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("Fire called");
}
}
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.*;
import java.util.*;
public class test1 extends JFrame implements MouseListener {
private JPanel JP = new JPanel();
public test1() {
JP.setBorder(BorderFactory.createLineBorder(Color.black));
JP.addMouseListener(this);
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
this.add(JP);
this.pack();
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
test1 frame = new test1();
frame.setSize(400,400);
frame.setVisible(true);
}
});
}
public void mouseClicked(MouseEvent e) {
//drawCircle(e.getX(), e.getY());
//repaint();
ballball ball;
ball = new ballball();
//ball.paintComponent(Graphics g);
System.out.println("ballball");
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
//this.mouseX=e.getX();
//this.mouseY=e.getY();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
}
class ballball extends test1 implements Runnable {
private int squareX = 50;
private int squareY = 50;
private int squareW = 100;
private int squareH = 100;
public boolean draw;
private Vector<Object> v = new Vector<Object>();
public ballball() {
/*addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
draw = true;
//Thread thread1 = new Thread(this.moveSquare(50, 50));
repaint();
//moveSquare(e.getX(),e.getY());
}
});*/
/*addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});*/
System.out.println("ball created");
this.repaint();
}
public void run() {
}
private void moveSquare(int x, int y) {
int OFFSET = 1;
if ((squareX!=x) || (squareY!=y)) {
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
squareX=x;
squareY=y;
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
}
}
public void paint(Graphics g) {
g.drawString("abcasdfasffasfas", 10, 10);
}
//#Override
public void paintComponent(Graphics g) {
//if (draw) {
// existing code
System.out.println("paint");
//super.paintComponent(g);
//g.drawString("This is my custom Panel!",10,20);
//g.setColor(Color.RED);
//g.fillRect(squareX,squareY,squareW,squareH);
//g.setColor(Color.BLACK);
//g.drawRect(squareX,squareY,squareW,squareH);
Shape circle = new Ellipse2D.Float(squareX,squareY,100f,100f);
Graphics2D ga = (Graphics2D)g;
ga.draw(circle);
//}
}
}
The aim of the program is to click to create the circle, the ballball class extends the test1, when test1 detect the mouse click, the ballball object created. But the paint/paintComponent method is never be executed. In my program structure, is it possible to paint the circle to the super class JPanel?
JFrame is not a JComponent, it doesn't have a paintComponent method you can override. Instead you could extend a JPanel and add it to the frame.
I try to implement two classes, one dedicated to the interface and the other one dedicated to the canvas allowing user to draw shapes on it.
So basically, let's take one of my button, here is my Jbutton bCircle where I want to initialize the action in an anonymous class. I have put just the specific piece :
public class Application extends JFrame implements ActionListener {
toolBar.add(Box.createHorizontalGlue());
toolBar.add(Box.createVerticalGlue());
toolBar.add(bSquare, toolBar.getComponentCount() - 1);
toolBar.add(bCircle, toolBar.getComponentCount() - 1);
bCircle.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
//Action ?????
}
});
toolBar.add(bRectangle, toolBar.getComponentCount() - 1);
toolBar.add(bTriangle, toolBar.getComponentCount() - 1);
toolBar.add(bErase, toolBar.getComponentCount() - 1);
toolBar.setOrientation(SwingConstants.VERTICAL);
container.add(toolBar, BorderLayout.WEST);
}
And in the other class, here is the action I want the selected state of the Jbutton bCircle to execute when I click on the canvas :
public class DrawingCanvas extends JPanel implements MouseListener, MouseMotionListener {
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == bCircle) {
shapes.add(new Circle(e.getX(),e.getY()));
}
repaint();
}
}
shapes is a ArrayList stocking the shapes to make the canvas easier to clean, Circle is a class which only contains drawing of the circle.
At the end, the purpose is to allow user to click first on four buttons representing four shapes, then draw them by a mouse pressed on the canvas. But I don't know how to link theses two classes, please help me,
Thanks in advance,
P.S : the full Application class (interface) that I have updated a second time:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
public class Application extends JFrame implements ActionListener {
{
//Set appearance Look & Feel for the window
try { javax.swing.UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
} catch(Exception e) {
e.printStackTrace();
}
}
private DrawingCanvas canvas = new DrawingCanvas();
private JPanel container = new JPanel();
private JPanel commandes = new JPanel();
private JMenuBar menu = new JMenuBar();
private JMenu newFile = new JMenu();
private JMenu open = new JMenu();
private JMenu save = new JMenu();
private JFileChooser fileChooser;
private JToolBar toolBar = new JToolBar();
private JButton bSquare = new JButton("Square");
private JButton bRectangle = new JButton("Rectangle");
private JButton bCircle = new JButton("Circle");
private JButton bTriangle = new JButton("Triangle");
private JButton bErase = new JButton("CLEAR");
//public static boolean bIsSelected = false;
public Application(){
this.setTitle("Animation");
this.setSize(579, 432);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
container.add(canvas, BorderLayout.CENTER);
this.setContentPane(container);
toolBar.add(Box.createHorizontalGlue());
toolBar.add(Box.createVerticalGlue());
toolBar.add(bSquare, toolBar.getComponentCount() - 1);
toolBar.add(bCircle, toolBar.getComponentCount() - 1);
bCircle.addActionListener(new SampleActionListener(canvas, new Circle()));
toolBar.add(bRectangle, toolBar.getComponentCount() - 1);
toolBar.add(bTriangle, toolBar.getComponentCount() - 1);
toolBar.add(bErase, toolBar.getComponentCount() - 1);
bErase.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent erase){
canvas.getShapes().clear();
repaint();
}
});
toolBar.setOrientation(SwingConstants.VERTICAL);
container.add(toolBar, BorderLayout.WEST);
menu.add(newFile);
newFile.setIcon(new ImageIcon("src/images/new.png"));
menu.add(open);
open.setIcon(new ImageIcon("src/images/open.png"));
menu.add(save);
save.setIcon(new ImageIcon("src/images/save.png"));
this.setJMenuBar(menu);
}
public class SampleActionListener implements ActionListener {
private final DrawingCanvas canvas2;
private final ShapeGenerator shapeGenerator;
public SampleActionListener(DrawingCanvas canvas, ShapeGenerator shapeGenerator) {
this.canvas2 = canvas;
this.shapeGenerator = shapeGenerator;
}
public void actionPerformed(ActionEvent event) {
this.canvas2.setShapeGenerator(shapeGenerator);
}
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Application App = new Application();
}
}
Here is the class for the canvas, uploaded a second time as well :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JPanel;
public class DrawingCanvas extends JPanel implements MouseListener {
private ArrayList<Shape> shapes = new ArrayList<>();
private Shape shapeUnderMouse = null;
public ArrayList<Shape> getShapes() {
return shapes;
}
public void setShapes(ArrayList<Shape> shapes) {
this.shapes = shapes;
}
public DrawingCanvas() {
super();
addMouseListener(this);
}
public void paint(Graphics g){
for(int i = 0;i < shapes.size();i++){
shapes.get(i).paint(g);
}
}
#Override
public void mouseClicked(MouseEvent e) {
// 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
}
public void addShape(Shape anyShape)
{
shapes.add(anyShape);
}
#Override
public void mousePressed(MouseEvent e) {
shapes.add(this.shapeGenerator.getGeneratedShape(e.getX(), e.getY()));
repaint();
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void setShapeGenerator(ShapeGenerator shapeGenerator) {
// TODO Auto-generated method stub
}
Now, the class shape :
import javax.swing.JPanel;
public class Shape extends JPanel{
protected int posX;
protected int posY;
/*public Shape(int posX, int posY) {
super();
this.posX = posX;
this.posY = posY;
}*/
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
}
My little circle class :
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Ellipse2D.Float;
import javax.swing.JPanel;
public class Circle extends Shape implements ShapeGenerator{
/*public Circle(int posX, int posY) {
super(posX, posY);
// TODO Auto-generated constructor stub
}*/
public void paint(Graphics g){
g.fillOval(posX,posY,40,40);
g.setColor(Color.blue);
}
public Shape getGeneratedShape(int x, int y) {
return new Ellipse2D.Float(x, y, 10, 10); //--> does not work, ask me to change method type to a float
return new Circle();
}
}
And finally the interface, all the class are in separate classes :
public interface ShapeGenerator {
Shape getGeneratedShape(int posX, int posY);
}
In fact, it's pretty easy. Don't use anonymous class.
For example, with your code, you just have to attach a defined listener. For example :
bCircle.addActionListener(new SampleActionListener(pan, new CircleShapeGenerator()));
Here is the SampleActionListener witch implements the ActionListener interface
public class SampleActionListener implements ActionListener {
private final DrawingCanvas canvas;
private final ShapeGenerator shapeGenerator;
public SampleActionListener(DrawingCanvas canvas, ShapeGenerator shapeGenerator) {
this.canvas = canvas;
this.shapeGenerator = shapeGenerator;
}
public void actionPerformed(ActionEvent event) {
this.canvas.setShapeGenerator(shapeGenerator);
}
}
Here is the class CircleShapeGenerator
public class CircleShapeGenerator implements ShapeGenerator {
public Shape getGeneratedShape(int x, int y) {
return new Ellipse2D.Float(x, y, 10, 10);
}
}
and the interface ShapeGenerator
public interface ShapeGenerator {
Shape getGeneratedShape(int x, int y);
}
and, if you want to add the action listener on the rectangle button, it's really easy now. create this class:
public class RectangleShapeGenerator implements ShapeGenerator {
public Shape getGeneratedShape(int x, int y) {
return new Rectangle2D.Float(x, y, 10, 10);
}
}
and in your application class, add the following code
toolBar.add(bRectangle, toolBar.getComponentCount() - 1);
bRectangle.addActionListerner(pan, new RectangleShapeGenerator() )
for your method paint in your DrawingCanvas, i think, you should use a code like this :
for (Shape s : shapes) {
Graphics2D g2 = (Graphics2D) g;
g2.draw(s);
}
BR,
Patouche
Sorry for my english, i know it's not really perfect...
First of all, remove your class Shape. You don't need to. Shape is a interface defined by Java. Use this interface instead.
Your setter for ShapeGenerator in the DrawingCanvas class do nothing. So add it. Your method paint is not correct.
public class DrawingCanvas extends JPanel implements MouseListener {
// Shape here is the java.awt.Shape from java.
private ArrayList<Shape> shapes = new ArrayList<>();
private ShapeGenerator shapeGenerator;
...
...
public void paint(Graphics g){
super.paint(g);
for (Shape s : shapes) {
Graphics2D g2 = (Graphics2D) g;
g2.draw(s);
}
}
...
#Override
public void mousePressed(MouseEvent e) {
shapes.add(this.shapeGenerator.getGeneratedShape(e.getX(), e.getY()));
repaint();
}
public void setShapeGenerator(ShapeGenerator shapeGenerator) {
this.shapeGenerator = shapeGenerator;
}
}
You class Circle is really to complex. It's simple and this method don't need any paint method. You class Circle is really simple :
public class Circle implements ShapeGenerator{
public Shape getGeneratedShape(int x, int y) {
// This will return a java.awt.Shape instance
return new Ellipse2D.Float(x, y, 10, 10);
}
}
And i thinks, that's all.
Here is the solution to your problem. But it's really dirty... Like i said, there is no sense to have a Shape that is inhereted from JPanel !!
public class Application extends JFrame implements ActionListener {
{
// Set appearance Look & Feel for the window
try {
javax.swing.UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
e.printStackTrace();
}
}
private final DrawingCanvas pan = new DrawingCanvas();
// don't use to many field, it's confusing and not necessary.
// you can do local var instead.
private final JPanel container = new JPanel();
private final JPanel commandes = new JPanel();
private final JMenuBar menu = new JMenuBar();
private final JMenu newFile = new JMenu();
private final JMenu open = new JMenu();
private final JMenu save = new JMenu();
private JFileChooser fileChooser;
private final JToolBar toolBar = new JToolBar();
private final JButton bSquare = new JButton("Square");
private final JButton bRectangle = new JButton("Rectangle");
private final JButton bCircle = new JButton("Circle");
private final JButton bTriangle = new JButton("Triangle");
private final JButton bErase = new JButton("CLEAR");
public Application() {
this.setTitle("Animation");
this.setSize(579, 432);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
container.add(pan, BorderLayout.CENTER);
this.setContentPane(container);
toolBar.add(Box.createHorizontalGlue());
toolBar.add(Box.createVerticalGlue());
toolBar.add(bSquare, toolBar.getComponentCount() - 1);
toolBar.add(bCircle, toolBar.getComponentCount() - 1);
bCircle.addActionListener(new SampleActionListener(pan, new CircleShapeGenerator()));
toolBar.add(bRectangle, toolBar.getComponentCount() - 1);
// bRectangle.addActionListener(new SampleActionListener(pan, new
// RectangleShapeGenerator()));
toolBar.add(bTriangle, toolBar.getComponentCount() - 1);
toolBar.add(bErase, toolBar.getComponentCount() - 1);
toolBar.setOrientation(SwingConstants.VERTICAL);
container.add(toolBar, BorderLayout.WEST);
menu.add(newFile);
newFile.setIcon(new ImageIcon("src/images/new.png"));
menu.add(open);
open.setIcon(new ImageIcon("src/images/open.png"));
menu.add(save);
save.setIcon(new ImageIcon("src/images/save.png"));
this.setJMenuBar(menu);
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Application App = new Application();
}
}
We keep the CircleShapeGenerator class
public class CircleShapeGenerator implements ShapeGenerator {
#Override
public CircleShape getGeneratedShape(int x, int y) {
CircleShape c = new CircleShape();
c.setCanvasX(x);
c.setCanvasY(y);
return c;
}
}
The circle shape
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
public class CircleShape extends Shape {
private final Ellipse2D.Float ellipse2D;
public CircleShape() {
this.ellipse2D = new Ellipse2D.Float();
this.setRadius(20);
}
private void setRadius(int r) {
this.ellipse2D.height = r;
this.ellipse2D.width = r;
}
#Override
public void setCanvasX(int canvasX) {
this.canvasX = canvasX;
this.ellipse2D.x = canvasX;
}
#Override
public void setCanvasY(int canvasY) {
this.canvasY = canvasY;
this.ellipse2D.y = canvasY;
}
#Override
public java.awt.Shape getTrueShape() {
return this.ellipse2D;
}
}
A class for the contextual menu to edit your shape
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
class ContextualShapeMenu extends JPopupMenu {
private final Shape shape;
public ContextualShapeMenu(Shape shape) {
this.shape = shape;
JMenuItem anItem = new JMenuItem("Edit the size");
add(anItem);
}
}
The DrawingCanvas class
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import com.google.common.collect.Lists;
public class DrawingCanvas extends JPanel implements MouseListener {
protected ArrayList<Shape> shapes = new ArrayList<Shape>();
private ShapeGenerator shapeGenerator;
public ArrayList<Shape> getShapes() {
return shapes;
}
public void setShapes(ArrayList<Shape> shapes) {
this.shapes = shapes;
}
public DrawingCanvas() {
super();
addMouseListener(this);
}
#Override
public void paint(Graphics g) {
super.paint(g);
for (Shape s : shapes) {
s.paint(g);
}
}
#Override
public void mouseClicked(MouseEvent e) {
switch (e.getButton()) {
case MouseEvent.BUTTON1:
shapes.add(this.shapeGenerator.getGeneratedShape(e.getX(), e.getY()));
break;
default:
Shape shape = getShapeUnderMouse(e);
if (shape != null) {
ContextualShapeMenu menu = new ContextualShapeMenu(shape);
menu.show(e.getComponent(), e.getX(), e.getY());
}
}
repaint();
}
private Shape getShapeUnderMouse(MouseEvent e) {
List<Shape> reversed = Lists.reverse(this.shapes);
for (Shape s : reversed) {
if (s.contains(e.getX(), e.getY())) {
return s;
}
}
return null;
}
#Override
public void mouseEntered(MouseEvent e) {
// Do nothing
}
#Override
public void mouseExited(MouseEvent e) {
// Do nothing
}
#Override
public void mousePressed(MouseEvent e) {
// Do nothing
}
#Override
public void mouseReleased(MouseEvent e) {
// Do nothing
}
public void setShapeGenerator(ShapeGenerator shapeGenerator) {
this.shapeGenerator = shapeGenerator;
}
}
Still the ActionListener. Rename it.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SampleActionListener implements ActionListener {
private final DrawingCanvas canvas;
private final ShapeGenerator shapeGenerator;
public SampleActionListener(DrawingCanvas canvas, ShapeGenerator shapeGenerator) {
this.canvas = canvas;
this.shapeGenerator = shapeGenerator;
}
#Override
public void actionPerformed(ActionEvent event) {
this.canvas.setShapeGenerator(shapeGenerator);
}
}
The ShapeGenerator interface
public interface ShapeGenerator {
Shape getGeneratedShape(int x, int y);
}
And at least, the most stupid class : Shape
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;
public abstract class Shape extends JPanel implements java.awt.Shape {
protected int canvasX;
protected int canvasY;
public int getCanvasX() {
return canvasX;
}
public abstract java.awt.Shape getTrueShape();
public abstract void setCanvasX(int canvasX);
public int getCanvasY() {
return canvasY;
}
public abstract void setCanvasY(int canvasY);
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.draw(this.getTrueShape());
}
#Override
public Rectangle getBounds() {
return getTrueShape().getBounds();
}
#Override
public Rectangle2D getBounds2D() {
return getTrueShape().getBounds2D();
}
#Override
public boolean contains(int x, int y) {
return this.getTrueShape().contains(x, y);
}
#Override
public boolean contains(double x, double y) {
return this.getTrueShape().contains(x, y);
}
#Override
public boolean contains(Point2D p) {
return this.getTrueShape().contains(p);
}
#Override
public boolean contains(Point p) {
return this.getTrueShape().contains(p);
}
#Override
public boolean intersects(double x, double y, double w, double h) {
return this.getTrueShape().intersects(x, y, w, h);
}
#Override
public boolean intersects(Rectangle2D r) {
return this.getTrueShape().intersects(r);
}
#Override
public boolean contains(double x, double y, double w, double h) {
return this.getTrueShape().contains(x, y, w, h);
}
#Override
public boolean contains(Rectangle2D r) {
return this.getTrueShape().contains(r);
}
#Override
public PathIterator getPathIterator(AffineTransform at) {
return this.getTrueShape().getPathIterator(at);
}
#Override
public PathIterator getPathIterator(AffineTransform at, double flatness) {
return this.getTrueShape().getPathIterator(at, flatness);
}
}
I have add the guava librairy, so, you will not find the Lists class. Add it to your project, use a other librairy or create a method to reverse your list.
Good luck and don't make something like that in the future !!! It's coding horror.
By the way, i came from France.
I am trying to draw lines with the mouse in a JFrame window, and when I try to do so, it doesn't work! Please ignore the menu, I am trying to do things with that later! What did I miss! I would be grateful if you could give me some hints!
public class newGUI extends JFrame implements ActionListener, MouseMotionListener, MouseListener {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 300;
public static final int HEIGHT = 200;
Point point1;
Point point2;
Line2D line2d;
public static void main(String[] args){
newGUI gui = new newGUI();
gui.setVisible(true);
}
public newGUI()
{
super("Menu Demonstration");
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenu colorMenu = new JMenu("Choose Colors");
JMenuItem greenChoice = new JMenuItem("GREEN");
greenChoice.addActionListener(this);
colorMenu.add(greenChoice);
JMenuItem redChoice = new JMenuItem("RED");
colorMenu.add(redChoice);
JMenuBar bar = new JMenuBar();
bar.add(colorMenu);
setJMenuBar(bar);
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
#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 arg0) {
// TODO Auto-generated method stub
point1=arg0.getPoint();
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
point2=arg0.getPoint();
line2d=new Line2D.Double(point1, point2);
repaint();
}
#Override
public void mouseMoved(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D) g;
if(point1!=null && point2!=null){
g2d.setPaint(Color.RED);
g2d.setStroke(new BasicStroke(1.5f));
g2d.draw(line2d);
repaint();
}
}
}
Always start class names with a capital letter i.e NewGui
Use Event Dispatch Thread for creating and changing of UI components
Do not extend JFrame class uncecessarily
Do not call setSize(..) rather call JFrame#pack() on JFrame instance
JFrame does not have a paintComponent(..), rather add custom JPanel and override its paintComponent(..) and getPreferredSize(..)
Dont forget to call super.paintComponent(..) in your custom JPanel
Do not call repaint() from within paintComponent(..) (this will cause an infinite loop of repainting more than needed)
Also where possible (if it is not used by other classes) use anonymous MouseListeners/MouseMotionListeners and rather use MouseAdapter instead of MouseListener/MouseMotionListeners etc.
Here is an example I made (basically your code with fixes mentioned):
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class NewGui implements ActionListener {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 300;
public static final int HEIGHT = 200;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
NewGui gui = new NewGui();
}
});
}
public NewGui() {
initComponents();
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
private void initComponents() {
JFrame frame = new JFrame("Menu Demonstration");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenu colorMenu = new JMenu("Choose Colors");
JMenuItem greenChoice = new JMenuItem("GREEN");
greenChoice.addActionListener(this);
colorMenu.add(greenChoice);
JMenuItem redChoice = new JMenuItem("RED");
colorMenu.add(redChoice);
JMenuBar bar = new JMenuBar();
bar.add(colorMenu);
frame.setJMenuBar(bar);
frame.add(new MyPanel());
frame.pack();
frame.setVisible(true);
}
}
class MyPanel extends JPanel {
Point point1;
Point point2;
Line2D line2d;
public MyPanel() {
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent me) {
super.mousePressed(me);
point1 = me.getPoint();
}
});
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent me) {
super.mouseDragged(me);
// TODO Auto-generated method stub
point2 = me.getPoint();
line2d = new Line2D.Double(point1, point2);
repaint();
}
});
}
//so our panel will be visible
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
//Set anti-alias!
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if (point1 != null && point2 != null) {
g2d.setPaint(Color.RED);
g2d.setStroke(new BasicStroke(1.5f));
g2d.draw(line2d);
}
}
}
Anybody know how can I repaint in a clone JPanel. Im using CLONE, so I can REPAINT() one, and the other will do the same automatically.
My code only paints the original JPanel if I move the mouse in the original or in the clone panel,
but If I move the mouse in the clone panel, this jpanel doesn't paint.
Thanks in advance
CODE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ProcessorClone {
public static void main(String[] args) {
JFrame aWindow = new JFrame();
aWindow.setBounds(300, 200, 300, 100);
aWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Container content = aWindow.getContentP
aWindow.setVisible(true);
CardViewer panel02=new CardViewer();
CardViewer panel01= (CardViewer) panel02.clone();
aWindow.setLayout(new BorderLayout());
aWindow.add(panel01,BorderLayout.NORTH);
aWindow.add(panel02,BorderLayout.SOUTH);
panel01.setBackground(Color.RED);
panel02.setBackground(Color.blue);
panel01.repaint();
panel02.repaint();
panel01.validate();
panel02.validate();
}
}
class CardViewer extends JPanel implements MouseListener,MouseMotionListener, Cloneable {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel mContentPaneBorder;
private JPanel mContentPane;
private JButton FileButton=new JButton("AAA");
private Point p;
public CardViewer(){
super();
this.add(FileButton);
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
public void mouseClicked(MouseEvent arg0) {
System.out.println("mouseClicked");
}
#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) {
System.out.println("mousePressed");
p = null;
repaint();
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseMoved(MouseEvent e) {
System.out.println("mouseMoved");
p = e.getPoint();
this.repaint();
this.validate();
}
public void paint(Graphics g) {
System.out.println( g.getClass() );
if (p != null) {
Dimension d = getSize();
int xc = d.width / 2;
int yc = d.height / 2;
g.drawLine(p.x, p.y, p.x, p.y);
this.setBackground(Color.pink);
}
}
public Object clone () {
// First make exact bitwise copy
CardViewer copy = null;
try {
copy = (CardViewer)super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return copy;
}
}
.clone() does not return a mirror of the JPanel but returns a copy of the object, so you really have 2 separate JPanel objects so actions in one will not automatically reflect in the other.
You could override all the actions in a component that inherits from JPanel with a reference to a .cloned() JPanel object and then route all methods to the other JPanel after calling super()