I'm working on a game currently using slick2d + lwjgl and I am trying to implement listeners for the gui components. I was wondering on how to do that since I am currently stumped. I was thinking I could do something like this
GuiComponent class....
public void addListener(MouseAdapter e){
// Stuck on this part
}
Than implement it into a menu like this
gComponent.addListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e){
// listener logic
}
}
I don't know how to actually trigger the method mouseClicked inside the addListener method, because when i ran it like this nothing happened unless I am delusional. Anyway, any help does help even if you just send me to a javadoc or something like that. Thanks guys & merry christmas :)
EDIT:
GuiComponent class
package com.connorbrezinsky.turbulent.gui;
import java.awt.event.MouseAdapter;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
public class GuiComponent {
int x, y, width, height;
Color color;
Image i;
public GuiComponent(Gui gui, int _x, int _y, int w, int h, Color c) {
gui.components.add(this);
x = _x;
y = _y;
width = w;
height = h;
color = c;
}
public GuiComponent(int _x, int _y, int w, int h, Color c) {
x = _x;
y = _y;
width = w;
height = h;
color = c;
}
public GuiComponent(Gui gui, int _x, int _y, int w, int h) {
gui.components.add(this);
x = _x;
y = _y;
width = w;
height = h;
color = Color.white;
}
public GuiComponent(int _x, int _y, int w, int h) {
x = _x;
y = _y;
width = w;
height = h;
color = Color.white;
}
public void addText(String s){
}
public void addSprite(Image s){
i = s;
}
public void render(Graphics g){
if(i == null) {
g.setColor(color);
g.fillRect(x, y, width, height);
}else{
i.draw(x,y,width,height);
}
}
public void addListener(MouseAdapter e){
// stuck here
}
}
Example in menu class
GuiComponent guiTest = new GuiComponent(20, 20, 50, 10);
public void update(GameContainer arg0, StateBasedGame arg1, int arg2) throws SlickException{
guiTest.addListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e){
System.out.println("click");
}
});
}
Slick2D offers several components, I don't know if you've seen them. Maybe can you use the AbstractComponent, by inherits from it to do what you expect. It seems to provide the addListeners method that you want to implement by yourself. It say simplify you own code.
Then to add a listener, you can use your gameContainer. Through gc.getInput().addListener().
With your code it would be something like :
GuiComponent guiTest = new GuiComponent(20, 20, 50, 10);
public void update(GameContainer arg0, StateBasedGame arg1, int arg2) throws SlickException{
arg0.getInput().addListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e){
System.out.println("click");
}
});
}
Related
I have a java application that i have been coding, it is an application that can allow me to draw shapes like a rectangle. My application can draw shapes but I cannot save them because when i try to draw a new shape and I click somewhere else the previously drawn shape disappears and is replaced by a new one. I tried array list to save my shapes but it does not work.
here is my code:
public class Toile extends JPanel {
Vector<Forme> forme = new Vector<Forme>();
private Color couleur;
private int x;
private int y;
private int x2;
private int y2;
private Oval oval;
private Rectangl rect;
public Toile(){
initComponents();
}
public void initComponents(){
addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent evt) {
formMousePressed(evt); }
public void mouseReleased(java.awt.event.MouseEvent evt) {
formMouseReleased(evt); } });
addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseDragged(java.awt.event.MouseEvent evt) {
formMouseDragged(evt); } });
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(couleur);
drawfillRect(g, x, y, x2, y2);
}
public void setStartPoint(int x, int y) {
this.x = x;
this.y = y;
}
public void setEndPoint(int x, int y) {
x2 = (x);
y2 = (y);
}
public void drawfillRect(Graphics g, int x, int y, int x2, int y2) {
int px = Math.min(x,x2);
int py = Math.min(y,y2);
int pw=Math.abs(x-x2);
int ph=Math.abs(y-y2);
//g.fillRect(px, py, pw, ph);
Rectangl rect = new Rectangl(px,y,x2,py,pw,ph,couleur,true);
rect.dessinerfrect(g);
forme.add(rect);
}
}
private void formMousePressed(java.awt.event.MouseEvent evt) {
setStartPoint(evt.getX(), evt.getY());
repaint();
}
private void formMouseReleased(java.awt.event.MouseEvent evt) {{
setEndPoint(evt.getX(), evt.getY());
repaint();
//dessiner(this.getGraphics());
}
}
private void formMouseDragged(java.awt.event.MouseEvent evt){{
setEndPoint(evt.getX(), evt.getY());
repaint();
//dessiner(this.getGraphics());
}
}
As you can see this is the class that does the drawings, the rectangle that will be drawn is an object from a class that I created and this class is a subclass of a super class Forme. As I said previously, the application can draw shapes but the shapes that are drawn are not saved. Also I removed the getters and setters from my post because I wanted to keep only what was essential and I wanted to make my post clearer.
Here is the class Rectangl:
public class Rectangl extends Forme {
private int largeur;
private int hauteur;
private Rectangle rectangle;
public Rectangl(int x1,int y1, int x2 ,int y2,int largeur,int hauteur,Color couleur,Boolean plein){
super(x1,y1,x2,y2,couleur,plein);
this.largeur = largeur;
this.hauteur = hauteur;
}
public void dessinerrect(Graphics g){
g.setColor(couleur);
g.drawRect((int)point1.getX(), (int)point2.getY(), largeur, hauteur);
}
public void dessinerfrect(Graphics g){
g.setColor(couleur);
g.fillRect((int)point1.getX(), (int)point2.getY(), largeur, hauteur);
}
}
You'll need to implement a display list. This is a data structure that represents all the items currently in the drawing. The component painter just traverses the list and draws each item (usually after erasing the screen so that deleted objects don't appear in the new drawing). It also optionally draws the "rubberband cursor" if the mouse has been pressed and not yet released. The mouse actions (usually releasing the mouse button just modify status variables including display list (add, select, delete, etc.) and then repaint the drawing surface so the component painter is called.
A Java ArrayList is a reasonable way to implement a simple display list. The items themselves are a classical use of interfaces and/or inheritance:
interface DisplayListItem {
void draw(Graphics g);
}
abstract class AbstractRectangle implements DisplayListItem {
protected int x, y, w, h;
protected Color color;
Rectangle(int x, int y, int w, int h, Color color) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
}
}
class Rectangle extends AbstractRectangle {
Rectangle(int x, int y, int w, int h, Color color) {
super(x, y, w, h, color);
}
#Override
void draw(Graphic g) {
g.setColor(color);
g.drawRect(x, y, w, h);
}
}
class FilledRectangle extends AbstractRectangle {
FilledRectangle(int x, int y, int w, int h, Color color) {
super(x, y, w, h, color);
}
#Override
void draw(Graphic g) {
g.setColor(color);
g.fillRect(x, y, w, h);
}
}
private List<DisplayListItem> displayList = new ArrayList<>();
private int xPress, yPress, xDrag, yDrag;
private boolean mousePressed = false;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (DisplayListItem item : displayList) {
item.draw(g);
}
if (mousePressed) {
// Draw the click-and-drag cursor.
g.setColor(Color.RED);
g.drawRect(xPress, yPress, xDrag - xPress, yDrag - yPress);
}
}
private void formMousePressed(MouseEvent evt) {
xPress = evt.getX();
yPress = evt.getY();
mousePressed = true;
}
private void formMouseDragged(MouseEvent evt) {
if (!mousePressed) return;
xDrag = evt.getX();
yDrag = evt.getY();
repaint();
}
private void formMouseReleased(MouseEvent evt) {
if (!mousePressed) return;
xDrag = evt.getX();
yDrag = evt.getY();
// Adding a rectangle to the display list makes it permanent.
displayList.add(new Rectangle(xPress, yPress, xDrag - xPress, yDrag - yPress));
mousePressed = false;
repaint();
}
Caveat: This is uncompiled, untested code. Use at your own risk.
Swing has the useful Shape interface which has been implemented into several concrete classes that could serve your purpose well.
There are several different Shapes (Ellipse2D, Rectangle2D, RoundRectangle2D) are stored in an ArrayList of Shape objects, and then these are drawn within the JPanel's paintComponent method after first casting the Graphics object into a Graphics2D.
I'm somewhat new to slick 2d and in my project I was playing around with things like buttons. I would draw an image and listen for a click at the coordinates and it ended up being like 50 lines long which seemed pretty unnecessary.
But then I saw this thread Slick 2d Button Listener; sadly it was dead so didn't help. What the guy was working on seemed really efficient but i have so far been unable to find any information on how to use it. If anyone can explain to me or show me how to use it that would be awesome.
I implemented a button like this in Slick 2D
protected Shape hitbox;
private boolean inside = false;
public void render(GameContainer container, Graphics g) {
.
.//drawing the picture of the button
.
if(inside && container.getInput().isMousePressed(Input.MOUSE_LEFT_BUTTON)){
//someone clicked the button
}
}
public void init(GameContainer container) {
//setting a hitbox up to recognize when the mouse is over the picture/button
hitbox = new Rectangle(/*dimensions of your picture*/);
}
public void update(GameContainer container, int delta) {
//this code finds out if the mouse is over the button
int mouseX = container.getInput().getMouseX();
int mouseY = container.getInput().getMouseY();
inside = hitbox.contains(mouseX, mouseY))
}
After some testing I found out how i could do this, in the button class I wrote :
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.gui.AbstractComponent;
import org.newdawn.slick.gui.GUIContext;
public class Button extends AbstractComponent{
protected int width;
protected int height;
protected int x;
protected int y;
protected int mouseX;
protected int mouseY;
protected boolean pressed;
protected Shape hitbox;
protected boolean over;
protected String text;
public Button(GUIContext container, int x, int y, int width, int height, String text) {
super(container);
setLocation(x, y);
this.width = width;
this.height = height;
this.text = text;
hitbox = new Rectangle(x, y, width, height);
}
#Override
public int getHeight() {
return height;
}
#Override
public int getWidth() {
return width;
}
#Override
public int getX() {
return x;
}
#Override
public int getY() {
return y;
}
public boolean isPressed() {
return pressed;
}
public void update(GUIContext container) {
mouseX = container.getInput().getMouseX();
mouseY = container.getInput().getMouseY();
over = hitbox.contains(mouseX, mouseY);
if (over && container.getInput().isMousePressed(Input.MOUSE_LEFT_BUTTON)) {
pressed = true;
}else{
pressed = false;
}
}
#Override
public void render(GUIContext container, Graphics g) throws SlickException {
g.setColor(Color.blue);
g.fillRect(x, y, width, height);
g.setColor(Color.black);
g.drawString(text, x + width/2, y + height/2);
}
#Override
public void setLocation(int x, int y) {
this.x = x;
this.y = y;
}
and to use it in my frame i simply write:
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
public class Menu extends BasicGameState{
public static final int ID = 1;
private StateBasedGame game;
private Button button;
public int getID() {
return ID;
}
#Override
public void init(GameContainer container, StateBasedGame game) throws SlickException {
this.game = game;
button = new Button(container, 1280/2, 720/2, 200, 200, "Works");
}
#Override
public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
button.render(container, g);
}
#Override
public void update(GameContainer container, StateBasedGame game, int delta) {
button.update(container);
if (button.isPressed()) {
System.out.println("Works");
}
}
}
I am working on a game.I want to add images to the applet but they do not appear there until I resize or minimize the applet.I do not know whether my image observer is wrong or not.
The images are in right path.Their in build and class folder with correct spelling. What is wrong with my code?
any help would be much appreciated.
public class game extends JApplet implements KeyListener, Runnable {
ScreenDir sd;
Image ball;
Image flower;
public void init() {
sd = new ScreenDir(this);
ball = getImage(getCodeBase(), "ball.jpg");
ballb = new Ball(50, 50, 30, 40, Color.red, ball, sd);
sd.add(ball);
flower = getImage(getCodeBase(), "flower.gif");
//class Flower is just defined like class Ball
flowerf = new Flower(60, 100, 30, 30, Color.green, flower, sd);
sd.add(flower);
}
public void paint(Graphics g) {
sd.draw(g);
}
//These are for moving the ball
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(15);
} catch (InterruptedException ex) {}}}
public class ScreenDir {
ArrayList<Object> olist;
JApplet parent;
public ScreenDir(JApplet parent) {
this.parent = parent;
olist = new ArrayList<>();
}
public void add(Object o) {
olist.add(o);
}
Image Img;
Graphics oG;
Img = parent.createImage(parent.getWidth(), parent.getHeight());
oG = offImg.getGraphics();
for(int i = 0;i<olist.size ();i++){
olist.get(i).draw(offG);
}
g.drawImage (Img,0, 0, parent);
}
public class Ball extends Object {
ScreenDir sd;
public ball(int x, int y, int w, int h, Color c, Image pi, ScreenDir sd) {
{
this.sd = sd;
}
public void draw(Graphics g) {
g.drawImage(pi, x, y, w, h, null);
}
public abstract class Object {
int x, y, w, h;
Color c;
Image pi;
public Object(int x, int y, int w, int h, Color c, Image pi) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.c = c;
this.pi = pi;
}
public abstract void draw(Graphics g) {
}
Applets load images asynchronously, so it is likely the images are not fully loaded before the applet goes to paint. But every Java component worth mentioning implements an ImageObserver that means it will get updates on image loading. So to fix the problem, change this:
g.drawImage(pi, x, y, w, h, null);
To this:
g.drawImage(pi, x, y, w, h, this);
Update
I mistakenly thought the drawImage method was part of the JApplet (which is an ImageObserver). You might simply change the method declaration & painting line to:
public void draw(Graphics g, ImageObserver io) {
g.drawImage(pi, x, y, w, h, io);
}
Then to call it, change:
sd.draw(g);
To:
sd.draw(g, this);
I have some issues with my paint program in Java.
I have a JComboBox where I can choose to draw either a rectangle or by freehand. The objects are added to an ArrayList. I want to be able to switch between drawing a rectangle and by free hand, and then back to drawing a rectangle, and then by free hand... and so on.
If I do that as the code looks like now, it first draws rectangles fine and then when I switch to free hand it draws lines fine, but then when I switch back to rectangles it still draws lines (or sometimes lines together with weird looking rectangles). The more I switch the weirder it gets.
Can anyone see what is wrong with the code, because I can't?
public abstract class Draw {
public int startX, startY, endX, endY, width, height, w, h;
public String color = "Black";
public Draw(int startX, int startY, int width, int height) {
this.startX = startX;
this.startY = startY;
this.width = width;
this.height = height;
}
public abstract void draw(Graphics2D g);
public int getX() {
return startX;
}
public void setX(int startX) {
this.startX = startX;
}
public int getY() {
return startY;
}
public void setY(int startY) {
this.startY = startY;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public void setColor(String color) {
this.color = color;
}
}
public class Rectangle extends Draw {
public Rectangle(int x, int y, int width, int height) {
super(x, y, width, height);
}
#Override
public void draw(Graphics2D g2) {
g2.drawRect(getX(), getY(), getWidth(), getHeight());
}
}
public class FreeHand extends Draw {
public FreeHand(int x, int y, int width, int height) {
super(x, y, width, height);
}
#Override
public void draw(Graphics2D g2) {
g2.drawLine(getX(), getY(), getWidth(), getHeight());
}
}
public class PaintProgram extends JFrame implements ActionListener {
public ArrayList<Draw> shapeList = new ArrayList<>();
int startX, startY, endX, endY, w, h;
private JPanel topPanel;
private JPanel bottomPanel;
private JPanel leftPanel;
private JPanel rightPanel;
private JComboBox comboBox;
private final String[] boxOptions = new String[] {"Rectangle", "Freehand"};
Container cp = getContentPane();
private int count = 0;
public JavaApplication30(String title) {
super(title);
this.setLayout(new BorderLayout());
this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setSize(840, 500);
this.initComponents();
this.setVisible(true);
}
private void initComponents() {
cp.setBackground(Color.WHITE);
comboBox = new JComboBox(boxOptions);
topPanel = new JPanel();
bottomPanel = new JPanel(new GridLayout(1,2));
rightPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
leftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
comboBox.setSelectedIndex(0);
comboBox.addActionListener(this);
topPanel.setPreferredSize(new Dimension(0,40));
bottomPanel.setPreferredSize(new Dimension(0,30));
bottomPanel.setBackground(Color.LIGHT_GRAY);
topPanel.add(comboBox);
bottomPanel.add(leftPanel);
bottomPanel.add(rightPanel);
this.add(topPanel, BorderLayout.PAGE_START);
this.add(bottomPanel, BorderLayout.PAGE_END);
}
#Override
public void paint(Graphics g) {
if(count == 0) {
cp.repaint();
}
Graphics2D g2 = (Graphics2D) g;
for (Draw d : shapeList) {
d.draw(g2);
}
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(1));
if (startX != 0 && startY != 0 && endX != 0 && endY != 0) {
int width = Math.abs(startX - endX);
int height = Math.abs(startY - endY);
int minX = Math.min(startX, endX);
int minY = Math.min(startY, endY);
Rectangle r = new Rectangle(minX, minY, width, height);
g2.setPaint(Color.WHITE);
g2.fillRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
r.setColor(pickedColor);
r.draw(g2);
}
}
#Override
public void actionPerformed(ActionEvent e) {
count++;
if (e.getSource().equals(comboBox)) {
JComboBox cb = (JComboBox)e.getSource();
if (cb.getSelectedItem().equals("Rectangle")) {
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
startX = e.getX();
startY = e.getY();
endX = startX;
endY = startY;
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
endX = e.getX();
endY = e.getY();
int width = Math.abs(startX - endX);
int height = Math.abs(startY - endY);
int minX = Math.min(startX, endX);
int minY = Math.min(startY, endY);
Rectangle r = new Rectangle(minX, minY, width, height);
shapeList.add(r);
r.setColor(pickedColor);
startX = 0;
startY = 0;
endX = 0;
endY = 0;
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
endX = e.getX();
endY = e.getY();
repaint();
}
});
}
else if (cb.getSelectedItem().equals("Freehand")) {
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
startX = e.getX();
startY = e.getY();
addCoordinate(startX, startY);
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
Graphics g = getGraphics();
Graphics2D g2 = (Graphics2D) g;
FreeHand fh = new FreeHand(startX, startY, e.getX(), e.getY());
shapeList.add(fh);
fh.setColor(pickedColor);
fh.draw(g2);
startX = e.getX();
startY = e.getY();
}
});
}
}
}
public static void main(String args[]) {
new PaintProgram("Paint");
}
}
You add MouseListeners but you do not remove them. Every time you choose something in the combobox, a new listener is added. So when you draw something every listener is applied and weird stuff will happen.
You should remove the previous MouseListener before adding a new one. You might have to remember it in an instance variable.
Alternatively, you can add all listeners at the start, but check the value of the combobox inside the listener. If the value does not correspond to what the listener is for, it should do nothing.
EDIT: Here is how you can remove all listeners
for (MouseListener listener : this.getMouseListeners()) {
this.removeMouseListener(listener);
}
for (MouseMotionListener listener : this.getMouseMotionListeners()) {
this.removeMouseMotionListener(listener);
}
Put this code in before you add the new listeners in the actionPerformed() method
As was stated here and here previously, do not add MouseListeners within your ActionListener, instead, create a single MosueListener and determine what you want to do based on the currently selected item.
Basically, you keep adding a new MouseListener each time actionPerformed is called...they are accumulating...
A solution would be to use a single MouseListener and a factory of some kind...
Start by defining the factory interface...
public interface DrawFactory {
public Draw createDrawing(int x, int y, int width, int height, Color color);
public void addPoint(Draw draw, int x, int y);
}
Create a implementation of the factory for each type of shape you want to draw...
public class RectangleFactory implements DrawFactory {
#Override
public Draw createDrawing(int x, int y, int width, int height, Color color) {
return new Rectangle(x, y, width, height);
}
#Override
public void addPoint(Draw draw, int x, int y) {
// Does nothing...
}
#Override
public boolean isMutable() {
return false;
}
#Override
public String getName() {
return "Rectangle";
}
#Override
public String toString() {
return getName();
}
}
public class FreeHandFactory implements DrawFactory {
#Override
public Draw createDrawing(int x, int y, int width, int height, Color color) {
return new FreeHand(x, y, width, height);
}
#Override
public void addPoint(Draw draw, int x, int y) {
if (draw instanceof FreeHand) {
FreeHand fh = (FreeHand)draw;
//fh.addPoint(x, y);
}
}
#Override
public boolean isMutable() {
return true;
}
#Override
public String getName() {
return "Free Hand";
}
#Override
public String toString() {
return getName();
}
}
Next, create a custom component that extends from JPanel which will act as the primary drawing surface, this will be repsonsible for monitoring the MouseLstener and painting the Draw instances, as was mentioned here
public class DrawSurface extends JPanel {
private DrawFactory factory;
private Draw currentDraw;
private List<Draw> shapeList = new ArrayList<>();
private Color drawColor;
public DrawSurface() {
shapeList = new ArrayList<>(25);
MouseAdapter ma = new MouseAdapter() {
private Point pressPoint;
#Override
public void mousePressed(MouseEvent e) {
pressPoint = e.getPoint();
}
#Override
public void mouseReleased(MouseEvent e) {
DrawFactory factory = getDrawFactory();
if (factory != null) {
Point p = e.getPoint();
if (factory.isMutable() && currentDraw != null) {
factory.addPoint(currentDraw, p.x, p.y);
} else {
int x = Math.min(p.x, pressPoint.x);
int y = Math.min(p.y, pressPoint.y);
int width = Math.abs(p.x - pressPoint.x);
int height = Math.abs(p.y - pressPoint.y);
Draw draw = factory.createDrawing(x, y, width, height, getDrawColor());
shapeList.add(draw);
if (factory.isMutable()) {
currentDraw = draw;
}
}
}
}
};
}
public DrawFactory getDrawFactory() {
return factory;
}
public void setDrawFactory(DrawFactory factory) {
this.factory = factory;
currentDraw = null;
}
public Color getDrawColor() {
return drawColor;
}
public void setDrawColor(Color drawColor) {
this.drawColor = drawColor;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Draw draw : shapeList) {
draw.draw(g2d);
}
g2d.dispose();
}
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
Next, change your boxOptions from String to DrawFactory, this will make it easier to determine which factory you should use. Don't forget to add a reference to the DrawSurface
private final DrawFactory[] boxOptions = new DrawFactory[]{new RectangleFactory(), new FreeHandFactory()};
private DrawSurface drawSurface;
In your initComponents create a new instance of DrawSurface and add it to your frame...
private void initComponents() {
//...
drawSurface = new DrawSurface();
this.add(drawSurface);
}
Change your actionPerformed method to look more like...
#Override
public void actionPerformed(ActionEvent e) {
count++;
drawSurface.setDrawFactory((DrawFactory)comboBox.getSelectedItem());
}
Not sure how you are determining the current color as you example code is incomplete, but basically, you want to set the drawColor of the DrawSurface similarly.
Get rid of the paint method in the PaintProgram as you shouldn't be overriding the paint method of top level containers, which you've been advised against at least once, if not twice.
The point of all this is simple, when you want to add a new "drawing shape", you create a Draw and DrawFactory for it and add the factory to the combo box ... work done...
I have a CLickableBox class that creates boxes for me and now I need to make it so that when clicked, either an X or an O will be displayed in place. Here is the ClickableBox class.
import java.awt.event.MouseAdapter;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.Container;
public class ClickableBox extends MouseAdapter {
private int x, y, width, height;
private Color borderColor, backColor, oldColor;
private boolean drawBorder, clicked;
private Container parent;
public ClickableBox(int x, int y, int width, int height, Color borderColor,
Color backColor, boolean drawBorder, Container parent) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.borderColor = borderColor;
this.backColor = backColor;
this.drawBorder = drawBorder;
this.parent = parent;
}
public void draw(Graphics g) {
oldColor = g.getColor();
g.setColor(backColor);
g.fillRect(x, y, width, height);
if(drawBorder) {
g.setColor(borderColor);
g.drawRect(x, y, width, height);
}
g.setColor(oldColor);
}
public void mouseReleased(MouseEvent e) {
if(x < e.getX() && e.getX() < x + width &&
y < e.getY() && e.getY() < y + height) {
clicked = true;
parent.repaint();
}
}
public boolean isClicked() {
return clicked;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public Color getBorderColor() {
return borderColor;
}
public void setBorderColor(Color borderColor) {
this.borderColor = borderColor;
}
public Color getBackColor() {
return backColor;
}
public void setBackColor(Color backColor) {
this.backColor = backColor;
}
public Color getOldColor() {
return oldColor;
}
public void setOldColor(Color oldColor) {
this.oldColor = oldColor;
}
public boolean isDrawBorder() {
return drawBorder;
}
public void setDrawBorder(boolean drawBorder) {
this.drawBorder = drawBorder;
}
public void setClicked(boolean clicked) {
this.clicked = clicked;
}
}
The TicTacToeBox class should extend ClickableBox, so that each box will be a listener. It needs to be designed so that each Box object will take care of itself- it knows if it's been clicked or not, and if so, whether it's going to be showing an x or an o.
The TicTacToeBox class is what I am having trouble with. This is what I will need for my game board. Any suggestions on how to implement this, simply? Below is my TicTacToeBox so far (not much):
Some direction and/or assistance would be greatly appreciated! Thanks.
import java.awt.Color;
import java.awt.Container;
public class TicTacToeBox extends ClickableBox {
public TicTacToeBox(int x, int y, int width, int height, Color borderColor,
Color backColor, boolean drawBorder, boolean mask, Container parent)
{
super(x, y, width, height, borderColor, backColor, drawBorder, parent);
}
}
Perhaps you need to override mouseReleased() - something like this:
public void mouseReleased(MouseEvent e) {
if ( this.value == NONE ) {
if ( currentTurn == Turn.X ) {
this.value = X;
}
else {
this.value = O;
}
}
super.mouseReleased();
}
With some global currentTurn variable to keep track of whose turn it is, and a value field to represent what the current value of this box is. You'd also probably want to override draw() to make it render the "X" or "O"...