Error: java.lang.NullPointerException and more with unknown sources - java

I'm having difficulties fixing my code. It compiles perfectly, except for the number of exceptions I get once I run the applet. The error message I keep getting is:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at WholePanel$Canvas.paintComponent(WholePanel.java:82)
and a multitude of others with unknown sources. I've looked at various NullPointerException questions on the site and none of them quite help.
Here is my code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*; // To use listener interfaces
import java.util.ArrayList;
public class WholePanel extends JPanel
{
private ArrayList <Rect> rectList;
private ArrayList <Rect> newList;
private boolean flag;
private Color currentColor;
private Canvas canvas;
private JComboBox colorList;
private JButton erase;
private JButton undo;
private JPanel buttonPanel;
private JPanel controlPanel;
private JSplitPane sp;
public WholePanel()
{
//Here we use black to draw a rectangle
currentColor = Color.black;
String colors[] = {"black", "red", "blue", "green", "orange"};
JComboBox<String> colorList = new JComboBox<String>(colors);
ColorListener colorListener = new ColorListener();
colorList.addActionListener(colorListener);
undo = new JButton("Undo");
undo.addActionListener(new ButtonListener());
erase = new JButton("Erase");
erase.addActionListener(new ButtonListener());
buttonPanel = new JPanel(new GridLayout(1,2));
buttonPanel.add(undo);
buttonPanel.add(erase);
controlPanel = new JPanel();
controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS));
controlPanel.add(colorList);
controlPanel.add(buttonPanel);
canvas = new Canvas();
JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, controlPanel, canvas);
setLayout(new BorderLayout());
add(sp);
//To be completed
}
private class Canvas extends JPanel
{
//This method needs to be defined to draw in this panel
private Point startingPoint, endingPoint, movingPoint;
private Rect rectangle;
private int x, y;
public Canvas()
{
PointListener pointListener = new PointListener();
this.addMouseListener(pointListener);
this.addMouseMotionListener(pointListener);
}
public void paintComponent(Graphics page)
{
super.paintComponent(page);
setBackground(Color.white);
for(int i = 0; i < rectList.size(); i++)
{
rectList.get(i).draw(page);
}
if(endingPoint != null)
{
startingPoint = null;
endingPoint = null;
movingPoint = null;
}
else if(movingPoint != null && x >= 0 && y >= 0)
{
page.setColor(currentColor);
page.drawRect(startingPoint.x, startingPoint.y, x, y);
}
//To be filled
}
} //End of Canvas class
private class PointListener implements MouseListener, MouseMotionListener
{
private Point startingPoint, endingPoint, movingPoint;
private Rect rectangle;
private int x, y;
public void mousePressed(MouseEvent event)
{
//Needs to be filled
startingPoint = event.getPoint();
}
public void mouseReleased(MouseEvent event)
{
//Needs to be filled
endingPoint = event.getPoint();
x = endingPoint.x - startingPoint.x;
y = endingPoint.y - startingPoint.y;
if(endingPoint != null && x >= 0 && y >= 0)
{
Rect rectangle = new Rect(startingPoint.x, startingPoint.y, x, y, currentColor);
rectList.add(rectangle);
}
canvas.repaint();
}
public void mouseClicked(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mouseDragged(MouseEvent event)
{
//Needs to be filled
movingPoint = event.getPoint();
x = movingPoint.x - startingPoint.x;
y = movingPoint.y - startingPoint.y;
canvas.repaint();
}
public void mouseMoved(MouseEvent event) {}
} //end of PointListener
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
rectList.trimToSize();
rectList.remove(rectList.size() - 1);
repaint();
}
}
private class ColorListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
switch(colorList.getSelectedIndex())
{
case 'r':
currentColor = Color.red;
break;
case 'b':
currentColor = Color.blue;
break;
case 'g':
currentColor = Color.green;
break;
case 'o':
currentColor = Color.orange;
break;
default:
currentColor = Color.black;
}
}
}
} // end of Whole Panel Class

Both rectList and newList need to be initialized
rectList = new ArrayList<Rect>();
newList = new ArrayList<Rect>();
Also another NPE source here - you're shadowing the variable colorList
JComboBox<String> colorList = new JComboBox<String>(colors);
should be
colorList = new JComboBox<String>(colors);

Related

I added a rectangle to a shape Arraylist but the shape will not show up on the panel

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.ArrayList;
#SuppressWarnings("serial")
public class GUI extends JFrame implements ActionListener, MouseListener {
private boolean drawLine = false;
private boolean drawRec = false;
private boolean drawOval = false;
private final JButton line;
private final JButton oval;
private final JButton rectangle;
private final JPanel buttonPanel;
public DrawStuff drawPanel = new DrawStuff();
public int x1;
public int x2;
public int y1;
public int y2;
public int click;
public GUI() {
super("Graphics IO");
this.click = 1;
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 3));
line = new JButton("Line");
line.addActionListener(this);
buttonPanel.add(line);
oval = new JButton("Oval");
oval.addActionListener(this);
buttonPanel.add(oval);
rectangle = new JButton("Rectangle");
rectangle.addActionListener(this);
buttonPanel.add(rectangle);
Container contentPane = this.getContentPane();
contentPane.add(buttonPanel, BorderLayout.SOUTH);
//add(drawPanel);
addMouseListener((MouseListener) this);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == line) {
drawLine = true;
repaint();
} else if (source == oval) {
drawOval = true;
repaint();
} else if (source == rectangle) {
drawRec = true;
repaint();
}
}
public static void main(String[] args) {
GUI guiIO = new GUI();
}
class DrawStuff extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLUE);
ArrayList<Shape> shapes = new ArrayList<>();
if (drawLine) {
drawLine = false;
} else if (drawOval) {
//no clue how to add an oval
drawOval = false;
} else if (drawRec) {
Rectangle rec = new Rectangle(x1, y1,Math.abs(x2-x1) , Math.abs(y2-y1));
shapes.add(rec);
drawRec = false;
}
Graphics2D j = (Graphics2D)g;
shapes.stream().map((s) -> {
((Graphics2D) j).draw((Shape) s);
return s;
}).forEach((_item) -> {
repaint();
});
}
}
#Override
public void mousePressed(MouseEvent me) {
if (click == 1){
x1 = me.getX();
y1 = me.getY();
System.out.println(x1);
System.out.println(y1);
click = 2;
}else if (click == 2) {
x2 = me.getX();
y2 = me.getY();
System.out.println(x2);
System.out.println(y2);
click = 1;
}
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
}
}
Okay so i have to make a program to create shapes using two mouseclicks and then be able to export/import them. I am trying to use arraylist for this but im having a hard time trying to get it to work. The rectangle im creating will not show up on the panel. What am i doing wrong? Please help me.
Lets start with the fact that DrawStuff hasn't actually been added to anything that is capable of painting it.
DrawStuff#paintComponent should be making decisions about updating the state of the shapes List, instead, your ActionListener and MouseListener should be making these decisions (what to add, where and what do modify), the DrawStuff panel should just be painting what's in the Shape list
You also shouldn't be modifying the state of the component from within the paintComponent calling things like setBackground could set up a repeated repaint request which could cripple your application if not your PC
Modify DrawStuff so it has it's own MouseListener and methods that allow your GUI to ask it to create new shapes. Make the shapes List a instance field so you can manage from within DrawStuff more easily
Something like...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GUI extends JFrame implements ActionListener {
private boolean drawLine = false;
private boolean drawRec = false;
private boolean drawOval = false;
private final JButton line;
private final JButton oval;
private final JButton rectangle;
private final JPanel buttonPanel;
public DrawStuff drawPanel = new DrawStuff();
public int x1;
public int x2;
public int y1;
public int y2;
public int click;
public GUI() {
super("Graphics IO");
this.click = 1;
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 3));
line = new JButton("Line");
line.addActionListener(this);
buttonPanel.add(line);
oval = new JButton("Oval");
oval.addActionListener(this);
buttonPanel.add(oval);
rectangle = new JButton("Rectangle");
rectangle.addActionListener(this);
buttonPanel.add(rectangle);
Container contentPane = this.getContentPane();
contentPane.add(buttonPanel, BorderLayout.SOUTH);
add(drawPanel);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == line) {
drawPanel.setDrawShape(DrawStuff.DrawShape.LINE);
} else if (source == oval) {
drawPanel.setDrawShape(DrawStuff.DrawShape.OVAL);
} else if (source == rectangle) {
drawPanel.setDrawShape(DrawStuff.DrawShape.RECTANGLE);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
GUI guiIO = new GUI();
}
});
}
public static class DrawStuff extends JPanel {
public enum DrawShape {
LINE, OVAL, RECTANGLE;
}
private ArrayList<Shape> shapes = new ArrayList<>();
private DrawShape drawShape = DrawShape.LINE;
private Shape currentShape;
public DrawStuff() {
setBackground(Color.BLUE);
MouseAdapter ma = new MouseAdapter() {
private Point clickPoint;
#Override
public void mousePressed(MouseEvent e) {
clickPoint = e.getPoint();
currentShape = null;
}
#Override
public void mouseReleased(MouseEvent e) {
if (currentShape != null) {
shapes.add(currentShape);
currentShape = null;
repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
Point p = e.getPoint();
switch (getDrawShape()) {
case LINE:
currentShape = new Line2D.Double(clickPoint, e.getPoint());
break;
case OVAL:
case RECTANGLE:
int x = clickPoint.x;
int y = clickPoint.y;
int width = p.x - clickPoint.x;
int height = p.y - clickPoint.y;
if (width < 0) {
x = p.x;
width *= -1;
}
if (height < 0) {
y = p.y;
height *= -1;
}
switch (getDrawShape()) {
case OVAL:
currentShape = new Ellipse2D.Double(x, y, width, height);
break;
case RECTANGLE:
currentShape = new Rectangle2D.Double(x, y, width, height);
break;
}
break;
}
repaint();
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
public DrawShape getDrawShape() {
return drawShape;
}
public void setDrawShape(DrawShape drawShape) {
this.drawShape = drawShape;
currentShape = null;
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLACK);
for (Shape shape : shapes) {
g2d.draw(shape);
}
if (currentShape != null) {
g2d.setColor(Color.RED);
g2d.draw(currentShape);
}
}
}
}
For example. You always need to be asking yourself "who is responsible for doing what". In this case the DrawStuff panel is actually responsible for determine "where" something is drawn, but it needs more information about "what", then based on that information it can perform the actual operation

Java KeyEvent square movement

I have a piece of code in which a KeyEvent is triggered when any of the arrow keys are pressed. This in turn causes a square to move across the screen.
Now I've noticed that when I press and hold the key, the square moves but the time after the initial movement to the subsequent movements is quite long if you understand what I mean? How would I go about diminishing this time?
Thanks!
import java.awt.*;
import javax.swing.*;
import squarequest.sprites.*;
import java.awt.event.*;
public class GamePanel extends JPanel{
private final int HEIGHT = 400;
private final int WIDTH = 600;
private Square square;
private Circle circle;
public GamePanel(){
addKeyListener(new DirectionListener());
setBackground (Color.white);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
square = new Square();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
square.display(g);
}
public class DirectionListener implements KeyListener{
#Override
public void keyReleased(KeyEvent event) {}
#Override
public void keyTyped(KeyEvent event) {}
#Override
public void keyPressed(KeyEvent event) {
switch(event.getKeyCode()){
case KeyEvent.VK_UP:
square.moveUp();
break;
case KeyEvent.VK_DOWN:
square.moveDown();
break;
case KeyEvent.VK_LEFT:
square.moveLeft();
break;
case KeyEvent.VK_RIGHT:
square.moveRight();
break;
}
repaint();
}
}
}
Use a Swing Timer for the actual movement.
Start the Timer on key press
Stop it on key release.
Or better still, keep the timer always running, but only moving the sprite based on the state of a map, one that holds a Direction enum key and a Boolean value.
Better to use key bindings rather than KeyListeners.
e.g.,
import java.awt.*;
import javax.swing.*;
//!! import squarequest.sprites.*;
import java.awt.event.*;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
public class GamePanel extends JPanel {
private static final int ANIMATION_DELAY = 15;
private final int HEIGHT = 400;
private final int WIDTH = 600;
private Square square;
private EnumMap<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
private Map<Integer, Direction> keyToDir = new HashMap<>();
// !! private Circle circle;
private Timer animationTimer;
public GamePanel() {
for (Direction dir : Direction.values()) {
dirMap.put(dir, Boolean.FALSE);
}
keyToDir.put(KeyEvent.VK_UP, Direction.UP);
keyToDir.put(KeyEvent.VK_DOWN, Direction.DOWN);
keyToDir.put(KeyEvent.VK_LEFT, Direction.LEFT);
keyToDir.put(KeyEvent.VK_RIGHT, Direction.RIGHT);
// !! addKeyListener(new DirectionListener());
setKeyBindings();
setBackground(Color.white);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
square = new Square();
animationTimer = new Timer(ANIMATION_DELAY, new AnimationListener());
animationTimer.start();
}
private void setKeyBindings() {
int condition = WHEN_IN_FOCUSED_WINDOW;
final InputMap inputMap = getInputMap(condition);
final ActionMap actionMap = getActionMap();
boolean[] keyPressed = { true, false };
for (Integer keyCode : keyToDir.keySet()) {
Direction dir = keyToDir.get(keyCode);
for (boolean onKeyPress : keyPressed) {
boolean onKeyRelease = !onKeyPress; // to make it clear how bindings work
KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, 0,
onKeyRelease);
Object key = keyStroke.toString();
inputMap.put(keyStroke, key);
actionMap.put(key, new KeyBindingsAction(dir, onKeyPress));
}
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
square.display(g);
}
// public class DirectionListener implements KeyListener {
// #Override
// public void keyReleased(KeyEvent event) {
// int keyCode = event.getKeyCode();
// if (keyToDir.keySet().contains(keyCode)) {
// Direction dir = keyToDir.get(keyCode);
// dirMap.put(dir, false);
// }
// }
//
// #Override
// public void keyTyped(KeyEvent event) {
// }
//
// #Override
// public void keyPressed(KeyEvent event) {
// int keyCode = event.getKeyCode();
// if (keyToDir.keySet().contains(keyCode)) {
// Direction dir = keyToDir.get(keyCode);
// dirMap.put(dir, true);
// }
// }
// }
private class AnimationListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent evt) {
boolean repaint = false;
for (Direction dir : Direction.values()) {
if (dirMap.get(dir)) {
square.move(dir);
repaint = true;
}
}
if (repaint) {
repaint();
}
}
}
private class KeyBindingsAction extends AbstractAction {
private Direction dir;
boolean pressed;
public KeyBindingsAction(Direction dir, boolean pressed) {
this.dir = dir;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent evt) {
dirMap.put(dir, pressed);
}
}
private static void createAndShowGUI() {
GamePanel gamePanel = new GamePanel();
JFrame frame = new JFrame("GamePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(gamePanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
gamePanel.requestFocusInWindow();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
enum Direction {
UP(0, -1), DOWN(0, 1), LEFT(-1, 0), RIGHT(1, 0);
private int incrX;
private int incrY;
private Direction(int incrX, int incrY) {
this.incrX = incrX;
this.incrY = incrY;
}
public int getIncrX() {
return incrX;
}
public int getIncrY() {
return incrY;
}
}
class Square {
private int x = 0;
private int y = 0;
private int w = 20;
private int h = w;
private int step = 1;
private Color color = Color.red;
private Color fillColor = new Color(255, 150, 150);
private Stroke stroke = new BasicStroke(3f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND);
public void display(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(fillColor);
g2d.fillRect(x, y, w, h);
g2d.setStroke(stroke);
g2d.setColor(color);
g2d.drawRect(x, y, w, h);
g2d.dispose();
}
public void setStep(int step) {
this.step = step;
}
public void move(Direction dir) {
x += step * dir.getIncrX();
y += step * dir.getIncrY();
}
// public void moveRight() {
// x++;
// }
//
// public void moveLeft() {
// x--;
// }
//
// public void moveUp() {
// y--;
// }
//
// public void moveDown() {
// y++;
// }
}

Something seems wrong with the layout, JButton showing unexpected behaviour at resize of the window

JRE Version 1.7 Update 3
EXPECTED BEHAVIOUR
As I run the program, it works as expected, everything works smoothly. As when I click on STOP JButton the animation stops and the text on the same JButton changes to START. Now when i click on BALL COLOUR JButton, the colour of the BALL changes, as well as the colour of the BALL COLOUR JBUTTON, also changes, to that of the BALL. This whole behaviour works if I run my application as is without resizing.
UNEXPECTED BEHAVIOUR
But when i RESIZE my JFrame, by pulling the Right Side, that's when unexpected behaviour of my Application is shown, in the sense that if I press STOP JButton and then click on BALL COLOUR button, the text on the JButton clicked earlier whose text changed to START will change to STOP again when it should not be, as well as the colour of the BALL COLOUR JButton will remain unchanged or will turn to BLUE, when it should be changed to the colour of the ball. I am attaching the pics for more info. But if you will try to resize it back to it's original size or closer to that, then things will come back to normal. Why is this happening ? Any idea or clue will be much appreciated.
As My Application Runs with EXPECTED BEHAVIOUR as described above :
And here the UNEXPECTED BEHAVIOUR
BOTTOM-LINE :
Why the Application runs as usual as it should be, at the BEGINNING , but not when RESIZED by dragging it's RIGHT SIDE, but again if you bring it to it's original size or closer to it, things come back to normal, it works as expected ?
So considering the scenario, am I doing something wrong, in the program. Or is this exactly the situation, where I should be using the SwingWorker, Or Is this an issue with the Layout, or something hidden related to Content Pane. Please do put some light :-)
here is the code I am using, I had brought it down to the minimum, as I think to demonstrate my problem :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BallAnimation
{
private int x;
private int y;
private boolean positiveX;
private boolean positiveY;
private boolean isTimerRunning;
private int speedValue;
private int diameter;
private DrawingArea drawingArea;
private Timer timer;
private int colourCounter;
Color[] colours = {
Color.BLUE.darker(),
Color.MAGENTA.darker(),
Color.BLACK.darker(),
Color.RED.darker(),
Color.PINK.darker(),
Color.CYAN.darker(),
Color.DARK_GRAY.darker(),
Color.YELLOW.darker(),
Color.GREEN.darker()
};
private Color backgroundColour;
private Color foregroundColour;
private ActionListener timerAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
x = getX();
y = getY();
drawingArea.setXYColourValues(x, y, backgroundColour
, foregroundColour);
}
};
private JPanel buttonPanel;
private JButton startStopButton;
private JButton speedIncButton;
private JButton speedDecButton;
private JButton resetButton;
private JButton colourButton;
private JButton exitButton;
private ComponentAdapter componentAdapter = new ComponentAdapter()
{
public void componentResized(ComponentEvent ce)
{
timer.restart();
startStopButton.setText("STOP");
isTimerRunning = true;
}
};
public BallAnimation()
{
x = y = 0;
positiveX = positiveY = true;
speedValue = 1;
colourCounter = 0;
isTimerRunning = false;
diameter = 50;
backgroundColour = Color.WHITE.brighter();
foregroundColour = colours[colourCounter];
timer = new Timer(10, timerAction);
}
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Ball Animation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
drawingArea = new DrawingArea(x, y
, backgroundColour, foregroundColour, diameter);
drawingArea.addComponentListener(componentAdapter);
frame.add(makeButtonPanel(), BorderLayout.LINE_END);
frame.add(drawingArea, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JPanel makeButtonPanel()
{
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(0, 1));
buttonPanel.setBorder(BorderFactory.createLineBorder(
Color.DARK_GRAY, 5, true));
startStopButton = new JButton("START");
startStopButton.setBackground(Color.GREEN.darker());
startStopButton.setForeground(Color.WHITE.brighter());
startStopButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("START/STOP JButton Clicked!");
if (!isTimerRunning)
{
startStopButton.setText("STOP");
timer.start();
isTimerRunning = true;
buttonPanel.revalidate();
buttonPanel.repaint();
}
else if (isTimerRunning)
{
startStopButton.setText("START");
timer.stop();
isTimerRunning = false;
buttonPanel.revalidate();
buttonPanel.repaint();
}
}
});
startStopButton.setBorder(BorderFactory.createLineBorder(
Color.WHITE, 4, true));
buttonPanel.add(startStopButton);
colourButton = new JButton("BALL COLOUR");
colourButton.setBackground(colours[colourCounter]);
colourButton.setForeground(Color.WHITE);
colourButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("COLOUR JButton Clicked!");
//timer.restart();
colourCounter++;
if (colourCounter == 9)
colourCounter = 0;
foregroundColour = colours[colourCounter];
drawingArea.setXYColourValues(x, y, backgroundColour
, foregroundColour);
//drawingArea.setForegroundForBall(foregroundColour);
colourButton.setBackground(foregroundColour);
colourButton.revalidate();
colourButton.repaint();
//timer.start();
}
});
colourButton.setBorder(BorderFactory.createLineBorder(
Color.WHITE, 2, true));
buttonPanel.add(colourButton);
exitButton = new JButton("EXIT");
exitButton.setBackground(Color.RED.darker());
exitButton.setForeground(Color.WHITE.brighter());
exitButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("EXIT JButton Clicked!");
timer.stop();
System.exit(0);
}
});
exitButton.setBorder(BorderFactory.createLineBorder(
Color.RED.darker().darker(), 4, true));
buttonPanel.add(exitButton);
return buttonPanel;
}
private int getX()
{
if (x < 0)
positiveX = true;
else if (x >= drawingArea.getWidth() - diameter)
positiveX = false;
return (calculateX());
}
private int calculateX()
{
if (positiveX)
return (x += speedValue);
else
return (x -= speedValue);
}
private int getY()
{
if (y < 0)
positiveY = true;
else if (y >= drawingArea.getHeight() - diameter)
positiveY = false;
return (calculateY());
}
private int calculateY()
{
if (positiveY)
return (y += speedValue);
else
return (y -= speedValue);
}
public static void main(String... args)
{
Runnable runnable = new Runnable()
{
public void run()
{
new BallAnimation().createAndDisplayGUI();
}
};
SwingUtilities.invokeLater(runnable);
}
}
class DrawingArea extends JComponent
{
private int x;
private int y;
private int ballDiameter;
private Color backgroundColor;
private Color foregroundColor;
public DrawingArea(int x, int y
, Color bColor, Color fColor, int dia)
{
this.x = x;
this.y = y;
ballDiameter = dia;
backgroundColor = bColor;
foregroundColor = fColor;
setBorder(BorderFactory.createLineBorder(
Color.DARK_GRAY.darker(), 5, true));
}
public void setXYColourValues(int x, int y
, Color bColor, Color fColor)
{
this.x = x;
this.y = y;
backgroundColor = bColor;
foregroundColor = fColor;
repaint();
}
public Dimension getPreferredSize()
{
return (new Dimension(500, 400));
}
public void paintComponent(Graphics g)
{
g.setColor(backgroundColor);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(foregroundColor);
g.fillOval(x, y, ballDiameter, ballDiameter);
}
}
**LATEST EDIT : **
The problem with your very nice example may be platform dependent, but I can offer a few observations:
You're not adding or removing components, so you don't need revalidate().
Because the background color is a bound property of the buttons, you don't need the subsequent calls to repaint().
You do need repaint() in your custom DrawingArea, but you may want to experiment with adding property change support, as suggested here.
Color.white can't be brighter() and Color.black can't be darker(); Color.darkGray.darker() is Color.black().
The variation below uses a Queue<Color> to simplify changing colors.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
/** #see https://stackoverflow.com/q/9849950/230513 */
public class BallAnimation {
private int x;
private int y;
private boolean positiveX;
private boolean positiveY;
private boolean isTimerRunning;
private int speedValue;
private int diameter;
private DrawingArea drawingArea;
private Timer timer;
private Queue<Color> clut = new LinkedList<Color>(Arrays.asList(
Color.BLUE.darker(),
Color.MAGENTA.darker(),
Color.BLACK,
Color.RED.darker(),
Color.PINK,
Color.CYAN.darker(),
Color.DARK_GRAY,
Color.YELLOW.darker(),
Color.GREEN.darker()));
private Color backgroundColour;
private Color foregroundColour;
private ActionListener timerAction = new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
x = getX();
y = getY();
drawingArea.setXYColourValues(x, y, backgroundColour, foregroundColour);
}
};
private JPanel buttonPanel;
private JButton startStopButton;
private JButton speedIncButton;
private JButton speedDecButton;
private JButton resetButton;
private JButton colourButton;
private JButton exitButton;
private ComponentAdapter componentAdapter = new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent ce) {
timer.restart();
startStopButton.setText("Stop");
isTimerRunning = true;
}
};
public BallAnimation() {
x = y = 0;
positiveX = positiveY = true;
speedValue = 1;
isTimerRunning = false;
diameter = 50;
backgroundColour = Color.white;
foregroundColour = clut.peek();
timer = new Timer(10, timerAction);
}
private void createAndDisplayGUI() {
JFrame frame = new JFrame("Ball Animation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
drawingArea = new DrawingArea(x, y, backgroundColour, foregroundColour, diameter);
drawingArea.addComponentListener(componentAdapter);
frame.add(makeButtonPanel(), BorderLayout.LINE_END);
frame.add(drawingArea, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JPanel makeButtonPanel() {
buttonPanel = new JPanel(new GridLayout(0, 1));
buttonPanel.setBorder(BorderFactory.createLineBorder(Color.darkGray, 5));
startStopButton = new JButton("Start");
startStopButton.setOpaque(true);
startStopButton.setForeground(Color.white);
startStopButton.setBackground(Color.green.darker());
startStopButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
if (!isTimerRunning) {
startStopButton.setText("Stop");
timer.start();
isTimerRunning = true;
} else if (isTimerRunning) {
startStopButton.setText("Start");
timer.stop();
isTimerRunning = false;
}
}
});
startStopButton.setBorder(BorderFactory.createLineBorder(Color.gray, 4));
buttonPanel.add(startStopButton);
colourButton = new JButton("Change Color");
colourButton.setOpaque(true);
colourButton.setForeground(Color.white);
colourButton.setBackground(clut.peek());
colourButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
//timer.restart();
clut.add(clut.remove());
foregroundColour = clut.peek();
drawingArea.setXYColourValues(x, y, backgroundColour, foregroundColour);
colourButton.setBackground(foregroundColour);
}
});
colourButton.setBorder(BorderFactory.createLineBorder(Color.gray, 4));
buttonPanel.add(colourButton);
exitButton = new JButton("Exit");
exitButton.setBackground(Color.red);
exitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
timer.stop();
System.exit(0);
}
});
exitButton.setBorder(BorderFactory.createLineBorder(Color.red.darker(), 4));
buttonPanel.add(exitButton);
return buttonPanel;
}
private int getX() {
if (x < 0) {
positiveX = true;
} else if (x >= drawingArea.getWidth() - diameter) {
positiveX = false;
}
return (calculateX());
}
private int calculateX() {
if (positiveX) {
return (x += speedValue);
} else {
return (x -= speedValue);
}
}
private int getY() {
if (y < 0) {
positiveY = true;
} else if (y >= drawingArea.getHeight() - diameter) {
positiveY = false;
}
return (calculateY());
}
private int calculateY() {
if (positiveY) {
return (y += speedValue);
} else {
return (y -= speedValue);
}
}
public static void main(String... args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new BallAnimation().createAndDisplayGUI();
}
};
SwingUtilities.invokeLater(runnable);
}
}
class DrawingArea extends JComponent {
private int x;
private int y;
private int ballDiameter;
private Color backgroundColor;
private Color foregroundColor;
public DrawingArea(int x, int y, Color bColor, Color fColor, int dia) {
this.x = x;
this.y = y;
ballDiameter = dia;
backgroundColor = bColor;
foregroundColor = fColor;
setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
}
public void setXYColourValues(int x, int y, Color bColor, Color fColor) {
this.x = x;
this.y = y;
backgroundColor = bColor;
foregroundColor = fColor;
repaint();
}
#Override
public Dimension getPreferredSize() {
return (new Dimension(500, 400));
}
#Override
public void paintComponent(Graphics g) {
g.setColor(backgroundColor);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(foregroundColor);
g.fillOval(x, y, ballDiameter, ballDiameter);
}
}
Seems like there is something wrong with BorderLayout.LINE_END thingy, only when I place the buttonPanel on LINE_END, I am getting undesirable results. I had tried to use only one JButton, instead of three as the latest measure, to sort out thingies. Now the problem that use to come as shown in this pic :
has been sorted out by changing the position of the JButton Panel to LINE_START or using JRE version 1.6 update 31, in the pic as below :
Here is the code used for this example :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BallAnimation
{
private int x;
private int y;
private boolean positiveX;
private boolean positiveY;
private boolean isTimerRunning;
private int speedValue;
private int diameter;
private DrawingArea drawingArea;
private Timer timer;
private int colourCounter;
Color[] colours = {
Color.BLUE.darker(),
Color.MAGENTA.darker(),
Color.BLACK.darker(),
Color.RED.darker(),
Color.PINK.darker(),
Color.CYAN.darker(),
Color.DARK_GRAY.darker(),
Color.YELLOW.darker(),
Color.GREEN.darker()
};
private Color backgroundColour;
private Color foregroundColour;
private ActionListener timerAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
x = getX();
y = getY();
drawingArea.setXYColourValues(x, y, backgroundColour
, foregroundColour);
}
};
private JPanel buttonPanel;
private JButton startStopButton;
private JButton speedIncButton;
private JButton speedDecButton;
private JButton resetButton;
private JButton colourButton;
private JButton exitButton;
private ComponentAdapter componentAdapter = new ComponentAdapter()
{
public void componentResized(ComponentEvent ce)
{
timer.restart();
}
};
public BallAnimation()
{
x = y = 0;
positiveX = positiveY = true;
speedValue = 1;
colourCounter = 0;
isTimerRunning = false;
diameter = 50;
backgroundColour = Color.WHITE.brighter();
foregroundColour = colours[colourCounter];
timer = new Timer(10, timerAction);
}
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Ball Animation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
drawingArea = new DrawingArea(x, y
, backgroundColour, foregroundColour, diameter);
drawingArea.addComponentListener(componentAdapter);
frame.add(makeButtonPanel(), BorderLayout.LINE_START);
frame.add(drawingArea, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JPanel makeButtonPanel()
{
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(0, 1));
buttonPanel.setBorder(BorderFactory.createLineBorder(
Color.DARK_GRAY, 5, true));
colourButton = new JButton("BALL COLOUR");
colourButton.setOpaque(true);
colourButton.setBackground(colours[colourCounter]);
colourButton.setForeground(Color.WHITE);
colourButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("COLOUR JButton Clicked!");
if (timer.isRunning())
timer.stop();
colourCounter++;
if (colourCounter == 9)
colourCounter = 0;
foregroundColour = colours[colourCounter];
drawingArea.setXYColourValues(x, y, backgroundColour
, foregroundColour);
colourButton.setBackground(foregroundColour);
if (!timer.isRunning())
timer.start();
}
});
colourButton.setBorder(BorderFactory.createLineBorder(
Color.WHITE, 2, true));
buttonPanel.add(colourButton);
return buttonPanel;
}
private int getX()
{
if (x < 0)
positiveX = true;
else if (x >= drawingArea.getWidth() - diameter)
positiveX = false;
return (calculateX());
}
private int calculateX()
{
if (positiveX)
return (x += speedValue);
else
return (x -= speedValue);
}
private int getY()
{
if (y < 0)
positiveY = true;
else if (y >= drawingArea.getHeight() - diameter)
positiveY = false;
return (calculateY());
}
private int calculateY()
{
if (positiveY)
return (y += speedValue);
else
return (y -= speedValue);
}
public static void main(String... args)
{
Runnable runnable = new Runnable()
{
public void run()
{
new BallAnimation().createAndDisplayGUI();
}
};
SwingUtilities.invokeLater(runnable);
}
}
class DrawingArea extends JComponent
{
private int x;
private int y;
private int ballDiameter;
private Color backgroundColor;
private Color foregroundColor;
public DrawingArea(int x, int y
, Color bColor, Color fColor, int dia)
{
this.x = x;
this.y = y;
ballDiameter = dia;
backgroundColor = bColor;
foregroundColor = fColor;
setBorder(BorderFactory.createLineBorder(
Color.DARK_GRAY.darker(), 5, true));
}
public void setXYColourValues(int x, int y
, Color bColor, Color fColor)
{
this.x = x;
this.y = y;
backgroundColor = bColor;
foregroundColor = fColor;
repaint();
}
public Dimension getPreferredSize()
{
return (new Dimension(500, 400));
}
public void paintComponent(Graphics g)
{
g.setColor(backgroundColor);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(foregroundColor);
g.fillOval(x, y, ballDiameter, ballDiameter);
}
}
maybe will help you with two parts of, I think that Graphics/2D is designated to use Swing Timer exclusively,
I am unsure whether I found a solution for your system, but adjusting the code to
colourButton = new JButton( "BALL COLOUR" );
colourButton.setOpaque( true );
colourButton.setBackground( colours[ colourCounter ] );
colourButton.setForeground( Color.WHITE );
works on my system (OS X with Java 1.7). Note the setOpaque call, which is needed so that the setBackground call has any effect as stated in the javadoc of that method:
Sets the background color of this component. The background color is used only if the component is opaque
On OS X, without that setOpaque call your code does not even work before a resize

Problem with extending class JLabel to add to it property dragging

I have class JLabelExtended, which extends class javax.swing.JLabel.
I extend it, because I want to add property dragging using mouse.
Here is my code:
public class JLabelExtended extends JLabel {
private MouseMotionAdapter mouseMotionAdapter;
private JLabelExtended jLabelExtended;
public LabelEasy(String text) {
super(text);
jLabelExtended = this;
mouseMotionAdapter = new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
System.out.println(e.getX() + " : " + e.getY());
jLabelExtended.setLocation(e.getX(), e.getY()
);
}
};
jLabelExtended.addMouseMotionListener(mouseMotionAdapter);
}
}
This is console part after label dragged:
163 : 163
144 : -87
163 : 162
144 : -88
163 : 161
144 : -89
I have several questions:
Why e.getY() takes negative results?
When I drag my label there are appeares copy of label which drags near my label. How can I fix it?
When I drag my label, it drags very slowly.For example: when I move my cursor on 10 points my label moves only on 5 point. How can I fix it?
Thanks in advance
Here are else one way to extend JLabel:
public class LabelEasy extends JLabel {
private MouseAdapter moveMouseAdapter;
private MouseMotionAdapter mouseMotionAdapter;
private LabelEasy jLabelExtended;
private int xAdjustment, yAdjustment;
Boolean count = false;
public LabelEasy(String text) {
super(text);
jLabelExtended = this;
moveMouseAdapter = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == 1) {
xAdjustment = e.getX();
yAdjustment = e.getY();
}
}
};
mouseMotionAdapter = new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
if (count) {
System.out.println(e.getX() + " : " + e.getY());
jLabelExtended.setLocation(xAdjustment + e.getX(), yAdjustment + e.getY());
count = false;
} else {
count = true;
}
;
}
};
jLabelExtended.addMouseMotionListener(mouseMotionAdapter);
jLabelExtended.addMouseListener(moveMouseAdapter);
}
}
But it works like previous variant.
I think you're doing it wrong. The MouseMotionListener is added to the JLabel and its location is relative to the JLabel, not the Container which holds the JLabel, so the information is useless to help you drag it. You may wish to use a MouseAdapter and add it both as a MouseListener and a MouseMotionListener. On mousePressed, get the location of the JLabel and the mouse relative to the screen and then use that for your dragging on mouseDragged. Myself, I wouldn't extend JLabel to do this but would rather just use a regular JLabel, but that's my preference.
Edit: it worked better for me when I dealt with the mouse's position relative to the screen (by calling getLocationOnScreen) and the JLabel's position relative to its Container (by calling getLocation). For e.g.,
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class DragLabelEg {
private static final String[] LABEL_STRINGS = { "Do", "Re", "Me", "Fa",
"So", "La", "Ti" };
private static final int HEIGHT = 400;
private static final int WIDTH = 600;
private static final Dimension MAIN_PANEL_SIZE = new Dimension(WIDTH,
HEIGHT);
private static final int LBL_WIDTH = 60;
private static final int LBL_HEIGHT = 40;
private static final Dimension LABEL_SIZE = new Dimension(LBL_WIDTH,
LBL_HEIGHT);
private JPanel mainPanel = new JPanel();
private Random random = new Random();
public DragLabelEg() {
mainPanel.setPreferredSize(MAIN_PANEL_SIZE);
mainPanel.setLayout(null);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
for (int i = 0; i < LABEL_STRINGS.length; i++) {
JLabel label = new JLabel(LABEL_STRINGS[i], SwingConstants.CENTER);
label.setSize(LABEL_SIZE);
label.setOpaque(true);
label.setLocation(random.nextInt(WIDTH - LBL_WIDTH),
random.nextInt(HEIGHT - LBL_HEIGHT));
label.setBackground(new Color(150 + random.nextInt(105),
150 + random.nextInt(105), 150 + random.nextInt(105)));
label.addMouseListener(myMouseAdapter);
label.addMouseMotionListener(myMouseAdapter);
mainPanel.add(label);
}
}
public JComponent getMainPanel() {
return mainPanel;
}
private class MyMouseAdapter extends MouseAdapter {
private Point initLabelLocation = null;
private Point initMouseLocationOnScreen = null;
#Override
public void mousePressed(MouseEvent e) {
JLabel label = (JLabel)e.getSource();
// get label's initial location relative to its container
initLabelLocation = label.getLocation();
// get Mouse's initial location relative to the screen
initMouseLocationOnScreen = e.getLocationOnScreen();
}
#Override
public void mouseReleased(MouseEvent e) {
initLabelLocation = null;
initMouseLocationOnScreen = null;
}
#Override
public void mouseDragged(MouseEvent e) {
// if not dragging a JLabel
if (initLabelLocation == null || initMouseLocationOnScreen == null) {
return;
}
JLabel label = (JLabel)e.getSource();
// get mouse's new location relative to the screen
Point mouseLocation = e.getLocationOnScreen();
// and see how this differs from the initial location.
int deltaX = mouseLocation.x - initMouseLocationOnScreen.x;
int deltaY = mouseLocation.y - initMouseLocationOnScreen.y;
// change label's position by the same difference, the "delta" vector
int labelX = initLabelLocation.x + deltaX;
int labelY = initLabelLocation.y + deltaY;
label.setLocation(labelX, labelY);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createGui();
}
});
}
private static void createGui() {
JFrame frame = new JFrame("App");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DragLabelEg().getMainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

JApplet drawing shapes

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class ShapeApplet extends JApplet{
//contains all shapes that created
private ShapeContainer shapeContaiter = new ShapeContainer();
//main window panels
private Panel leftPanel = new Panel();
private Panel rightPanel = new Panel();
private Panel buttomPanel = new Panel();
//the panel inside right panel
private Panel shapesPanel = new Panel();
private String [] shapeNames = {"Cicle","Rect","Polygon","Line","Cylinder"};
private Choice shapeChoice = new Choice();
//defines the colors to choose from
JColorChooser colorChooser = new JColorChooser(Color.BLACK);
//item that will be use for painting
private Shape shapeToDraw;
//creating shapesButtons
ImageIcon iconCircle = new ImageIcon("circle.png", "Circle");
JButton buttonCircle = new JButton(iconCircle);
ImageIcon iconLine = new ImageIcon("line.png","Line");
JButton buttonLine = new JButton(iconLine);
ImageIcon iconRect = new ImageIcon("rect.png","Line");
JButton buttonRect = new JButton(iconRect);
ImageIcon iconPolygon = new ImageIcon("polygon.png","Line");
JButton buttonPolygon = new JButton(iconPolygon);
//creating the other tool buttons
JButton buttonClear = new JButton("Undo");
Checkbox checkBoxIsTheShapeFilled = new Checkbox("Filled");
//defines the new canvas
PaintingCanvas paintingCanvas = new PaintingCanvas();
//defines the class for buttons actions
ButtonAction buttonAction = new ButtonAction();
//save the shape that selected
private int currentTool = 4;
//integers to keep the mouse location
private int xPoint1, xPoint2 = 0, yPoint1,yPoint2 = 0;
#Override
public void init() {
System.out.println("points" + xPoint1+yPoint2);
//setting location , size and properties
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int screenWidth = (int) dim.getWidth();
int screenHeight = (int) dim.getHeight();
this.setSize(screenWidth,screenHeight-400);
//setting layout
this.setLayout(new BorderLayout());
//creating the choices for shapes
for(int i = 0 ; i < shapeNames.length ; i++ )
shapeChoice.add(shapeNames[i]);
//defines left Panel and right Panel properties
this.leftPanel.setBackground(Color.LIGHT_GRAY);
this.leftPanel.setLayout(new GridLayout(5, 0));
this.rightPanel.setBackground(Color.LIGHT_GRAY);
this.rightPanel.setLayout(new BorderLayout());
//adding items to the right panel
this.rightPanel.add(colorChooser, BorderLayout.NORTH);
//setting the shapes panel
this.shapesPanel.setLayout(new GridLayout(3,3));
this.shapesPanel.add(buttonCircle);
this.shapesPanel.add(buttonLine);
this.shapesPanel.add(buttonRect);
this.shapesPanel.add(buttonPolygon);
this.shapesPanel.add(checkBoxIsTheShapeFilled);
//adding the shapes panel to the right Panel
this.rightPanel.add(shapesPanel, BorderLayout.SOUTH);
//adding items to the left panel
this.leftPanel.add(buttonClear);
//defines the location of each item on the main window
this.add(leftPanel, BorderLayout.WEST);
this.add(rightPanel, BorderLayout.EAST);
this.add(buttomPanel,BorderLayout.SOUTH);
this.add(paintingCanvas,BorderLayout.CENTER);
//setting button actions
this.buttonCircle.addActionListener(buttonAction);
this.buttonLine.addActionListener(buttonAction);
this.buttonPolygon.addActionListener(buttonAction);
this.buttonRect.addActionListener(buttonAction);
this.buttonClear.addActionListener(buttonAction);
}
#Override
public void start() {
super.start();
}
#Override
public void stop() {
super.stop();
}
#Override
public void destroy() {
super.destroy();
}
public class PaintingCanvas extends Canvas implements MouseListener, MouseMotionListener
{
public PaintingCanvas()
{
addMouseListener(this);
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
xPoint1 = e.getX();
yPoint1 = e.getY();
xPoint2 = e.getX();
yPoint2 = e.getY();
}//end of mousePressed
#Override
public void mouseReleased(MouseEvent e) {
xPoint2 = e.getX();
yPoint2 = e.getY();
shapeContaiter.add(shapeToDraw);
System.out.println("Release");
repaint();
}
#Override
public void update(Graphics g) {
paint(g);
}//end of update
#Override
public void paint(Graphics g) {
switch (currentTool)
{
case 0:
//System.out.println("Circle pointsxy: " + xPoint1+","+yPoint1);
//System.out.println("Circle pointsx2y2: " + xPoint2+","+yPoint2);
shapeToDraw = new Circle(xPoint1 , yPoint1, new Point(xPoint2, yPoint2),colorChooser.getColor() , checkBoxIsTheShapeFilled.getState());
//System.out.println( "Circle pointsxy: " + shapeToDraw.getLocation());
shapeToDraw.draw(g);
break;
case 1:
shapeToDraw = new Line(xPoint1, yPoint1, new Point(xPoint2,yPoint2), colorChooser.getColor(), checkBoxIsTheShapeFilled.getState());
shapeToDraw.draw(g);
break;
case 2:
break;
case 3:
shapeToDraw = new Rect(xPoint1, yPoint1, new Point(xPoint2, yPoint2), colorChooser.getColor(), checkBoxIsTheShapeFilled.getState());
shapeToDraw.draw(g);
break;
case 4:
break;
default:
}//end of switch
System.out.println("Size of shapeContianer: "+shapeContaiter.size());
System.out.println("pointsxy: " + xPoint1+","+yPoint1);
System.out.println("pointsx2y2: " + xPoint2+","+yPoint2);
}//end of paint
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
}//end of canvas
public class ButtonAction implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e) {
if ( e.getSource() == buttonCircle)
currentTool = 0;
else if ( e.getSource() == buttonLine)
currentTool = 1;
else if ( e.getSource() == buttonPolygon)
currentTool = 2;
else if ( e.getSource() == buttonRect)
currentTool = 3;
else if (e.getSource() == buttonClear){
currentTool=4;
if(shapeContaiter.isEmpty()) JOptionPane.showMessageDialog(buttonClear, "Nothing to delete");
else {
Graphics g = paintingCanvas.getGraphics();
shapeContaiter.get(shapeContaiter.size()-1).setColor(Color.WHITE);
shapeContaiter.get(shapeContaiter.size()-1).draw(g);
shapeContaiter.remove(shapeContaiter.size()-1);
System.out.println("Size of shapeContianer: "+shapeContaiter.size());
}
}
}//end of action performed
}//end of ButtonClicked
}
I'm trying to create an Undo button that will erase the last shape from the shapeContainer array and from the canvas.
i can put the finger on the problem but when i am trying to erase on of the shapes it erase the shape that i painted before the current shape.
i created Circle,Rect,Polygon,Line classes that after heavy checking seems to be ok.
What is the ShapeContainer class? Instead why don't you just use a Stack http://download.oracle.com/javase/6/docs/api/java/util/Stack.html
Why the use of awt Panel and Canvas? I would suggest just using JPanel and JComponents instead.
Your Button listener is looking very scary with all the if and else statements. Instead use a separate listener for each button. This will simplify the logic which in turn will prevent bugs in your code and make it easier to make changes. (The Action class in the API might be useful to you in this case).

Categories