|
|
Welcome to the Java Forums.
You are currently viewing our boards as a guest which gives you limited access to view most discussions and access our other features. By joining our free community, you will:
- have access to post topics
- communicate privately with other members (PM)
- not see advertisements between posts
- have the possibility to earn one of our surprises if you are an active member
- access many other special features that will be introduced later.
Registration is fast, simple and absolutely free so please, join our community today!
If you have any problems with the registration process or your account login, please contact us.
|
|

11-08-2007, 03:58 PM
|
|
Member
|
|
Join Date: Nov 2007
Posts: 2
|
|
|
Drawing outside paintComponent()
This is my first time posting on here, so any help at all is appreciated and I'm sorry if i just sound dumb.
I have a practical to do which involves creating a noughts and crosses board using Graphics2D, but I have found myself experiencing problems quite early, which I cant seem to fix.
I can get the board, etc drawn up correctly, but, I'm not sure how to go about drawing a new X or O every time someone clicks a square.
Currently, I have placed a circle in the top left square, just to try this out.
When I click in any other square, the circle moves, but what I need is for the original circle to stay in place, so I can get on to making rows etc.
Below is my basic code so far, but I'm planning on removing the individual squares etc, that seems a bit simple I know. (clicked is called from the main class)
I suppose the basic question is, how do I draw a new circle outside of the paintComponent() method?
Thanks for any help you guys can give, and sorry so seem so confusing!!
Code:
public class graphicsPanel extends JPanel {
int circleX =15;
int circleY =15;
int size= 50;
Rectangle2D.Double topLeft, topCentre, topRight, midLeft, midCentre, midRight, bottomLeft, bottomCentre, bottomRight;
Ellipse2D.Double computer;
Map<Rectangle2D.Double, String> squares = new HashMap<Rectangle2D.Double, String>();
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(236,233,216));//sets colour
//Sets up the 9 squares (to be changed)
topLeft = new Rectangle2D.Double(0,0,77,77);
topCentre = new Rectangle2D.Double(77,0,77,77);
topRight = new Rectangle2D.Double(154,0,77,77);
midLeft = new Rectangle2D.Double(0,77,77,77);
midCentre = new Rectangle2D.Double(77,77,77,77);
midRight = new Rectangle2D.Double(154,77,77,77);
bottomLeft = new Rectangle2D.Double(0,154,77,77);
bottomCentre = new Rectangle2D.Double(77,154,77,77);
bottomRight = new Rectangle2D.Double(154,154,77,77);
//puts squares into an array
squares.put(topLeft, "");
squares.put(topCentre, "");
squares.put(topRight, "");
squares.put(midLeft,"");
squares.put(midCentre, "");
squares.put(midRight, "");
squares.put(bottomLeft, "");
squares.put(bottomCentre, "");
squares.put(bottomRight, "");
//draws the squares
for(Rectangle2D square: squares.keySet()){
g2.draw(square);
}
g2.setColor(Color.black);//changes colour back
g2.setStroke(new BasicStroke(5));//sets the line width
//Draws up the grid
g2.drawLine(0,77,231,77);
g2.drawLine(0,154,231,154);
g2.drawLine(77,0,77,231);
g2.drawLine(154,0,154,231);
//Draws the EXAMPLE CIRCLE
computer = new Ellipse2D.Double(circleX,circleY,size, size);
g2.draw(computer);
}
//Point clicked method
public void clicked(Point p) {
for(Rectangle2D square: squares.keySet()){
if(square.contains(p)){
//changes the x and y coords
circleX = (int)square.getX() +15;
circleY = (int)square.getY() +15;
repaint();
}
}
}
/** Creates a new instance of graphicsPanel */
public graphicsPanel() {
}
}
|
|

11-08-2007, 10:26 PM
|
|
Senior Member
|
|
Join Date: Jul 2007
Posts: 910
|
|
The basic idea is to design your graphic component class so that it can render itself (including its state) at any time. Keep your logic in another class and communicate with the graphic component to query/change its state. There are many ways to put these things together and imagination plays a big role in how you do it. Here's an example demonstrating (one way of) how to encapsulate state in the graphic component and how to communicate with it from a class that handles user input.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
public class BoardGame extends MouseAdapter implements ActionListener {
BoardPanel board;
int turn = 0;
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
if(board.contains(p)) {
Point cell = board.getCell(p);
if(board.isCellEmpty(cell)) {
board.setToken(cell, turn++ % 2);
// check for winner
}
}
}
public void actionPerformed(ActionEvent e) {
String ac = e.getActionCommand();
if(ac.equals("RESET")) {
board.clearBoard();
turn = 0;
}
}
private JPanel getBoard() {
board = new BoardPanel();
board.addMouseListener(this);
return board;
}
private JPanel getControls() {
JButton reset = new JButton("reset");
reset.setActionCommand("RESET");
reset.addActionListener(this);
JPanel panel = new JPanel();
panel.add(reset);
return panel;
}
public static void main(String[] args) {
BoardGame game = new BoardGame();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(game.getBoard());
f.getContentPane().add(game.getControls(), "Last");
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
}
}
class BoardPanel extends JPanel {
final int NAUGHT = 0;
final int CROSS = 1;
final int COLS = 3;
final int ROWS = 3;
final int PAD = 20;
int[][] tokens = new int[ROWS][COLS];
double xInc; // cell width
double yInc; // cell height
BoardPanel() {
clearBoard();
}
public void clearBoard() {
for(int j = 0; j < ROWS; j++)
for(int k = 0; k < COLS; k++)
tokens[j][k] = -1;
repaint();
}
public boolean contains(Point p) {
Rectangle r = getBounds();
r.grow(-PAD, -PAD);
return r.contains(p);
}
public Point getCell(Point p) {
Point cell = new Point();
for(int j = 0; j < ROWS; j++) {
double y = PAD + j*yInc;
if(p.y < y + yInc) {
cell.y = j;
break;
}
}
for(int j = 0; j < COLS; j++) {
double x = PAD + j*xInc;
if(p.x < x + xInc ) {
cell.x = j;
break;
}
}
return cell;
}
public boolean isCellEmpty(Point p) {
return tokens[p.x][p.y] == -1;
}
public void setToken(Point p, int token) {
tokens[p.x][p.y] = token;
repaint();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(4f));
g2.setPaint(Color.blue);
int w = getWidth();
int h = getHeight();
xInc = (double)(w - 2*PAD)/COLS;
yInc = (double)(h - 2*PAD)/ROWS;
// Horizontal grid lines.
for(int j = 0; j <= ROWS; j++) {
double y = PAD + j*yInc;
g2.draw(new Line2D.Double(PAD, y, w-PAD, y));
}
// Vertical grid lines.
for(int j = 0; j <= COLS; j++) {
double x = PAD + j*xInc;
g2.draw(new Line2D.Double(x, PAD, x, h-PAD));
}
// Draw tokens.
g2.setPaint(Color.red);
double tokenWidth = xInc*4/5;
double tokenHeight = yInc*4/5;
for(int j = 0; j < ROWS; j++) {
for(int k = 0; k < COLS; k++) {
int token = tokens[j][k];
double d = Math.min(tokenWidth, tokenHeight);
double x = PAD + j*xInc + (xInc - d)/2;
double y = PAD + k*yInc + (yInc - d)/2;
switch(token) {
case NAUGHT:
g2.draw(new Ellipse2D.Double(x, y, d, d));
break;
case CROSS:
g2.draw(new Line2D.Double(x, y, x+d, y+d));
g2.draw(new Line2D.Double(x+d, y, x, y+d));
}
}
}
}
}
|
|

11-08-2007, 11:36 PM
|
|
Member
|
|
Join Date: Nov 2007
Posts: 2
|
|
Thanks a lot, this really helps. I was a bit confused by the whole thing but you've given me an idea of how to go about it.
Thanks again! 
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|