Method paintComponent
I have a class that extends Jpanel .
This class is in a JApplet .
When I call the method paintComponent of JPanel from the JApplet , I want only paint in the JPanel.
Instead the paint is done outer the JPanel.
In The JApplet I call paintComponent of JPanel to repaint.
How can resolve this problem?
Message was edited by:
wnocella
The way to go is this.
If you want to paint in a jpanel you have to create a class that extend it.
Whithin that class you override method: public void paintComponent(Graphics g)
In paintComponent you do your painting.
It will like similar to this:
public void paintComponent(Graphics g){
g.drawImage(image, x, y, w, h,null);
if(beingDragged){
g.setColor(Color.black);
Graphics2D g2 = (Graphics2D)g;
g2.setStroke(BorderLines.getStroke(BorderLines.DOTTED));
g2.drawRect(tempX, tempY, tempW, tempH);
if(!selected) return;
g.setColor(Color.black);
g.translate(x, y);
int xMid=w/2-3;
int yMid = h/2-3;
g.setXORMode(Color.red);
// TL
g.drawLine(0,5,6,5);
g.drawLine(5,0,5,5);
}When you want to repaint your panel you call panel.repaint(). This method will eventually invoke your panel's paingComponent method.
Good luck.
Similar Messages
-
I'm writing a calendar applet for a programming class and I've nearly completed it but I'm stuck at checking for valid data.
What seems to be happening is that paintComponent() is being called before actionPerformed.
In actionPerformed (when they click the button), it checks to make sure they entered a valid month (1 to 12). If the didn't it dispalys a message, but if they did it calls repaint().
But even if repaint() isn't called, Java still seems to call it before actionPerformed and I get exceptions.
So I tried checking inside of paintComponent() by using a simple if(...) return; but that doesn't seem to do anything... it just keeps going through with the method.
So -- Once the user presses my button I want to make sure the data is valid before repainting the screen. How can I do this?I validate it in actionPerformed which is called by
the action listener... that is what you meant right?
The problem is that it seems paintComponent() is being
called before I can validate the data with
actionPerformed(). I need to stop paintComponent()
from always being calledMVC. (Model, View, Controller)
Initially the internal value of the data (the model) should be valid (or null with a check in the paintComponent method)
paintComponent (the view part) shows the state of the valid data.
You press the button.
actionPerformed is called (the controller).
It checks the value and, if valid, writes it to the data (model), then updates the view.
At no point will the view have to render invalid data, because the model is only updated after actionPerformed checks the value.
The pattern may be applied with different classes performing the three roles, or different methods in the same class (sometimes it's easier that way for simple cases).
Pete -
SwingUtilities.paintComponent - problems with painting childs of components
Maybe this question was mention already but i cant find any answer...
Thats what could be found in API about method paintComponent in SwingUtilities:
Paints a component c on an arbitrary graphics g in the specified rectangle, specifying the rectangle's upper left corner and size. The component is reparented to a private container (whose parent becomes p) which prevents c.validate() and c.repaint() calls from propagating up the tree. The intermediate container has no other effect.
The component should either descend from JComponent or be another kind of lightweight component. A lightweight component is one whose "lightweight" property (returned by the Component isLightweight method) is true. If the Component is not lightweight, bad things map happen: crashes, exceptions, painting problems...
So this method perfectly works for simple Java components like JButton / JCheckbox e.t.c.
But there are problems with painting JScrollBar / JScrollPane (only background of this component appears).
I tried to understand why this happens and i think the answer is that it has child components that does not draw at all using SwingUtilities.paintComponent()
(JScrollBar got at least 2 childs - 2 buttons on its both sides for scroll)
Only parent component appears on graphics - and thats why i see only gray background of scrollbar
So is there any way to draw something like panel with a few components on it if i have some Graphics2D to paint on and component itself?
Simple example with JScrollPane:
JScrollPane pane = new JScrollPane(new JLabel("TEST"));
pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
SwingUtilities.paintComponent(g2d, pane, new JPanel(), 0, 0, 200, 200);Edited by: mgarin on Aug 11, 2008 7:48 AMWell the thing you advised could work... but this wont be effective, because i call repaint of the area, where Components painted, very often..
So it will lag like hell when i make 10-20 repaints in a second... (for e.g. when i drag anything i need mass repainting of the area)
Isnt there any more optimal way to do painting of the sub-components?
As i understand when any component (even complicated with childs) paints in swing - its paint method calls its child components paint() to show them... can this thing be reproduced to paint such components as JScrollPane? -
Request For Enhancement: Add method mouseIn() to JComponent
I would like to propose that a new method be added to JComponent. This method would return boolean true if the mouse is currently over the JComponent and false if not. Method signature: public boolean mouseIn().
This method would make it easier to accomplish visual feedback for when the mouse is over any JComponent, similar to how rollover can be done for AbstractButton.
Currently, the best method I can come up with is to add a MouseListener that records the state from the mouseEntered() and mouseExited() events. I add my own method mouseIn() that returns that state. Then method paintComponent() can check this state by calling mouseIn() and paint the component accordingly.
At first I thought the MouseListener should be added in each and every constructor of each and every JComponent, but then realized actually, the place to provide this feedback is in the ComponentUI class for each JComponent, as part of a custom Look & Feel. What I have come up with is to add the MouseListener to the JComponent in the ComponentUI's createUI() method, recording the state in the ComponentUI instance. The problem with this is, it makes it impossible for the ComponentUI to be a singleton like most of the ComponentUI classes are for the standard L&F's. This requires that each JComponent instance have its own ComponentUI instance.
If JComponent had this proposed mouseIn() method, the ComponentUI methods could simply call this method, and the ComponentUI would not have to record JComponent-instance-specific state. There would not be a need for so many instances of ComponentUI and MouseListener.Hi,
imho this request for enhancement is much better than your other onces. In fact monitoring this state is more than just using mouseEntered(..) and mouseExited(...) - if there is a method, it must return a valid state - if mouse has entered and you make the component invisible, mouse does not exit before that takes place - if you open another application which covers this component, mouse does also not exit before, but the component stays visible - you see, there are much more things to control, to get a valid state at any time. And mouseIn() is an ugly name and says less - why not isMouseOver() or something like this?
Another thing is, why do you request this for JComponent?- Should java.awt.Component not get this feature in your opinion?
greetings Marsian -
I'm using the below code
public void paintComponent(Graphics g)
super.paintComponent(g);
layeredPane.setOpaque(false);
g = layeredPane.getGraphics();
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.draw((Shape) vPoly.elementAt(0));
}it throws the below error in "super.paintComponent(g);" :
symbol : method paintComponent(java.awt.Graphics)
location: class javax.swing.JFrame
super.paintComponent(g);
Note: D:\Usama\NetBeans\MTT\src\First.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 errorCould anyone please tell me why?
The repaint() method does not call the paintComponent but if I change it to paint it does (in both cases i could not use the "super.paintComponent(g);"). When I change the paintComponent method to paint the I do not get the required result.
RegardsQuit multi-posting. You where asked in your other posting to post a SSCCE.
There is no problem overiding paintComponent(). We have all done it hundreds of times. We can't help based on a few lines of code as we don't know the context of how the code is used.
So quit wasting everybodies time by creating multiple postings on the forum. Keep the questions in a single posting so everybody knows what has been suggested already.
How many time to you have to be asked to do this?????? -
Cannot resolve symbol: method getCodeBase ()
I`m creating a dice game that makes a sound when player wins or looses. Instaed I`m getting the following error message: Cannot resolve symbol: method getCodeBase (). I think this depends on the fact that I have a separate applet launcher but cannot figure out how to solve this, please help!!
This is the applet launcher
import javax.swing.*;
import java.awt.*;
// [MC] Public class DiceApplet
public class DiceApplet extends JApplet
// [MC] Constructor.
public DiceApplet()
// [MC] Sets the contentPane property. This method is called by the constructor.
this.setContentPane(new DicePanel());
This is the die class
import java.awt.*;
import javax.swing.*;
// [MC] Public class Die
public class Die extends JPanel
// ======================================================================
// [MC] Instance variable.
private int myFaceValue; // [MC] Value that shows on face of die.
// [MC] End instance variable.
// ======================================================================
// [MC] Constructor.
// [MC] Initialises die to blue background and initial roll.
public Die()
// [MC] Sets the background colour of the die to blue.
setBackground(Color.blue);
// [MC] Sets the foreground colour of the die to gray.
setForeground(Color.gray);
// [MC] Sets the border colour of the die to white.
setBorder(BorderFactory.createMatteBorder(4, 4, 4, 4, Color.white));
// [MC] Sets to random initial value.
roll();
} // [MC] End constructor.
// ======================================================================
// [MC] Method roll.
// [MC] Produces random roll in the range of 1 to 6.
public int roll()
int val = (int)(6*Math.random() + 1); // [MC] Range from 1 to 6.
setValue(val);
return val; // [MC] Returns a value from 1 to 6.
} // [MC] End method roll.
// [MC] Method setValue
// [MC] Sets the value of the die. Causes repaint.
public void setValue(int dots)
myFaceValue = dots;
repaint(); // [MC] Value has changed, must repaint.
} // [MC] End method setValue.
// ======================================================================
// [MC] Method getValue.
// [MC] Returns result of last roll.
public int getValue()
return myFaceValue;
} // [MC] End method getValue.
// ======================================================================
// [MC] Method paintComponent.
// [MC] Draws dots of die face.
public void paintComponent(Graphics g)
// [MC] Call superclass's paint method.
super.paintComponent(g);
// [MC] Sets panel width.
int w = getWidth();
// [MC] Sets panel height.
int h = getHeight();
// [MC] Draws border.
g.drawRect(0, 0, w-1, h-1);
// Switch
switch (myFaceValue)
case 1: drawDot(g, w/2, h/2);
break;
case 3: drawDot(g, w/2, h/2);
case 2: drawDot(g, w/4, h/4);
drawDot(g, 3*w/4, 3*h/4);
break;
case 5: drawDot(g, w/2, h/2);
case 4: drawDot(g, w/4, h/4);
drawDot(g, 3*w/4, 3*h/4);
drawDot(g, 3*w/4, h/4);
drawDot(g, w/4, 3*h/4);
break;
case 6: drawDot(g, w/4, h/4);
drawDot(g, 3*w/4, 3*h/4);
drawDot(g, 3*w/4, h/4);
drawDot(g, w/4, 3*h/4);
drawDot(g, w/4, h/2);
drawDot(g, 3*w/4, h/2);
break;
} // [MC] End switch.
} // [MC] End method paintComponent.
// [MC] Method drawDot.
/** Utility method used by paintComponent(). */
private void drawDot(Graphics g, int x, int y)
// [MC] Gets panel width.
int w = getWidth();
// [MC] Gets panel height.
int h = getHeight();
// [MC] Local variable.
int d;
// [MC] Sets diameter of dot proportional to panel size.
d = (w + h)/10;
// [MC] Sets colour for dot to white.
Color myDotColor = new Color(255, 255, 255);
g.setColor(myDotColor);
// [MC] Draws dot.
g.fillOval(x-d/2, y-d/2, d, d);
} // [MC] End method drawDot.
This is the class giving the error message
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.applet.AudioClip;
import java.applet.Applet;
import java.net.*;
// [MC] Public class DicePanel
public class DicePanel extends JPanel
// ======================================================================
// [MC] Instance variables.
// [MC] Creates new instances of the component for the die.
private Die myLeftDie; // [MC] Component for left die.
private Die myRightDie; // [MC] Component for right die.
// [MC] Creates the button (rollButton) to roll the dice.
private JButton rollButton = new JButton("Roll Dice");
// [MC] Creates the text fields. Creates new instance of JTextField.
// [MC] Creates the text field (rollNumberTextField) to display number of rolls.
private JTextField rollNumberTextField = new JTextField(20);
// [MC] Creates the text field (rollResultTextField) to display result of roll.
private JTextField rollResultTextField = new JTextField(20);
// [MC] Creates the text field (rollPointsTextField) to display the player`s points.
private JTextField rollPointsTextField = new JTextField(20);
// [MC] Creates the text field (gameFinalResultTextField) to display the final game result.
private JTextField gameFinalResultTextField = new JTextField(20);
// [MC] Initialises instance variables declared in the inner listeners.
private int result = 0, resultLeft = 0, resultRight = 0;
private int rolls = 0;
private int finalResult = 0;
private int points = 0;
private boolean first = true;
private AudioClip winClip = null;
private AudioClip looseClip = null;
// ======================================================================
// [MC] Constructor. Creates border layout panel.
DicePanel()
// [MC] Creates the dice
myLeftDie = new Die();
myRightDie = new Die();
// ======================================================================
// [MC] Creates the buttons.
// [MC] Creates the button (newGameButton) to start new game.
JButton newGameButton = new JButton("New Game");
// *[MC] Creates the button (rollButton) to roll the dice.
// *JButton rollButton = new JButton("Roll Dice");
// [MC] Sets the font of the buttons.
// [MC[ Sets the font of the button newGameButton.
newGameButton.setFont(new Font("Batang", Font.BOLD, 20));
// [MC[ Sets the font of the button rollButton.
rollButton.setFont(new Font("Batang", Font.BOLD, 20));
// [MC] Sets the button border format.
// [MC] Sets the button with compound borders.
Border compound;
// [MC] Border format local variables.
Border blackline, raisedetched, loweredetched, raisedbevel, loweredbevel, empty;
// [MC] Initialises border formats.
//blackline = BorderFactory.createLineBorder(Color.gray);
raisedetched = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
loweredetched = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
raisedbevel = BorderFactory.createRaisedBevelBorder();
//loweredbevel = BorderFactory.createLoweredBevelBorder();
// [MC] Sets compound border format.
compound = BorderFactory.createCompoundBorder(raisedetched, raisedbevel);
// [MC] Sets the button (newGameButton) with compound border format.
newGameButton.setBorder(compound);
// [MC] Sets the button (rollButton) with compound border format.
rollButton.setBorder(compound);
// [MC] Adds listener.
// [MC] Adds listener to rollButton.
rollButton.addActionListener(new RollListener());
// [MC] Adds listener to newGameButton.
newGameButton.addActionListener(new NewGameListener());
// ======================================================================
// [MC] Creates the labels. Creates new instance of JLabel.
// [MC] Creates the label (rollNumberLabel) for the number of rolls.
JLabel rollNumberLabel = new JLabel("Roll Number");
// [MC] Creates the label (rollResultLabel) for the result of roll.
JLabel rollResultLabel = new JLabel("Roll Result");
// [MC] Creates the label (rollPointsLabel) for the player`s points.
JLabel rollPointsLabel = new JLabel("Player Points");
// [MC] Creates the label (gameFinalResult) for the final game result.
JLabel gameFinalResultLabel = new JLabel("Final Result");
// [MC] Sets the label font.
rollNumberLabel.setFont(new Font("Sansserif", Font.PLAIN, 10));
rollResultLabel.setFont(new Font("Sansserif", Font.PLAIN, 10));
rollPointsLabel.setFont(new Font("Sansserif", Font.PLAIN, 10));
gameFinalResultLabel.setFont(new Font("Sansserif", Font.PLAIN, 10));
// [MC] Sets the label title alignment.
rollNumberLabel.setHorizontalAlignment(JLabel.CENTER);
rollResultLabel.setHorizontalAlignment(JLabel.CENTER);
rollPointsLabel.setHorizontalAlignment(JLabel.CENTER);
gameFinalResultLabel.setHorizontalAlignment(JLabel.CENTER);
// [MC] Sets the label border format.
//rollNumberLabel.setBorder(loweredetched);
//rollResultLabel.setBorder(loweredetched);
//rollPointsLabel.setBorder(loweredetched);
//gameFinalResultLabel.setBorder(loweredetched);
// ======================================================================
// [MC] Sets the text field font.
rollNumberTextField.setFont(new Font("Sansserif", Font.PLAIN, 16));
rollResultTextField.setFont(new Font("Sansserif", Font.PLAIN, 16));
rollPointsTextField.setFont(new Font("Sansserif", Font.PLAIN, 16));
gameFinalResultTextField.setFont(new Font("Sansserif", Font.BOLD, 16));
// [MC] Sets the text field text alignment.
rollNumberTextField.setHorizontalAlignment(JTextField.CENTER);
rollResultTextField.setHorizontalAlignment(JTextField.CENTER);
rollPointsTextField.setHorizontalAlignment(JTextField.CENTER);
gameFinalResultTextField.setHorizontalAlignment(JTextField.CENTER);
// [MC] Sets the text field text colour.
gameFinalResultTextField.setForeground(Color.blue);
// [MC] Sets the text field to not editable.
rollNumberTextField.setEditable(false);
rollResultTextField.setEditable(false);
rollPointsTextField.setEditable(false);
gameFinalResultTextField.setEditable(false);
// ======================================================================
// [MC] Gets sounds.
winClip = getAudioClip(getCodeBase(), "bunny1.au");
looseClip = getAudioClip(getCodeBase(), "bunny1.au");
// ======================================================================
// [MC] Sets the layout manager (GridBagLayout) for this container.
this.setLayout(new GridBagLayout());
// [MC] Creates new instance of GridBagConstraints.
GridBagConstraints c = new GridBagConstraints();
// [MC] Makes the component fill its display area entirely.
c.fill = GridBagConstraints.BOTH;
// [MC] Layouts components.
// [MC] Adds the component newGameButton to this container.
c.gridx = 0; // [MC] Makes this component the leftmost column (column 1).
c.gridy = 0; // [MC] Makes this component the uppermost row (row 1).
c.gridheight = 1; // [MC] Specifies the number of rows the component uses (1 row).
c.gridwidth = 2; // [MC] Specifies the number of columns the component uses (2 columns).
this.add(newGameButton, c); // [MC] Adds the button newGameButton.
// [MC] Adds the component rollButton to this container.
c.gridx = 2; // [MC] Makes this component the third column from left (column 3).
c.gridy = 0; // [MC] Make this component the uppermost row (row 1).
c.gridheight = 1; // [MC] Specifies the number of rows the component uses (1 rows).
c.gridwidth = 2; // [MC] Specifies the number of columns the component uses (2 columns).
this.add(rollButton, c); // [MC] Adds the button rollButton.
// [MC] Adds the component rollNumberLabel to this container.
c.gridx = 0; // [MC] Makes this component the leftmost column (column 1).
c.gridy = 3; // [MC] Makes this component the third row from top (row 3).
c.gridheight = 1; // [MC] Specifies the number of rows the component uses (1 row).
c.gridwidth = 1; // [MC] Specifies the number of columns the component uses (1 column).
c.weightx = 0.1; // [MC] Requests any extra vertical (column) space.
this.add(rollNumberLabel, c); // [MC] Adds the label rollNumberLabel.
// [MC] Adds the component rollResultLabel to this container.
c.gridx = 1; // [MC] Makes this component the second column from left (column 2).
c.gridy = 3; // [MC] Makes this component the third row from top (row 3).
c.gridheight = 1; // [MC] Specifies the number of rows the component uses (1 row).
c.gridwidth = 1; // [MC] Specifies the number of columns the component uses (1 column).
this.add(rollResultLabel, c); // [MC] Adds the label rollResultLabel.
// [MC] Adds the component rollPointsLabel to this container.
c.gridx = 2; // [MC] Makes this component the third column from left (column 3).
c.gridy = 3; // [MC] Makes this component the third row from top (row 3).
c.gridheight = 1; // [MC] Specifies the number of rows the component uses (1 row).
c.gridwidth = 1; // [MC] Specifies the number of columns the component uses (1 column).
this.add(rollPointsLabel, c); // [MC] Adds the label rollPointsLabel.
// [MC] Adds the component gameFinalResultLabel to this container.
c.gridx = 3; // [MC] Makes this component the fourth column from left (column 4).
c.gridy = 3; // [MC] Makes this component the third row from top (row 3).
c.gridheight = 1; // [MC] Specifies the number of rows the component uses (1 row).
c.gridwidth = 1; // [MC] Specifies the number of columns the component uses (1 column).
this.add(gameFinalResultLabel, c); // [MC] Adds the label gameFinalResultLabel.
// [MC] Adds the component rollNumberTextField to this container.
c.gridx = 0; // [MC] Makes this component the leftmost column (column 1).
c.gridy = 4; // [MC] Makes this component the fourth row from top (row 4).
c.gridheight = 1; // [MC] Specifies the number of rows the component uses (1 row).
c.gridwidth = 1; // [MC] Specifies the number of columns the component uses (1 column).
c.weightx = 0.1; // [MC] Requests any extra vertical (column) space.
this.add(rollNumberTextField, c); // [MC] Adds the text field rollNumberTextField.
// [MC] Adds the component rollResultTextField to this container.
c.gridx = 1; // [MC] Makes this component the second column from left (column 2).
c.gridy = 4; // [MC] Makes this component the fourth row from top (row 4).
c.gridheight = 1; // [MC] Specifies the number of rows the component uses (1 row).
c.gridwidth = 1; // [MC] Specifies the number of columns the component uses (1 column).
this.add(rollResultTextField, c); // [MC] Adds the text field rollResultTextField.
// [MC] Adds the component rollPointsTextField to this container.
c.gridx = 2; // [MC] Makes this component the third column from left (column 3).
c.gridy = 4; // [MC] Makes this component the fourth row from top (row 4).
c.gridheight = 1; // [MC] Specifies the number of rows the component uses (1 row).
c.gridwidth = 1; // [MC] Specifies the number of columns the component uses (1 column).
this.add(rollPointsTextField, c); // [MC] Adds the text field rollPointsTextField.
// [MC] Adds the component gameFinalResultTextField to this container.
c.gridx = 3; // [MC] Makes this component the fourth column from left (column 4).
c.gridy = 4; // [MC] Makes this component the fourth row from top (row 4).
c.gridheight = 1; // [MC] Specifies the number of rows the component uses (1 row).
c.gridwidth = 1; // [MC] Specifies the number of columns the component uses (1 column).
this.add(gameFinalResultTextField, c); // [MC] Adds the text field gameFinalResultTextField.
// [MC] Adds the component myLeftDie to this container.
c.gridx = 0; // [MC] Makes this component the leftmost column (column 1).
c.gridy = 1; // [MC] Makes this component the second row from top (row 2).
c.gridheight = 2; // [MC] Specifies the number of rows the component uses (2 rows).
c.gridwidth = 2; // [MC] Specifies the number of columns the component uses (2 columns).
c.weightx = 1.0; // [MC] Requests any extra vertical (column) space.
c.weighty = 1.0; // [MC] Requests any extra horizontal (row) space.
this.add(myLeftDie, c); // [MC] Adds the component myLeftDie.
// [MC] Adds the component myRightDie to this container.
c.gridx = 2; // [MC] Makes this component the third column from left (column 3).
c.gridy = 1; // [MC] Makes this component the second row from top (row 2).
c.gridheight = 2; // [MC] Specifies the number of rows the component uses (2 rows).
c.gridwidth = 2; // [MC] Specifies the number of columns the component uses (2 column).
c.weightx = 1.0; // [MC] Requests any extra column (vertical) space.
c.weighty = 1.0; // [MC] Requests any extra horizontal (row) space.
this.add(myRightDie, c); // [MC] Adds the component myRightDie.
} // [MC] end constructor
// ======================================================================
// [MC] Private class RollListener
// [MC] Inner listener class for rollButton.
private class RollListener implements ActionListener
public void actionPerformed(ActionEvent e)
// [MC] Rolls the dice.
myLeftDie.roll(); // [MC] Rolls left die.
myRightDie.roll(); // [MC] Rolls right die.
finalResult = 0; // [MC] If result = 0 then game is not over.
rolls++; // [MC] Increments the number of rolls.
// [MC] Displays the roll number.
rollNumberTextField.setText(" " + rolls + " ");
// [MC] Returns the result (number of dots) of last roll.
resultLeft = myLeftDie.getValue(); // [MC] Returns the result of the left die.
resultRight = myRightDie.getValue(); // [MC] Returns the result of the right die.
result = resultLeft + resultRight; // [MC] Returns the total result of dice.
// [MC] Displays the result of last roll.
rollResultTextField.setText(" " + result + " ");
// [MC] Sets the rules for the game.
// [MC] Sets the rules for the first roll of dice.
if (first)
// [MC] If the result is 2, 3 or 12 on the first throw, the player loses.
if (result == 2 || result == 3 || result == 12)
finalResult = 2; // [MC] If result = 2 then the player loses and the game is over.
gameFinalResultTextField.setText("LOOSE");
Toolkit.getDefaultToolkit().beep();
rollButton.setEnabled(false); // [MC] Disable rollButton.
first = true; // [MC] Game over after first roll.
// [MC] If the result is 7 or 11 on the first throw, the player wins.
else if (result == 7 || result == 11)
finalResult = 1; // [MC] If result = 1 then the player wins and the game is over.
gameFinalResultTextField.setText("WIN");
//Toolkit.getDefaultToolkit().beep();
rollButton.setEnabled(false); // [MC] Disable rollButton.
first = true; // [MC] Game over after first roll.
// [MC] If the player didn`t win or lose then the results 4, 5, 6, 8, 9 or 10 become the player`s point.
else if (result == 4 || result == 5 || result == 6 || result == 8 || result == 9 || result == 10);
// [MC] Returns the player`s points.
points = result; // [MC] Returns the player`s points.
// [MC] Displays the player`s points.
rollPointsTextField.setText(" " + points + " ");
first = false; // [MC] Game is not over after first roll.
// [MC] Sets the rules for the next rolls (from second roll onwards) of the dice.
// [MC] If the result is 7, then the player loses.
else if (result == 7)
finalResult = 2; // [MC] If result = 2 then the player loses and the game is over.
gameFinalResultTextField.setText("LOOSE");
Toolkit.getDefaultToolkit().beep();
rollButton.setEnabled(false); // [MC] Disable rollButton.
// [MC] If the result is equal to the player`s point, then the player wins.
else if (result == points)
finalResult = 1; // [MC] If result = 1 then the player wins and the game is over.
gameFinalResultTextField.setText("WIN");
winClip.play();
//Toolkit.getDefaultToolkit().beep();
rollButton.setEnabled(false); // [MC] Disable rollButton.
} // [MC] End public void actionPerformed(ActionEvent e).
} // [MC] End private class RollListener.
// ======================================================================
// [MC] Private class NewGameListener
// [MC] Inner listener class for newGameButton.
private class NewGameListener implements ActionListener
public void actionPerformed(ActionEvent e)
// [MC] Initialises instance variables.
first = true; // [MC] Initialise dice roll to first roll.
rolls = 0; // [MC] Initialises number of rolls to 0.
// [MC] Initialises text fields.
rollResultTextField.setText("");
rollNumberTextField.setText("");
rollPointsTextField.setText("");
gameFinalResultTextField.setText("");
rollButton.setEnabled(true); // [MC] Enable rollButton.
} // [MC] End public void actionPerformed(ActionEvent e).
}// [MC] End private class NewGameListener implements ActionListener.
} // [MC] End public class DicePanel extends JPanel.make a backup copy before these changes
it now compiles, but I haven't run/tested it
changed constructor to init(), extending Applet, not JApplet
// [MC] Public class DiceApplet
public class DiceApplet extends Applet
// [MC] Constructor.
public void init()
// [MC] Sets the contentPane property. This method is called by the constructor.
add(new DicePanel());
}then the 'error lines' become
winClip = ((Applet)getParent()).getAudioClip(((Applet)getParent()).getCodeBase(), "bunny1.au");
looseClip = ((Applet)getParent()).getAudioClip(((Applet)getParent()).getCodeBase(), "bunny1.au");there might be additional problems when you run/test it, but this might get you started -
"cannot resolve symbol" error when using super.paintComponent
I am trying to override the paintComponent method in a class extending a JFrame, but when I call super.paintComponent(g) from inside the overridden method I get the error
QubicGUI.java:63: cannot resolve symbol
symbol : method paintComponent (java.awt.Graphics)
location: class javax.swing.JFrame
super.paintComponent(g);
^
1 error
I can't see where I am deviating from examples I know work. It is a very small program, so I have included it here:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.net.URL;
class QubicGUI extends JFrame
private int width;
private int height;
private Image background;
public int getWidth()
{ return width; }
public int getHeight()
{ return height; }
public boolean isOpaque()
return true;
public QubicGUI()
super("Qubic"); //set title
// The following gets the default screen device for the purpose of finding the
// current settings of height and width of the screen
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = environment.getDefaultScreenDevice();
DisplayMode display = device.getDisplayMode();
width = display.getWidth();
height = display.getHeight();
// Here we set the window to cover the entire screen with a black background, and
// remove the decorations. (This includes the title bar and close, minimize and
// maximize buttons and the border)
setUndecorated(false);
setVisible(true);
setSize(width,height);
setResizable(false);
setBackground(Color.black);
// Initializes the background Image
Image background = Toolkit.getDefaultToolkit().getImage("background.gif");
// This is included for debugging with a decorated window.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} // end constructor
public void paintComponent(Graphics g)
super.paintComponent(g);
} // end paintComponenet
} // end QubicGUITwo things I want to know:
1. I was trying to access a variable as JLabel
myLabel; defined in the constructor of a class from
the constructor of another class. I got this error
message - "Cannot access non-static variable from a
static context". Why(When both are non-static am I
getting the message as static context)?Post some code. It's hard to pinpoint a syntax error like that without seeing the code.
Also, there may be cleaner ways of doing what you want without having classes sharing labels.
2. I am using a map to set the attributes of a font.
One of the key-value pair of the map is
TextAttributesHashMap.put(TextAttribute.FOREGROUND,Colo
.BLUE);
But when I using the statement g.drawString("First
line of the address", 40, 200); the text being
displayed is in black and not blue. Why?You need to use the drawString that takes an AttributedCharacterIterator:
import java.awt.*;
import java.awt.font.*;
import java.text.*;
import javax.swing.*;
public class Example extends JPanel {
public static void main(String[] args) {
JFrame f = new JFrame("Example");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cp = f.getContentPane();
cp.add(new Example());
f.setSize(400,300);
f.setLocationRelativeTo(null);
f.setVisible(true);
protected void paintComponent(Graphics g) {
super.paintComponent(g);
String text = "Every good boy does fine always";
AttributedString as = new AttributedString(text);
as.addAttribute(TextAttribute.FAMILY, "Lucida Bright");
as.addAttribute(TextAttribute.SIZE, new Float(16));
as.addAttribute(TextAttribute.FOREGROUND, Color.BLUE, 0, 5);
as.addAttribute(TextAttribute.FOREGROUND, Color.GREEN, 6, 10);
as.addAttribute(TextAttribute.FOREGROUND, Color.RED, 11, 14);
as.addAttribute(TextAttribute.FOREGROUND, Color.YELLOW, 15, 19);
as.addAttribute(TextAttribute.FOREGROUND, Color.MAGENTA, 20, 24);
as.addAttribute(TextAttribute.FOREGROUND, Color.CYAN, 25, 31);
g.drawString(as.getIterator(), 10, 20); -
Overriding paint for customizing JButton??? Shouldn't be paintComponent?
Hi
Shouldn't we always override paintComponent to customize the painting of a component?
Why MetalScrollButton in javax.swing.plaf.Metal overrides paint instead of paintComponent?
Should I override paint if I want to write my own LnF?
Thanks.As is said in the online doc about paint(), "This method actually delegates the work of painting to three protected methods: paintComponent, paintBorder, and paintChildren. They're called in the order listed to ensure that children appear on top of component itself. Generally speaking, the component and its children should not paint in the insets area allocated to the border. Subclasses can just override this method, as always. A subclass that just wants to specialize the UI (look and feel) delegate's paint method should just override paintComponent."
That means you can override paint(), , but in this case you'll have to draw the border yourself... and if you have a composite custom component (a panel containing labels, for example), you will have to call the label's paintComponent() methods by yourself...
Hope this helped,
Regards -
Explain paintComponent concept please
Hi
I have a Swing application which implements the paintComponent() method. I am having trouble understanding how it works, could someone help please ?
- Why can i call the paintComponent() method with rePaint() but not paintComponent() ?
- When we overide paintComponent with a Graphics object how does this work ? Because we don't explicitly give it a graphics object yet it is still called. I know about method overiding but i don't understand this . . .
- Can each application can only implement 1 paintComponent method? For instance i use paintComponent initially to draw some things but then later, at a specific point that happens once i need to draw something else. Do i just have to find a way to incorporate this in my paintComponent method ?
-the super() extends from JFrame. What happens in this second line of code please
public void paintComponent(Graphics g) {
super.paintComponent(g); //what is occuring here ?
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(Color.black); help much appreciated - thanksHi
I have a Swing application which implements the
paintComponent() method. I am having trouble
understanding how it works, could someone help please
- Why can i call the paintComponent() method with
rePaint() but not paintComponent() ?Do you know what threads are? Very roughly, threads are "subprocesses" that run at fairly independent rates within a running application. Swing starts a thread called the EDT (Event Dispatch Thread). Its job is to draw your GUI and respond to events like mouse clicks &movements and keyboard input. As the name indicates, the EDT is driven by a queue of events: events are enqueued and later they are dequeued and processed. Some events are higher priority, like mouse movements, and can skip ahead of other events, like requests to repaint parts of components. To get a component repainted, you call one of its repaint methods (many methods, like JTextField's setText, will invoke repaint for you). The repaint methods are asynchronous: when it returns, it's likely that repainting hasn't even begun. All that happened is that the repaint request has been queued. When a Swing component (any subclass of JComponent) is to be repainted, it's paint method is called by code in the EDT (this part of the Swing Framework -- you don't paint directly -- let the EDT call paint when it decides it's right). Component's implementation of paint calls three protected methods in order:
-- paintComponent : to paint the background of the component
-- paintBorder
-- paintChildren, in case the component is a container, like JPanel
To customize the painting of a JComponent you could override any of these, but the most useful to override is paintComponent.
>
- When we overide paintComponent with a Graphics
object how does this work ? Because we don't
explicitly give it a graphics object yet it is still
called. I know about method overiding but i don't
understand this . . .As a Design Pattern, method paintComponent is an example of a Template Method: you override but your code doesn't call it directly. This is a very common pattern in object oriented code. For example, if you wanted to make Zubs sortable, you could have the Zub class implement Comparable and override the compareTo method. Your code doesn't call this method, the sorting algorithm does.
>
- Can each application can only implement 1
paintComponent method? For instance i use
paintComponent initially to draw some things but then
later, at a specific point that happens once i need to
draw something else. Do i just have to find a way to
incorporate this in my paintComponent method ?Any JComponent can override paintComponent. There many be several such classes in your app. To "draw things later" means to add state to your JComponent. An example follows at the end of this post.
>
-the super() extends from JFrame. What happens in
this second line of code please
public void paintComponent(Graphics g) {
super.paintComponent(g); //what is occuring here
ere ?
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(Color.black); help much appreciated - thanks First, its not a great idea to override JFrame's paintComponent -- think of your window as an oil painting: is it the job of the gilt frame to draw what gets fitted inside of it? It's usually better to subclass JPanel or JComponent to do that. Anyway, the call to the super class's paintComponent often does things like painting the background of the component the component's background color...
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.util.List;
public class X extends JPanel {
private List points = new ArrayList();
public X() {
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent evt) {
points.add(evt.getPoint());
repaint();
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for(Iterator i = points.iterator(); i.hasNext(); ) {
Point pt = (Point) i.next();
g.drawOval(pt.x-2, pt.y-2, 5, 5);
public static void main(String[] args) {
final JFrame f = new JFrame("X");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new X());
f.setSize(400,300);
f.setLocationRelativeTo(null);
f.setVisible(true); -
Hello,
My instructor is wanting me to use the MVC paradigm. He was telling me that I should be able to put my deal() method in my Model.java. How can I access paintComponent() from the Model.java? If I put the deal() method in the View.java, then it is fine. I have been racking my brains all day long with this. Can anyone please take a look and let me know what I am doing wrong?
Thanks,
E
//======================================
//======================================
//NewSolitaireController.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class NewSolitaireController extends JApplet
//==========================================applet constructor
public NewSolitaireController()
this.setContentPane(new NewSolitaireView());
}//===========================================end constructor
//=================================================method main
public static void main(String[] args)
JFrame window = new JFrame();
window.setTitle("Solitaire by EK");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setContentPane(new NewSolitaireView());
window.pack();
//window.setResizable(false);
window.show();
}//======================================================end main
}//=========================================endclass SolitaireProject
//================================================
//================================================
//NewSolitaireView.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
//import java.util.*;
public class NewSolitaireView extends JPanel //implements MouseListener, MouseMotionListener
//================================================================instance variables
private GraphicsPanel boardDisplay_;
private NewSolitaireModel gameLogic_ = new NewSolitaireModel();
private boolean gameOver_ = false;
int clubPosition = 0;
int diamondPosition = 0;
int heartPosition = 0;
int spadePosition = 0;
private final int ACES_DIST_BETWEEN_CARDS = 87;
private final int ACES_DIST_FROM_LEFT = 350;
private final int ACES_DIST_FROM_TOP = 50;
private final int ACES_MAX = 611;
private final int PLAYCARDS_DIST_FROM_LEFT = 175;
private final int PLAYCARDS_DIST_FROM_TOP = 175;
private final int PLAYCARDS_DIST_BETWEEN_COLS = 87;
private final int PLAYCARDS_DIST_BETWEEN_ROWS_BACKS = 5;
private final int PLAYCARDS_DIST_BETWEEN_ROWS_FACES = 30;
private final int PLAYCARDS_MAX = 697;
private final int PILE_DIST_FROM_LEFT = 50;
private final int PILE_DIST_FROM_TOP = 50;
private final int SHOWCARD_DIST_FROM_LEFT = 50;
private final int SHOWCARD_DIST_FROM_TOP = 175;
private static final int CARD_WIDTH = 77;
private static final int CARD_HEIGHT = 110;
private final int CARDS_PER_SUIT = 13; //Suit limit
private final int CARDS_PER_DECK = 52; //Deck limit
private int initialX = 0; //x coord - set from drag
private int initialY = 0; //y coord - set from drag
private int _dragFromX = 0; //Displacement inside image of mouse press
private int _dragFromY = 0; //Displacement inside image of mouse press
private Card[] _club = new Card[CARDS_PER_SUIT]; //Creates an array of clubs
private Card[] _diamond = new Card[CARDS_PER_SUIT]; //Creates an array of diamonds
private Card[] _heart = new Card[CARDS_PER_SUIT]; //Creates an array of hearts
private Card[] _spade = new Card[CARDS_PER_SUIT]; //Creates an array of spades
private Card[] _deckFront = new Card[CARDS_PER_DECK]; //Creates an array of cardfronts
private Card[] _deckBack = new Card[CARDS_PER_DECK]; //Creates an array of cardbacks
private Card _currentCard = null; //Current draggable card
//====================================================NewSolitaireView constructor
public NewSolitaireView()
String suitC = "c"; //This is the character in the club image names that will be loaded
String suitD = "d"; //This is the character in the diamond image names that will be loaded
String suitH = "h"; //This is the character in the heart image names that will be loaded
String suitS = "s"; //This is the character in the spade image names that will be loaded
String faces = "a23456789tjqk"; //These are the characters in the face image names that will be loaded
int crdFrontPosition = 0;
//=========================================================Read in the clubs
for(int clubCounter = 0; clubCounter < suitC.length(); clubCounter ++)
for(int face = 0; face < faces.length(); face ++)
ImageIcon imgFront = new ImageIcon(faces.charAt(face) + suitC.charAt(clubCounter) + ".gif");
Image image = imgFront.getImage();
Image scaledImage = image.getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_FAST);
imgFront.setImage(scaledImage);
_club[clubPosition ++] = new Card(imgFront, initialX ++, initialY ++);
_deckFront[crdFrontPosition ++] = new Card(imgFront, initialX ++, initialY ++);
//=======================================================Read in the diamonds
for(int diamondCounter = 0; diamondCounter < suitD.length(); diamondCounter ++)
for(int face = 0; face < faces.length(); face ++)
ImageIcon imgFront = new ImageIcon(faces.charAt(face) + suitD.charAt(diamondCounter) + ".gif");
Image image = imgFront.getImage();
Image scaledImage = image.getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_FAST);
imgFront.setImage(scaledImage);
_diamond[diamondPosition ++] = new Card (imgFront, initialX ++, initialY ++);
_deckFront[crdFrontPosition ++] = new Card (imgFront, initialX ++, initialY ++);
//=======================================================Read in the hearts
for(int heartCounter = 0; heartCounter < suitH.length(); heartCounter ++)
for(int face = 0; face < faces.length(); face ++)
ImageIcon imgFront = new ImageIcon(faces.charAt(face) + suitH.charAt(heartCounter) + ".gif");
Image image = imgFront.getImage();
Image scaledImage = image.getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_FAST);
imgFront.setImage(scaledImage);
_heart[heartPosition ++] = new Card (imgFront, initialX ++, initialY ++);
_deckFront[crdFrontPosition ++] = new Card (imgFront, initialX ++, initialY ++);
//==========================================================Read in the spades
for(int spadeCounter = 0; spadeCounter < suitS.length(); spadeCounter ++)
for(int face = 0; face < faces.length(); face ++)
ImageIcon imgFront = new ImageIcon(faces.charAt(face) + suitS.charAt(spadeCounter) + ".gif");
Image image = imgFront.getImage();
Image scaledImage = image.getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_FAST);
imgFront.setImage(scaledImage);
_spade[spadePosition ++] = new Card (imgFront, initialX ++, initialY ++);
_deckFront[crdFrontPosition ++] = new Card (imgFront, initialX ++, initialY ++);
int crdBackPosition = 0;
//Load the card back image into an array of 52 cardbacks and resize each cardback
for(int crdBack = 0; crdBack < CARDS_PER_DECK; crdBack ++)
ImageIcon imgBack = new ImageIcon("b.gif");
Image image = imgBack.getImage();
Image scaledImage = image.getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_FAST);
imgBack.setImage(scaledImage);
_deckBack[crdBackPosition ++] = new Card (imgBack, initialX ++, initialY ++);
//============================================================Create buttons
JButton newGameButton = new JButton("New Game");
JButton exitButton = new JButton("Exit");
//========================================================Create controlPanel
JPanel controlPanel = new JPanel();
controlPanel.add(newGameButton);
controlPanel.add(exitButton);
//=======================================================Create GraphicsPanel
boardDisplay_ = new GraphicsPanel();
//======================================Set the layout and add the components
this.add(controlPanel);
this.add(boardDisplay_);
//===================================================Add listeners to buttons
exitButton.addActionListener(new ExitAction());
newGameButton.addActionListener(new NewGameAction());
}//==============================================end NewSolitaireView constructor
class GraphicsPanel extends JPanel //implements MouseListener
//===================================class GraphicsPanel constructor
public GraphicsPanel()
//Initialize graphics
this.setPreferredSize(new Dimension(850, 500));
this.setBackground(Color.white);
//this.addMouseListener(this);
}//=======================================end GraphicsPanel constructor
//=================================================method paintComponent
public void paintComponent(Graphics g)
super.paintComponent(g); //Required for background.
//update(g);
g.drawRect(PILE_DIST_FROM_LEFT, PILE_DIST_FROM_TOP, CARD_WIDTH, CARD_HEIGHT);
g.drawRect(SHOWCARD_DIST_FROM_LEFT, SHOWCARD_DIST_FROM_TOP, CARD_WIDTH, CARD_HEIGHT);
for(int position1 = ACES_DIST_FROM_LEFT; position1 <= ACES_MAX; position1 += ACES_DIST_BETWEEN_CARDS)
g.drawRect(position1, ACES_DIST_FROM_TOP, CARD_WIDTH, CARD_HEIGHT);
for(int position2 = PLAYCARDS_DIST_FROM_LEFT; position2 <= PLAYCARDS_MAX; position2 += PLAYCARDS_DIST_BETWEEN_COLS)
g.drawRect(position2, PLAYCARDS_DIST_FROM_TOP, CARD_WIDTH, CARD_HEIGHT);
//This is to test the card images, but they are not working
for(int k = 0; k < 51; k ++)
Card c = _deckFront[k];
c.image.paintIcon(this, g, c.x, c.y);
}//=====================================================end paintComponent method
}//========================================================end class GraphicsPanel
//======================================================================class Card
class Card
javax.swing.ImageIcon image;
int x;
int y;
public Card(javax.swing.ImageIcon image, int x, int y)
this.image = image;
this.x = x;
this.y = y;
}//=================================================================end class Card
//===========================================================inner class ExitAction
class ExitAction implements ActionListener
public void actionPerformed(ActionEvent e)
System.exit(0);
}//==========================================================end actionPerformed
}//=======================================================end inner class ExitAction
//=========================================================inner class NewGameAction
class NewGameAction implements ActionListener
public void actionPerformed(ActionEvent e)
gameLogic_.shuffle();
//gameLogic_.deal(Graphics g);
repaint();
}//===========================================================end actionPerformed
}//=====================================================end inner class NewGameAction
}//===========================================================end class NewSolitaireView
//==========================================
//==========================================
//NewSolitaireModel.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
//import javax.swing.ImageIcon.*;
//import java.awt.Image.*;
//import java.awt.Graphics.*;
class NewSolitaireModel
private NewSolitaireView gameGUI_ = new NewSolitaireView();
private final int ACES_DIST_BETWEEN_CARDS = 87;
private final int ACES_DIST_FROM_LEFT = 350;
private final int ACES_DIST_FROM_TOP = 50;
private final int ACES_MAX = 611;
private final int PLAYCARDS_DIST_FROM_LEFT = 175;
private final int PLAYCARDS_DIST_FROM_TOP = 175;
private final int PLAYCARDS_DIST_BETWEEN_COLS = 87;
private final int PLAYCARDS_DIST_BETWEEN_ROWS_BACKS = 5;
private final int PLAYCARDS_DIST_BETWEEN_ROWS_FACES = 30;
private final int PLAYCARDS_MAX = 697;
private final int PILE_DIST_FROM_LEFT = 50;
private final int PILE_DIST_FROM_TOP = 50;
private final int SHOWCARD_DIST_FROM_LEFT = 50;
private final int SHOWCARD_DIST_FROM_TOP = 175;
private final int FIRST_CARD_AFTER_DEAL = 29;
private final int CARDS_PER_DECK = 52; //Deck limit
private Card[] _deckFront = new Card[CARDS_PER_DECK]; //Creates an array of cardfronts
private Card[] _deckBack = new Card[CARDS_PER_DECK]; //Creates an array of cardbacks
//===============================================NewSolitaireModel constructor
public NewSolitaireModel()
shuffle();
//repaint();
}//==============================================end NewSolitaireModel constructor
public void deal(Graphics g)
//================================================Deal the cards for game play
//=========This is done initially and everytime the new game button is pressed
//===========================================Uses paintComponent for paintIcon
//========================Deal the first row of cards (top 7), first 1 face up
int crd1 = 1;
int col1 = PLAYCARDS_DIST_FROM_LEFT;
int fromTop1 = PLAYCARDS_DIST_FROM_TOP;
Card df = _deckFront[crd1];
ImageIcon icon;
//icon.paintIcon(df, g, col1, fromTop1);
//=========================================================next 6 face down
crd1 = 2;
col1 = col1 + PLAYCARDS_DIST_BETWEEN_COLS;
for(int count = 0; count < 6; count ++)
Card db = _deckBack[crd1];
//image.paintIcon(db, g, col1, fromTop1);
crd1 ++;
col1 += PLAYCARDS_DIST_BETWEEN_COLS;
//====================Deal the second row of cards (next 6), first 1 face up
int crd2 = 8;
int col2 = 262;
int fromTop2 = fromTop1 + PLAYCARDS_DIST_BETWEEN_ROWS_BACKS;
df = _deckFront[crd2];
//df.image.paintIcon(this, g, col2, fromTop2);
//==========================================================next 5 face down
crd2 = 9;
col2 = col2 + PLAYCARDS_DIST_BETWEEN_COLS;
for(int count = 0; count < 5; count ++)
Card db = _deckBack[crd2];
//db.image.paintIcon(this, g, col2, fromTop2);
crd2 ++;
col2 += PLAYCARDS_DIST_BETWEEN_COLS;
//======================Deal the third row of cards (next 5), first 1 face up
int crd3 = 14;
int col3 = 349;
int fromTop3 = fromTop2 + PLAYCARDS_DIST_BETWEEN_ROWS_BACKS;
df = _deckFront[crd3];
//df.image.paintIcon(this, g, col3, fromTop3);
//==========================================================next 4 face down
crd3 = 15;
col3 = col3 + PLAYCARDS_DIST_BETWEEN_COLS;
for(int count = 0; count < 4; count ++)
Card db = _deckBack[crd3];
//db.image.paintIcon(this, g, col3, fromTop3);
crd3 ++;
col3 += PLAYCARDS_DIST_BETWEEN_COLS;
//===================Deal the fourth row of cards (next 4), first 1 face up
int crd4 = 19;
int col4 = 436;
int fromTop4 = fromTop3 + PLAYCARDS_DIST_BETWEEN_ROWS_BACKS;
df = _deckFront[crd4];
//df.image.paintIcon(this, g, col4, fromTop4);
//========================================================next 3 face down
crd4 = 20;
col4 = col4 + PLAYCARDS_DIST_BETWEEN_COLS;
for(int count = 0; count < 3; count ++)
Card db = _deckBack[crd4];
//db.image.paintIcon(this, g, col4, fromTop4);
crd4 ++;
col4 += PLAYCARDS_DIST_BETWEEN_COLS;
//====================Deal the fifth row of cards (next 3), first 1 face up
int crd5 = 23;
int col5 = 523;
int fromTop5 = fromTop4 + PLAYCARDS_DIST_BETWEEN_ROWS_BACKS;
df = _deckFront[crd5];
//df.image.paintIcon(this, g, col5, fromTop5);
//==========================================================next 2 face down
crd5 = 24;
col5 = col5 + PLAYCARDS_DIST_BETWEEN_COLS;
for(int count = 0; count < 2; count ++)
Card db = _deckBack[crd5];
//db.image.paintIcon(this, g, col5, fromTop5);
crd5 ++;
col5 += PLAYCARDS_DIST_BETWEEN_COLS;
//====================Deal the sixth row of cards (next 2), first 1 face up
int crd6 = 26;
int col6 = 610;
int fromTop6 = fromTop5 + PLAYCARDS_DIST_BETWEEN_ROWS_BACKS;
df = _deckFront[crd6];
//df.image.paintIcon(this, g, col6, fromTop6);
//==================================================second 1 face down
crd6 = 27;
col6 = col6 + PLAYCARDS_DIST_BETWEEN_COLS;
for(int count = 0; count < 1; count ++)
Card db = _deckBack[crd6];
//db.image.paintIcon(this, g, col6, fromTop6);
crd6 ++;
col6 += PLAYCARDS_DIST_BETWEEN_COLS;
//====================Deal the seventh row of cards (next 1) face up
int crd7 = 28;
int col7 = 697;
int fromTop7 = fromTop6 + PLAYCARDS_DIST_BETWEEN_ROWS_BACKS;
df = _deckFront[crd7];
//df.image.paintIcon(this, g, col7, fromTop7);
//=============Put the undealt cards in the upper left stack to use for game play
for(int playCard = FIRST_CARD_AFTER_DEAL; playCard < CARDS_PER_DECK; playCard ++)
Card db = _deckBack[playCard];
//db.image.paintIcon(this, g, PILE_DIST_FROM_LEFT, PILE_DIST_FROM_TOP);
}//============================================================end method deal
//=============================================================method displayImage
private void displayImage(int k)
//Graphics g = getGraphics();
//=================================================================method shuffle
public void shuffle()
Random rgen = new Random(); // Random number generator
// Shuffle by exchanging each element randomly
for (int i = 0; i < CARDS_PER_DECK; i ++)
int randomPosition = rgen.nextInt(CARDS_PER_DECK);
Card temp = _deckFront;
_deckFront[i] = _deckFront[randomPosition];
_deckFront[randomPosition] = temp;
}//===============================================================end method shuffle
}//=============================================end class NewSolitaireModelI would have deal() in the model. I think that's where it belongs, because deal() should probably be distributing the cards in some random manner into some container (abstractly speaking). The view can then get the cards from that container when it's notified that the deal() happened...
public class DeckModel {
private List listeners = new ArrayList();
private List available = new ArrayList();
private List played = new ArrayList();
public void deal() {
// take all cards, shuffle them, put them into "available"
fireCardsShuffled();// listeners can then get from available and display them however
public void play(Card c) {
played.add(c);
available.remove(c);
fireCardsPlayed(c);
public void fireCardsPlayed(Card c) {
// notifiy listeners
for(int x = 0; x < listeners.size(); x++) {
((DeckListener)listeners.get(x)).cardPlayed(new DeckEvent(this, c));
public void fireCardsShuffled() {
// notifiy listeners
for(int x = 0; x < listeners.size(); x++) {
((DeckListener)listeners.get(x)).cardsShuffled(new DeckEvent(this, null));
public void addDeckListener(DeckListener dl) {
listeners.add(dl); // maybe have a remove method.
// deck listener, implemented by the view.
public interface DeckListener {
public void cardsShuffled(DeckEvent de);
public void cardPlayed(DeckEvent de);
}Something along those lines. -
I'm a just beginner in Swing.I want to draw a graph on a frame.My problem is.....:in the o/p window graph is just become disable afterit came.it will reappear whwn we maximize thhe o/p window...my part of code is following:
public void paint(Graphics g) {//main graph drawing part
super.paint(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for(i=0;i<ss2;i++){//assigning the the values of FROM node and TO node
pf=p[Integer.parseInt(str2[i][0])];
pt[i]=p[Integer.parseInt(str2[i][2])];
for(i=0;i<ss2;i++){//to print the value like a,b,c...
xf=pf[i].x;
yf=pf[i].y;
xt=pt[i].x;
yt=pt[i].y;
xm=(xf+xt*3)/4;
ym=((yf+yt*3)/4)-5;
sssss=str2[i][1].charAt(0);
g2.setColor(Color.black);
if(xf==xt&&yf==yt){
g2.drawArc(xf,yf,35,20,0,360);
g2.drawString(Character.toString(sssss),xf+15,yf+12);
else{
g2.drawLine(xf,yf,xt,yt);
g2.setColor(Color.black);
g2.drawString(Character.toString(sssss),xm,ym);
g2.fillOval(m,n,7,7);
for(i=0;i<sc1;i++) {//for loop to draw the circle class to draw circles
int _x;
int _y;
_x=(p[i].x-10);
_y=(p[i].y-10);
if(str1[i][3].equals("1")){
g2.setColor(Color.PINK);
g2.fillOval(_x, _y,20,20);
x=0;y=0;
else if(str1[i][3].equals("2")){
g2.setColor(Color.CYAN);
g2.fillOval(_x, y,20,20);x=0;_y=0;
else if(str1[i][3].equals("4")){
g2.setColor(Color.YELLOW);
g2.fillOval(_x, y,20,20);x=0;_y=0;
else{
g2.setColor(Color.ORANGE);
g2.fillOval(_x, y,20,20);x=0;_y=0;
for(i=0;i<sc1;i++){//to put the node name like 1,2...i'll changed it to Q0,Q1,... later
g2.setColor(Color.BLACK);
g2.drawString(Integer.toString(i),p[i].x,p[i].y);Comments:
If you had gone through the painting tutorial linked, you would know that custom painting is not normally performed on a JFrame. And knowing that, you would find no reason to extend JFrame.
If you had taken a look at the API you would know that JFrame doesn't have a method paintComponent.
If you had gone through the Swing tutorial linked, you would know about concurrency in Swing, and that the GUI should be launched on the EDT.
So. With the wealth of knowledge already available in the tutorials, do you really think forum members should waste their time teaching you the basics? Please go through the changed code and post back what you conclude about the differences that make it work.
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class FrameTest {
int px, py, ox, oy;
JFrame frame;
JPanel panel;
FrameTest(String title, int x1, int y1, int x2, int y2){
frame = new JFrame(title);
px = x1;
py = y1;
ox = x2;
oy = y2;
private void makeUI() {
panel = new JPanel() {
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawLine(px, py, ox, oy);
frame.setContentPane(panel);
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new FrameTest("Show", 10, 10, 100, 100).makeUI();
}db -
Hi, in my code. I want to plot a 2D object, a JSlider and two comb box.
But the 2D object can't displayed correctly, can you look at my code?
Please don't provide the link of sun swing tutorial, I have studied many times, but no achievement.
import java.awt.event.*;
import javax.swing.event.*;
import java.applet.Applet;
public class Combox extends JApplet{
private JSlider dJSlider;
private JComboBox comb;
private JComboBox alfa;
private Container panel;
public void init()
panel = getContentPane();
drawing = new Drawing(a,id,scale);
JPanel p2 = new JPanel();
panel.add(p2);
p2.add(drawing);// this drawing can't be plotted,only a small white square is showed.
p2.add(new getSlider(),BorderLayout.NORTH);
p2.add(new getComboPanel(),BorderLayout.EAST);
class getSlider extends JPanel {
public getSlider(){
add(dJSlider);
class getComboPanel extends JPanel {
public getComboPanel(){
comb = new JComboBox(e);
layout = new GridBagLayout();
setLayout(layout);
alfa = new JComboBox(af);
add(comb);
add(alfa);
class Drawing extends JPanel
// plot 2D
public static void main(String[] args)
JFrame a = new JFrame("show");
Applet b = new Combox();
}But if the code becomes
public void init()
panel = getContentPane();
drawing = new Drawing(a,id,scale);
panel.add(drawing);
panel.add(new getSlider(),BorderLayout.NORTH);
panel.add(new getComboPanel(),BorderLayout.EAST);
}the plot is right.why?
Thanksdrawing will plot a ploygon and fill a ploygon.(contains two methods)
drawPolygon(g2d);
drawSides(g2d);pets1234, you have traced my poster so long.
here is the Drawing class.
class Drawing extends JPanel
final int TRANSITION = 100; // Transition x,y coordinates of cells.
private double x1, y1, x2, y2; // to plot lines from (x1,y1) to (x2,y2)
private double xCells[][]; // Every cell's points's x coordinates array
private double yCells[][]; // Every cell's points's y coordinates array
private double rgb[][]; // Color red, green, blue for each point in each cell
private double red[][];
private double green[][];
private double blue[][];
private double lineWidth;
private int sideId;
private int sidesTotalNumber; // Total sides number for all cells
private int rgbLength; // Total rgb color group number for all cells at each point
private int cellsPointsNumber[]; // point numbers of each cell.(each cell has how many points)
private int numberofCells;
private int numberofsets;
int a,id;
double scale;
Drawing(int a, int id, double scale)
{ this.a = a;
this.id = id;
this.scale = scale;
public void setscale(double scale)
this.scale = scale;
repaint();
public void setid(int id)
this.id = id;
repaint();
public void seta(int a)
this.a = a;
repaint();
public void paintComponent(Graphics g)
super.paintComponent( g ); // call superclass's paint method
this.setBackground( Color.WHITE );
Graphics2D g2d = (Graphics2D)g; // cast g to Graphics 2D
getDrawingData();
if (a==0)
drawPolygon(g2d);
drawSides(g2d);
// end method paintComponent
public void getDrawingData()
TestCell p = new TestCell();
p.cellData();
p.rgbs();
xCells = p.getxCells();
yCells = p.getyCells();
sidesTotalNumber = p.getsidesTotalNumber();
red = p.getred();
green = p.getgreen();
blue = p.getblue();
rgbLength = p.getrgbLength();
cellsPointsNumber = p.getcellsPointsNumber();//array: each cell has how many points
numberofCells = p.getnumberofCells();
numberofsets = p.getnumberofsets();
for(int i = 0; i < numberofCells; i++)
for(int j = 0; j<cellsPointsNumber; j++)
xCells[i][j] = (xCells[i][j])*scale+TRANSITION;
yCells[i][j] = (yCells[i][j])*scale+TRANSITION;
public void drawSides(Graphics2D g2d)
g2d.setColor(Color.GRAY);
g2d.setStroke(new BasicStroke((float)lineWidth));
for (int i = 0; i<numberofCells; i++)
for (int j = 0; j<cellsPointsNumber[i]-1; j++)
x1 = xCells[i][j];
y1 = yCells[i][j];
x2 = xCells[i][j+1];
y2 = yCells[i][j+1];
Line2D line = new Line2D.Double(x1,y1,x2,y2);
g2d.draw(line);// draw Sidess here
public void drawPolygon(Graphics2D g2d)
for (int i = 0; i<numberofCells; i++)
Polygon poly = new Polygon();
float r = (float)red[i][id];
// red for ith cell,id is from 0 to numberofsets-1
// if id=0, means "Mixture"
float g = (float)green[i][id]; // green for ith cell
float b = (float)blue[i][id]; // blue for ith cell
List<Integer> xList = new ArrayList<Integer>();
List<Integer> yList = new ArrayList<Integer>();
for (int j = 0; j<cellsPointsNumber[i]; j++)
xList.add((int)(xCells[i][j]));
yList.add((int)(yCells[i][j]));
Integer[] x = xList.toArray(new Integer[xList.size()]);
Integer[] y = yList.toArray(new Integer[yList.size()]);
for (int s = 0; s<xList.size(); s++)
poly.addPoint(x[s],y[s]);
g2d.setColor(new Color(r, g, b));// transparent drawing
g2d.fillPolygon(poly); -
Hi
I used Deitel's code of TicTacToe program that creats a server and have 2 clients playing TicTacToe. When the game is over one of the client has to click on new game and a new game will begin. I don't know how to do this.
Please Help.
Here's the code for the server
import java.awt.BorderLayout;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.util.Formatter;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TicTacToeServer extends JFrame
private String[] board = new String[ 9 ]; // tic-tac-toe board
private JTextArea outputArea; // for outputting moves
private Player[] players; // array of Players
private ServerSocket server; // server socket to connect with clients
private int currentPlayer; // keeps track of player with current move
private final static int PLAYER_X = 0; // constant for first player
private final static int PLAYER_O = 1; // constant for second player
private final static String[] MARKS = { "X", "O" }; // array of marks
private ExecutorService runGame; // will run players
private Lock gameLock; // to lock game for synchronization
private Condition otherPlayerConnected; // to wait for other player
private Condition otherPlayerTurn; // to wait for other player's turn
// set up tic-tac-toe server and GUI that displays messages
public TicTacToeServer()
super( "Tic-Tac-Toe Server" ); // set title of window
// create ExecutorService with a thread for each player
runGame = Executors.newFixedThreadPool( 2 );
gameLock = new ReentrantLock(); // create lock for game
// condition variable for both players being connected
otherPlayerConnected = gameLock.newCondition();
// condition variable for the other player's turn
otherPlayerTurn = gameLock.newCondition();
for ( int i = 0; i < 9; i++ )
board[ i ] = new String( "" ); // create tic-tac-toe board
players = new Player[ 2 ]; // create array of players
currentPlayer = PLAYER_X; // set current player to first player
try
server = new ServerSocket( 12345, 2 ); // set up ServerSocket
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
outputArea = new JTextArea(); // create JTextArea for output
add( outputArea, BorderLayout.CENTER );
outputArea.setText( "Server awaiting connections\n" );
setSize( 300, 300 ); // set size of window
setVisible( true ); // show window
} // end TicTacToeServer constructor
// wait for two connections so game can be played
public void execute()
// wait for each client to connect
for ( int i = 0; i < players.length; i++ )
try // wait for connection, create Player, start runnable
players[ i ] = new Player( server.accept(), i );
runGame.execute( players[ i ] ); // execute player runnable
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end for
gameLock.lock(); // lock game to signal player X's thread
try
players[ PLAYER_X ].setSuspended( false ); // resume player X
otherPlayerConnected.signal(); // wake up player X's thread
} // end try
finally
gameLock.unlock(); // unlock game after signalling player X
} // end finally
} // end method execute
// display message in outputArea
private void displayMessage( final String messageToDisplay )
// display message from event-dispatch thread of execution
SwingUtilities.invokeLater(
new Runnable()
public void run() // updates outputArea
outputArea.append( messageToDisplay ); // add message
} // end method run
} // end inner class
); // end call to SwingUtilities.invokeLater
} // end method displayMessage
// determine if move is valid
public boolean validateAndMove( int location, int player )
// while not current player, must wait for turn
while ( player != currentPlayer )
gameLock.lock(); // lock game to wait for other player to go
try
otherPlayerTurn.await(); // wait for player's turn
} // end try
catch ( InterruptedException exception )
exception.printStackTrace();
} // end catch
finally
gameLock.unlock(); // unlock game after waiting
} // end finally
} // end while
// if location not occupied, make move
if ( !isOccupied( location ) )
board[ location ] = MARKS[ currentPlayer ]; // set move on board
currentPlayer = ( currentPlayer + 1 ) % 2; // change player
// let new current player know that move occurred
players[ currentPlayer ].otherPlayerMoved( location );
gameLock.lock(); // lock game to signal other player to go
try
otherPlayerTurn.signal(); // signal other player to continue
} // end try
finally
gameLock.unlock(); // unlock game after signaling
} // end finally
return true; // notify player that move was valid
} // end if
else // move was not valid
return false; // notify player that move was invalid
} // end method validateAndMove
// determine whether location is occupied
public boolean isOccupied( int location )
if ( board[ location ].equals( MARKS[ PLAYER_X ] ) ||
board [ location ].equals( MARKS[ PLAYER_O ] ) )
return true; // location is occupied
else
return false; // location is not occupied
} // end method isOccupied
// place code in this method to determine whether game over
public boolean isGameOver()
if( ( !board[ 0 ].equals( "" ) &&
!board[ 1 ].equals( "" ) &&
!board[ 2 ].equals( "" ) &&
!board[ 3 ].equals( "" ) &&
!board[ 4 ].equals( "" ) &&
!board[ 5 ].equals( "" ) &&
!board[ 6 ].equals( "" ) &&
!board[ 7 ].equals( "" ) &&
!board[ 8 ].equals( "" ) ) )
players[0].gameOver("Game Over, no winner");
players[1].gameOver("Game Over, no winner");
return true;
else if( board[ 0 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 1 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 2 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 0 ].equals( MARKS[ PLAYER_O ]) &&
board [ 1 ].equals( MARKS[ PLAYER_O ]) &&
board [ 2 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 3 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 4 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 5 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 3 ].equals( MARKS[ PLAYER_O ]) &&
board [ 4 ].equals( MARKS[ PLAYER_O ]) &&
board [ 5 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 6 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 7 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 8 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 6 ].equals( MARKS[ PLAYER_O ]) &&
board [ 7 ].equals( MARKS[ PLAYER_O ]) &&
board [ 8 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 0 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 3 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 6 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board[ 0 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 3 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 6 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 1 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 4 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 7 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 1 ].equals( MARKS[ PLAYER_O ]) &&
board [ 4 ].equals( MARKS[ PLAYER_O ]) &&
board [ 7 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 2 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 5 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 8 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 2 ].equals( MARKS[ PLAYER_O ]) &&
board [ 5 ].equals( MARKS[ PLAYER_O ]) &&
board [ 8 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 0 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 4 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 8 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 0 ].equals( MARKS[ PLAYER_O ]) &&
board [ 4 ].equals( MARKS[ PLAYER_O ]) &&
board [ 8 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 2 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 4 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 8 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 2 ].equals( MARKS[ PLAYER_O ]) &&
board [ 4 ].equals( MARKS[ PLAYER_O ]) &&
board [ 8 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else
return false; // this is left as an exercise
} // end method isGameOver
// private inner class Player manages each Player as a runnable
private class Player implements Runnable
private Socket connection; // connection to client
private Scanner input; // input from client
private Formatter output; // output to client
private int playerNumber; // tracks which player this is
private String mark; // mark for this player
private boolean suspended = true; // whether thread is suspended
// set up Player thread
public Player( Socket socket, int number )
playerNumber = number; // store this player's number
mark = MARKS[ playerNumber ]; // specify player's mark
connection = socket; // store socket for client
try // obtain streams from Socket
input = new Scanner( connection.getInputStream() );
output = new Formatter( connection.getOutputStream() );
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end Player constructor
// send message that other player moved
public void otherPlayerMoved( int location )
output.format( "Opponent moved\n" );
output.format( "%d\n", location ); // send location of move
output.flush(); // flush output
} // end method otherPlayerMoved
// control thread's execution
public void run()
// send client its mark (X or O), process messages from client
try
displayMessage( "Player " + mark + " connected\n" );
output.format( "%s\n", mark ); // send player's mark
output.flush(); // flush output
// if player X, wait for another player to arrive
if ( playerNumber == PLAYER_X )
output.format( "%s\n%s", "Player X connected",
"Waiting for another player\n" );
output.flush(); // flush output
gameLock.lock(); // lock game to wait for second player
try
while( suspended )
otherPlayerConnected.await(); // wait for player O
} // end while
} // end try
catch ( InterruptedException exception )
exception.printStackTrace();
} // end catch
finally
gameLock.unlock(); // unlock game after second player
} // end finally
// send message that other player connected
output.format( "Other player connected. Your move.\n" );
output.flush(); // flush output
} // end if
else
output.format( "Player O connected, please wait\n" );
output.flush(); // flush output
} // end else
// while game not over
while ( !isGameOver() )
int location = 0; // initialize move location
if ( input.hasNext() )
location = input.nextInt(); // get move location
// check for valid move
if ( validateAndMove( location, playerNumber ) )
displayMessage( "\nlocation: " + location );
output.format( "Valid move.\n" ); // notify client
output.flush(); // flush output
} // end if
else // move was invalid
output.format( "Invalid move, try again\n" );
output.flush(); // flush output
} // end else
} // end while
} // end try
finally
try
connection.close(); // close connection to client
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end finally
} // end method run
// set whether or not thread is suspended
public void setSuspended( boolean status )
suspended = status; // set value of suspended
} // end method setSuspended
public void gameOver(String msg)
if(msg.equals("Game Over, no winner"))
if ( playerNumber == PLAYER_X )
output.format( "no winner, you loose\n" );
output.flush(); // flush output
} // end if
else
output.format( "no winner, you loose\n" );
output.flush(); // flush output
} // end else
gameLock.lock();
else if(msg.equals("Player X wins"))
if ( playerNumber == PLAYER_X )
output.format(msg + "\n" );
output.flush(); // flush output
} // end if
else
output.format(msg + ", you loose\n" );
output.flush(); // flush output
} // end else
gameLock.lock();
else if(msg.equals("Player O wins"))
if ( playerNumber == PLAYER_X )
//players[1].
output.format(msg + ", you loose\n" );
output.flush(); // flush output
} // end if
else
output.format(msg + "\n" );
output.flush(); // flush output
} // end else
gameLock.lock();
else
} // end class Player
} // end class TicTacToeServer
*****and here's the code for the client
// Fig. 24.15: TicTacToeClient.java
// Client that let a user play Tic-Tac-Toe with another across a network.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.*;
import java.net.Socket;
import java.net.InetAddress;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import java.util.Formatter;
import java.util.Scanner;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class TicTacToeClient extends JFrame implements Runnable
private JTextField idField; // textfield to display player's mark
private JTextArea displayArea; // JTextArea to display output
private JPanel boardPanel; // panel for tic-tac-toe board
private JPanel panel2; // panel to hold board
private JButton btnNew;
private Square board[][]; // tic-tac-toe board
private Square currentSquare; // current square
private Socket connection; // connection to server
private Scanner input; // input from server
private Formatter output; // output to server
private String ticTacToeHost; // host name for server
private String myMark; // this client's mark
private boolean myTurn; // determines which client's turn it is
private final String X_MARK = "X"; // mark for first client
private final String O_MARK = "O"; // mark for second client
// set up user-interface and board
public TicTacToeClient( String host )
ticTacToeHost = host; // set name of server
displayArea = new JTextArea( 4, 30 ); // set up JTextArea
displayArea.setEditable( false );
add( new JScrollPane( displayArea ), BorderLayout.SOUTH );
boardPanel = new JPanel(); // set up panel for squares in board
boardPanel.setLayout( new GridLayout( 3, 3, 0, 0 ) );
board = new Square[ 3 ][ 3 ]; // create board
// loop over the rows in the board
for ( int row = 0; row < board.length; row++ )
// loop over the columns in the board
for ( int column = 0; column < board[ row ].length; column++ )
// create square
board[ row ][ column ] = new Square( " ", row * 3 + column );
boardPanel.add( board[ row ][ column ] ); // add square
} // end inner for
} // end outer for
idField = new JTextField(); // set up textfield
idField.setEditable( false );
add( idField, BorderLayout.NORTH );
panel2 = new JPanel(); // set up panel to contain boardPanel
btnNew = new JButton("New Game");
panel2.add(btnNew, BorderLayout.NORTH);
panel2.add( boardPanel, BorderLayout.CENTER ); // add board panel
add( panel2, BorderLayout.CENTER ); // add container panel
btnNew.setEnabled(false);
btnNew.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
newGame();
setSize( 300, 225 ); // set size of window
setVisible( true ); // show window
startClient();
} // end TicTacToeClient constructor
// start the client thread
public void startClient()
try // connect to server, get streams and start outputThread
// make connection to server
connection = new Socket(
InetAddress.getByName( ticTacToeHost ), 12345 );
// get streams for input and output
input = new Scanner( connection.getInputStream() );
output = new Formatter( connection.getOutputStream() );
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
} // end catch
// create and start worker thread for this client
ExecutorService worker = Executors.newFixedThreadPool( 1 );
worker.execute( this ); // execute client
} // end method startClient
// control thread that allows continuous update of displayArea
public void run()
myMark = input.nextLine(); // get player's mark (X or O)
SwingUtilities.invokeLater(
new Runnable()
public void run()
// display player's mark
idField.setText( "You are player \"" + myMark + "\"" );
} // end method run
} // end anonymous inner class
); // end call to SwingUtilities.invokeLater
myTurn = ( myMark.equals( X_MARK ) ); // determine if client's turn
// receive messages sent to client and output them
while ( true )
if ( input.hasNextLine() )
processMessage( input.nextLine() );
} // end while
} // end method run
// process messages received by client
private void processMessage( String message )
// valid move occurred
if ( message.equals( "Valid move." ) )
displayMessage( "Valid move, please wait.\n" );
setMark( currentSquare, myMark ); // set mark in square
} // end if
else if ( message.equals( "Invalid move, try again" ) )
displayMessage( message + "\n" ); // display invalid move
myTurn = true; // still this client's turn
} // end else if
else if ( message.equals( "Opponent moved" ) )
int location = input.nextInt(); // get move location
input.nextLine(); // skip newline after int location
int row = location / 3; // calculate row
int column = location % 3; // calculate column
setMark( board[ row ][ column ],
( myMark.equals( X_MARK ) ? O_MARK : X_MARK ) ); // mark move
displayMessage( "Opponent moved. Your turn.\n" );
myTurn = true; // now this client's turn
} // end else if
//Game Over #*********Here**********#
else if ( message.equals( "no winner, you loose" ) )
btnNew.setEnabled(true);
myTurn = false;
} // end else if
else if ( message.equals( "Player X wins" ) ||
message.equals( "Player X wins, you loose" ) )
btnNew.setEnabled(true);
myTurn = false;
} // end else if
else if ( message.equals( "Player O wins" ) ||
message.equals( "Player O wins, you loose" ) )
btnNew.setEnabled(true);
myTurn = false;
} // end else if
else
displayMessage( message + "\n" ); // display the message
} // end method processMessage
//start a new game here
private void newGame()
// manipulate outputArea in event-dispatch thread
private void displayMessage( final String messageToDisplay )
SwingUtilities.invokeLater(
new Runnable()
public void run()
displayArea.append( messageToDisplay ); // updates output
} // end method run
} // end inner class
); // end call to SwingUtilities.invokeLater
} // end method displayMessage
// utility method to set mark on board in event-dispatch thread
private void setMark( final Square squareToMark, final String mark )
SwingUtilities.invokeLater(
new Runnable()
public void run()
squareToMark.setMark( mark ); // set mark in square
} // end method run
} // end anonymous inner class
); // end call to SwingUtilities.invokeLater
} // end method setMark
// send message to server indicating clicked square
public void sendClickedSquare( int location )
// if it is my turn
if ( myTurn )
output.format( "%d\n", location ); // send location to server
output.flush();
myTurn = false; // not my turn anymore
} // end if
} // end method sendClickedSquare
// set current Square
public void setCurrentSquare( Square square )
currentSquare = square; // set current square to argument
} // end method setCurrentSquare
// private inner class for the squares on the board
private class Square extends JPanel
private String mark; // mark to be drawn in this square
private int location; // location of square
public Square( String squareMark, int squareLocation )
mark = squareMark; // set mark for this square
location = squareLocation; // set location of this square
addMouseListener(
new MouseAdapter() {
public void mouseReleased( MouseEvent e )
setCurrentSquare( Square.this ); // set current square
// send location of this square
sendClickedSquare( getSquareLocation() );
} // end method mouseReleased
} // end anonymous inner class
); // end call to addMouseListener
} // end Square constructor
// return preferred size of Square
public Dimension getPreferredSize()
return new Dimension( 30, 30 ); // return preferred size
} // end method getPreferredSize
// return minimum size of Square
public Dimension getMinimumSize()
return getPreferredSize(); // return preferred size
} // end method getMinimumSize
// set mark for Square
public void setMark( String newMark )
mark = newMark; // set mark of square
repaint(); // repaint square
} // end method setMark
// return Square location
public int getSquareLocation()
return location; // return location of square
} // end method getSquareLocation
// draw Square
public void paintComponent( Graphics g )
super.paintComponent( g );
g.drawRect( 0, 0, 29, 29 ); // draw square
g.drawString( mark, 11, 20 ); // draw mark
} // end method paintComponent
} // end inner-class Square
} // end class TicTacToeClient
Please any kind of help will be appreciated.
HELP!!!I would be happy to help you, but I've decided not to contribute here anymore because of the poor way in which this site is being administered.
Others are still helping, but more may leave if things don't improve. May I recommend devshed or javaranch?
http://www.devshed.com/
http://www.javaranch.com/
If you would like to complain to the amdins of this forum, either click the "Report Abuse" link or the "Feedback" link. -
Hi
I used Deitel's code of TicTacToe program that creats a server and have 2 clients playing TicTacToe. When the game is over one of the client has to click on new game and a new game will begin. I don't know how to do this.
Please Help.
Here's the code for the server
import java.awt.BorderLayout;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.util.Formatter;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TicTacToeServer extends JFrame
private String[] board = new String[ 9 ]; // tic-tac-toe board
private JTextArea outputArea; // for outputting moves
private Player[] players; // array of Players
private ServerSocket server; // server socket to connect with clients
private int currentPlayer; // keeps track of player with current move
private final static int PLAYER_X = 0; // constant for first player
private final static int PLAYER_O = 1; // constant for second player
private final static String[] MARKS = { "X", "O" }; // array of marks
private ExecutorService runGame; // will run players
private Lock gameLock; // to lock game for synchronization
private Condition otherPlayerConnected; // to wait for other player
private Condition otherPlayerTurn; // to wait for other player's turn
// set up tic-tac-toe server and GUI that displays messages
public TicTacToeServer()
super( "Tic-Tac-Toe Server" ); // set title of window
// create ExecutorService with a thread for each player
runGame = Executors.newFixedThreadPool( 2 );
gameLock = new ReentrantLock(); // create lock for game
// condition variable for both players being connected
otherPlayerConnected = gameLock.newCondition();
// condition variable for the other player's turn
otherPlayerTurn = gameLock.newCondition();
for ( int i = 0; i < 9; i++ )
board[ i ] = new String( "" ); // create tic-tac-toe board
players = new Player[ 2 ]; // create array of players
currentPlayer = PLAYER_X; // set current player to first player
try
server = new ServerSocket( 12345, 2 ); // set up ServerSocket
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
outputArea = new JTextArea(); // create JTextArea for output
add( outputArea, BorderLayout.CENTER );
outputArea.setText( "Server awaiting connections\n" );
setSize( 300, 300 ); // set size of window
setVisible( true ); // show window
} // end TicTacToeServer constructor
// wait for two connections so game can be played
public void execute()
// wait for each client to connect
for ( int i = 0; i < players.length; i++ )
try // wait for connection, create Player, start runnable
players[ i ] = new Player( server.accept(), i );
runGame.execute( players[ i ] ); // execute player runnable
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end for
gameLock.lock(); // lock game to signal player X's thread
try
players[ PLAYER_X ].setSuspended( false ); // resume player X
otherPlayerConnected.signal(); // wake up player X's thread
} // end try
finally
gameLock.unlock(); // unlock game after signalling player X
} // end finally
} // end method execute
// display message in outputArea
private void displayMessage( final String messageToDisplay )
// display message from event-dispatch thread of execution
SwingUtilities.invokeLater(
new Runnable()
public void run() // updates outputArea
outputArea.append( messageToDisplay ); // add message
} // end method run
} // end inner class
); // end call to SwingUtilities.invokeLater
} // end method displayMessage
// determine if move is valid
public boolean validateAndMove( int location, int player )
// while not current player, must wait for turn
while ( player != currentPlayer )
gameLock.lock(); // lock game to wait for other player to go
try
otherPlayerTurn.await(); // wait for player's turn
} // end try
catch ( InterruptedException exception )
exception.printStackTrace();
} // end catch
finally
gameLock.unlock(); // unlock game after waiting
} // end finally
} // end while
// if location not occupied, make move
if ( !isOccupied( location ) )
board[ location ] = MARKS[ currentPlayer ]; // set move on board
currentPlayer = ( currentPlayer + 1 ) % 2; // change player
// let new current player know that move occurred
players[ currentPlayer ].otherPlayerMoved( location );
gameLock.lock(); // lock game to signal other player to go
try
otherPlayerTurn.signal(); // signal other player to continue
} // end try
finally
gameLock.unlock(); // unlock game after signaling
} // end finally
return true; // notify player that move was valid
} // end if
else // move was not valid
return false; // notify player that move was invalid
} // end method validateAndMove
// determine whether location is occupied
public boolean isOccupied( int location )
if ( board[ location ].equals( MARKS[ PLAYER_X ] ) ||
board [ location ].equals( MARKS[ PLAYER_O ] ) )
return true; // location is occupied
else
return false; // location is not occupied
} // end method isOccupied
// place code in this method to determine whether game over
public boolean isGameOver()
if( ( !board[ 0 ].equals( "" ) &&
!board[ 1 ].equals( "" ) &&
!board[ 2 ].equals( "" ) &&
!board[ 3 ].equals( "" ) &&
!board[ 4 ].equals( "" ) &&
!board[ 5 ].equals( "" ) &&
!board[ 6 ].equals( "" ) &&
!board[ 7 ].equals( "" ) &&
!board[ 8 ].equals( "" ) ) )
players[0].gameOver("Game Over, no winner");
players[1].gameOver("Game Over, no winner");
return true;
else if( board[ 0 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 1 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 2 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 0 ].equals( MARKS[ PLAYER_O ]) &&
board [ 1 ].equals( MARKS[ PLAYER_O ]) &&
board [ 2 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 3 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 4 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 5 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 3 ].equals( MARKS[ PLAYER_O ]) &&
board [ 4 ].equals( MARKS[ PLAYER_O ]) &&
board [ 5 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 6 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 7 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 8 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 6 ].equals( MARKS[ PLAYER_O ]) &&
board [ 7 ].equals( MARKS[ PLAYER_O ]) &&
board [ 8 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 0 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 3 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 6 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board[ 0 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 3 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 6 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 1 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 4 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 7 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 1 ].equals( MARKS[ PLAYER_O ]) &&
board [ 4 ].equals( MARKS[ PLAYER_O ]) &&
board [ 7 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 2 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 5 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 8 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 2 ].equals( MARKS[ PLAYER_O ]) &&
board [ 5 ].equals( MARKS[ PLAYER_O ]) &&
board [ 8 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 0 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 4 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 8 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 0 ].equals( MARKS[ PLAYER_O ]) &&
board [ 4 ].equals( MARKS[ PLAYER_O ]) &&
board [ 8 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else if( board[ 2 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 4 ].equals( MARKS[ PLAYER_X ] ) &&
board[ 8 ].equals( MARKS[ PLAYER_X ] ) )
players[0].gameOver("Player X wins");
players[1].gameOver("Player X wins");
return true;
else if( board [ 2 ].equals( MARKS[ PLAYER_O ]) &&
board [ 4 ].equals( MARKS[ PLAYER_O ]) &&
board [ 8 ].equals( MARKS[ PLAYER_O ]) )
players[0].gameOver("Player O wins");
players[1].gameOver("Player O wins");
return true;
else
return false; // this is left as an exercise
} // end method isGameOver
// private inner class Player manages each Player as a runnable
private class Player implements Runnable
private Socket connection; // connection to client
private Scanner input; // input from client
private Formatter output; // output to client
private int playerNumber; // tracks which player this is
private String mark; // mark for this player
private boolean suspended = true; // whether thread is suspended
// set up Player thread
public Player( Socket socket, int number )
playerNumber = number; // store this player's number
mark = MARKS[ playerNumber ]; // specify player's mark
connection = socket; // store socket for client
try // obtain streams from Socket
input = new Scanner( connection.getInputStream() );
output = new Formatter( connection.getOutputStream() );
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end Player constructor
// send message that other player moved
public void otherPlayerMoved( int location )
output.format( "Opponent moved\n" );
output.format( "%d\n", location ); // send location of move
output.flush(); // flush output
} // end method otherPlayerMoved
// control thread's execution
public void run()
// send client its mark (X or O), process messages from client
try
displayMessage( "Player " + mark + " connected\n" );
output.format( "%s\n", mark ); // send player's mark
output.flush(); // flush output
// if player X, wait for another player to arrive
if ( playerNumber == PLAYER_X )
output.format( "%s\n%s", "Player X connected",
"Waiting for another player\n" );
output.flush(); // flush output
gameLock.lock(); // lock game to wait for second player
try
while( suspended )
otherPlayerConnected.await(); // wait for player O
} // end while
} // end try
catch ( InterruptedException exception )
exception.printStackTrace();
} // end catch
finally
gameLock.unlock(); // unlock game after second player
} // end finally
// send message that other player connected
output.format( "Other player connected. Your move.\n" );
output.flush(); // flush output
} // end if
else
output.format( "Player O connected, please wait\n" );
output.flush(); // flush output
} // end else
// while game not over
while ( !isGameOver() )
int location = 0; // initialize move location
if ( input.hasNext() )
location = input.nextInt(); // get move location
// check for valid move
if ( validateAndMove( location, playerNumber ) )
displayMessage( "\nlocation: " + location );
output.format( "Valid move.\n" ); // notify client
output.flush(); // flush output
} // end if
else // move was invalid
output.format( "Invalid move, try again\n" );
output.flush(); // flush output
} // end else
} // end while
} // end try
finally
try
connection.close(); // close connection to client
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end finally
} // end method run
// set whether or not thread is suspended
public void setSuspended( boolean status )
suspended = status; // set value of suspended
} // end method setSuspended
public void gameOver(String msg)
if(msg.equals("Game Over, no winner"))
if ( playerNumber == PLAYER_X )
output.format( "no winner, you loose\n" );
output.flush(); // flush output
} // end if
else
output.format( "no winner, you loose\n" );
output.flush(); // flush output
} // end else
gameLock.lock();
else if(msg.equals("Player X wins"))
if ( playerNumber == PLAYER_X )
output.format(msg + "\n" );
output.flush(); // flush output
} // end if
else
output.format(msg + ", you loose\n" );
output.flush(); // flush output
} // end else
gameLock.lock();
else if(msg.equals("Player O wins"))
if ( playerNumber == PLAYER_X )
//players[1].
output.format(msg + ", you loose\n" );
output.flush(); // flush output
} // end if
else
output.format(msg + "\n" );
output.flush(); // flush output
} // end else
gameLock.lock();
else
} // end class Player
} // end class TicTacToeServer
*****and here's the code for the client
// Fig. 24.15: TicTacToeClient.java
// Client that let a user play Tic-Tac-Toe with another across a network.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.*;
import java.net.Socket;
import java.net.InetAddress;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import java.util.Formatter;
import java.util.Scanner;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class TicTacToeClient extends JFrame implements Runnable
private JTextField idField; // textfield to display player's mark
private JTextArea displayArea; // JTextArea to display output
private JPanel boardPanel; // panel for tic-tac-toe board
private JPanel panel2; // panel to hold board
private JButton btnNew;
private Square board[][]; // tic-tac-toe board
private Square currentSquare; // current square
private Socket connection; // connection to server
private Scanner input; // input from server
private Formatter output; // output to server
private String ticTacToeHost; // host name for server
private String myMark; // this client's mark
private boolean myTurn; // determines which client's turn it is
private final String X_MARK = "X"; // mark for first client
private final String O_MARK = "O"; // mark for second client
// set up user-interface and board
public TicTacToeClient( String host )
ticTacToeHost = host; // set name of server
displayArea = new JTextArea( 4, 30 ); // set up JTextArea
displayArea.setEditable( false );
add( new JScrollPane( displayArea ), BorderLayout.SOUTH );
boardPanel = new JPanel(); // set up panel for squares in board
boardPanel.setLayout( new GridLayout( 3, 3, 0, 0 ) );
board = new Square[ 3 ][ 3 ]; // create board
// loop over the rows in the board
for ( int row = 0; row < board.length; row++ )
// loop over the columns in the board
for ( int column = 0; column < board[ row ].length; column++ )
// create square
board[ row ][ column ] = new Square( " ", row * 3 + column );
boardPanel.add( board[ row ][ column ] ); // add square
} // end inner for
} // end outer for
idField = new JTextField(); // set up textfield
idField.setEditable( false );
add( idField, BorderLayout.NORTH );
panel2 = new JPanel(); // set up panel to contain boardPanel
btnNew = new JButton("New Game");
panel2.add(btnNew, BorderLayout.NORTH);
panel2.add( boardPanel, BorderLayout.CENTER ); // add board panel
add( panel2, BorderLayout.CENTER ); // add container panel
btnNew.setEnabled(false);
btnNew.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
newGame();
setSize( 300, 225 ); // set size of window
setVisible( true ); // show window
startClient();
} // end TicTacToeClient constructor
// start the client thread
public void startClient()
try // connect to server, get streams and start outputThread
// make connection to server
connection = new Socket(
InetAddress.getByName( ticTacToeHost ), 12345 );
// get streams for input and output
input = new Scanner( connection.getInputStream() );
output = new Formatter( connection.getOutputStream() );
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
} // end catch
// create and start worker thread for this client
ExecutorService worker = Executors.newFixedThreadPool( 1 );
worker.execute( this ); // execute client
} // end method startClient
// control thread that allows continuous update of displayArea
public void run()
myMark = input.nextLine(); // get player's mark (X or O)
SwingUtilities.invokeLater(
new Runnable()
public void run()
// display player's mark
idField.setText( "You are player \"" + myMark + "\"" );
} // end method run
} // end anonymous inner class
); // end call to SwingUtilities.invokeLater
myTurn = ( myMark.equals( X_MARK ) ); // determine if client's turn
// receive messages sent to client and output them
while ( true )
if ( input.hasNextLine() )
processMessage( input.nextLine() );
} // end while
} // end method run
// process messages received by client
private void processMessage( String message )
// valid move occurred
if ( message.equals( "Valid move." ) )
displayMessage( "Valid move, please wait.\n" );
setMark( currentSquare, myMark ); // set mark in square
} // end if
else if ( message.equals( "Invalid move, try again" ) )
displayMessage( message + "\n" ); // display invalid move
myTurn = true; // still this client's turn
} // end else if
else if ( message.equals( "Opponent moved" ) )
int location = input.nextInt(); // get move location
input.nextLine(); // skip newline after int location
int row = location / 3; // calculate row
int column = location % 3; // calculate column
setMark( board[ row ][ column ],
( myMark.equals( X_MARK ) ? O_MARK : X_MARK ) ); // mark move
displayMessage( "Opponent moved. Your turn.\n" );
myTurn = true; // now this client's turn
} // end else if
//Game Over #*********Here**********#
else if ( message.equals( "no winner, you loose" ) )
btnNew.setEnabled(true);
myTurn = false;
} // end else if
else if ( message.equals( "Player X wins" ) ||
message.equals( "Player X wins, you loose" ) )
btnNew.setEnabled(true);
myTurn = false;
} // end else if
else if ( message.equals( "Player O wins" ) ||
message.equals( "Player O wins, you loose" ) )
btnNew.setEnabled(true);
myTurn = false;
} // end else if
else
displayMessage( message + "\n" ); // display the message
} // end method processMessage
//start a new game here
private void newGame()
// manipulate outputArea in event-dispatch thread
private void displayMessage( final String messageToDisplay )
SwingUtilities.invokeLater(
new Runnable()
public void run()
displayArea.append( messageToDisplay ); // updates output
} // end method run
} // end inner class
); // end call to SwingUtilities.invokeLater
} // end method displayMessage
// utility method to set mark on board in event-dispatch thread
private void setMark( final Square squareToMark, final String mark )
SwingUtilities.invokeLater(
new Runnable()
public void run()
squareToMark.setMark( mark ); // set mark in square
} // end method run
} // end anonymous inner class
); // end call to SwingUtilities.invokeLater
} // end method setMark
// send message to server indicating clicked square
public void sendClickedSquare( int location )
// if it is my turn
if ( myTurn )
output.format( "%d\n", location ); // send location to server
output.flush();
myTurn = false; // not my turn anymore
} // end if
} // end method sendClickedSquare
// set current Square
public void setCurrentSquare( Square square )
currentSquare = square; // set current square to argument
} // end method setCurrentSquare
// private inner class for the squares on the board
private class Square extends JPanel
private String mark; // mark to be drawn in this square
private int location; // location of square
public Square( String squareMark, int squareLocation )
mark = squareMark; // set mark for this square
location = squareLocation; // set location of this square
addMouseListener(
new MouseAdapter() {
public void mouseReleased( MouseEvent e )
setCurrentSquare( Square.this ); // set current square
// send location of this square
sendClickedSquare( getSquareLocation() );
} // end method mouseReleased
} // end anonymous inner class
); // end call to addMouseListener
} // end Square constructor
// return preferred size of Square
public Dimension getPreferredSize()
return new Dimension( 30, 30 ); // return preferred size
} // end method getPreferredSize
// return minimum size of Square
public Dimension getMinimumSize()
return getPreferredSize(); // return preferred size
} // end method getMinimumSize
// set mark for Square
public void setMark( String newMark )
mark = newMark; // set mark of square
repaint(); // repaint square
} // end method setMark
// return Square location
public int getSquareLocation()
return location; // return location of square
} // end method getSquareLocation
// draw Square
public void paintComponent( Graphics g )
super.paintComponent( g );
g.drawRect( 0, 0, 29, 29 ); // draw square
g.drawString( mark, 11, 20 ); // draw mark
} // end method paintComponent
} // end inner-class Square
} // end class TicTacToeClient
Please any kind of help will be appreciated.
HELP!!!This isn't a code writing service.
Start your own thread, rather than reviving one that is very old. And ask a question: that is, actually describe in what respect your program is not working. Often the most effective way of doing this is to post some code whose runtime behaviour is not what you expect or intend. If you do post code make sure it's brief and to the point (ie just illustrates the problem you are having). To make sure your code is readable when you post it here use the code tags: put {code} at the start of your code and the same thing again at the end. -
Multithread TicTacToe Server Problem
I'm having some problems with finishing up a tic tac toe server and it's driving me crazy. I'm hoping someone can give me some hints or help out with this. All of the code is written for the server which allows 2 clients to connect, but the code for determining if the game is won needs to be finished up.
I've got the method for determining if the game is over done, that part is easy, and I'm able to send a message to the client who wins when they place the winning marker and end the game for them, but currently the next player gets to place one more marker before being signaled that the game is over. I worked on this forever and I think I'm just missing something simple that I hope someone can help me with. Here's the code:
Line 180 in TicTacToeServer.java is where I test for the win
Line 304 in TicTacToeServer.java is where the clients exit the main while loop after determining that the game is won and I send a message letting them know that the game is won
Server Code:
TicTacToeServerTest.java
// Tests the TicTacToeServer.
import javax.swing.JFrame;
public class TicTacToeServerTest
public static void main( String args[] )
TicTacToeServer application = new TicTacToeServer();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
application.execute();
} // end main
} // end class TicTacToeServerTest
TicTacToeServer.java
// This class maintains a game of Tic-Tac-Toe for two clients.
import javax.swing.JOptionPane;
import java.awt.BorderLayout;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.util.Formatter;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TicTacToeServer extends JFrame
private String[] board = new String[ 9 ]; // tic-tac-toe board
private JTextArea outputArea; // for outputting moves
private Player[] players; // array of Players
private ServerSocket server; // server socket to connect with clients
private int currentPlayer; // keeps track of player with current move
private final static int PLAYER_X = 0; // constant for first player
private final static int PLAYER_O = 1; // constant for second player
private final static String[] MARKS = { "X", "O" }; // array of marks
private ExecutorService runGame; // will run players
private Lock gameLock; // to lock game for synchronization
private Condition otherPlayerConnected; // to wait for other player
private Condition otherPlayerTurn; // to wait for other player's turn
private int winner = 2;
// set up tic-tac-toe server and GUI that displays messages
public TicTacToeServer()
super( "Tic-Tac-Toe Server" ); // set title of window
// create ExecutorService with a thread for each player
runGame = Executors.newFixedThreadPool( 2 );
gameLock = new ReentrantLock(); // create lock for game
// condition variable for both players being connected
otherPlayerConnected = gameLock.newCondition();
// condition variable for the other player's turn
otherPlayerTurn = gameLock.newCondition();
for ( int i = 0; i < 9; i++ )
board[ i ] = new String( "" ); // create tic-tac-toe board
players = new Player[ 2 ]; // create array of players
currentPlayer = PLAYER_X; // set current player to first player
try
server = new ServerSocket( 12345, 2 ); // set up ServerSocket
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
outputArea = new JTextArea(); // create JTextArea for output
add( outputArea, BorderLayout.CENTER );
outputArea.setText( "Server awaiting connections\n" );
setSize( 300, 300 ); // set size of window
setVisible( true ); // show window
} // end TicTacToeServer constructor
// wait for two connections so game can be played
public void execute()
// wait for each client to connect
for ( int i = 0; i < players.length; i++ )
try // wait for connection, create Player, start runnable
players[ i ] = new Player( server.accept(), i );
runGame.execute( players[ i ] ); // execute player runnable
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end for
gameLock.lock(); // lock game to signal player X's thread
try
players[ PLAYER_X ].setSuspended( false ); // resume player X
otherPlayerConnected.signal(); // wake up player X's thread
} // end try
finally
gameLock.unlock(); // unlock game after signalling player X
} // end finally
} // end method execute
// display message in outputArea
private void displayMessage( final String messageToDisplay )
// display message from event-dispatch thread of execution
SwingUtilities.invokeLater(
new Runnable()
public void run() // updates outputArea
outputArea.append( messageToDisplay ); // add message
} // end method run
} // end inner class
); // end call to SwingUtilities.invokeLater
} // end method displayMessage
// determine if move is valid
public boolean validateAndMove( int location, int player )
// while not current player, must wait for turn
while ( player != currentPlayer )
gameLock.lock(); // lock game to wait for other player to go
try
otherPlayerTurn.await(); // wait for player's turn
} // end try
catch ( InterruptedException exception )
exception.printStackTrace();
} // end catch
finally
gameLock.unlock(); // unlock game after waiting
} // end finally
} // end while
// if location not occupied, make move
if ( !isOccupied( location ) )
board[ location ] = MARKS[ currentPlayer ]; // set move on board
currentPlayer = ( currentPlayer + 1 ) % 2; // change player
// let new current player know that move occurred
players[ currentPlayer ].otherPlayerMoved( location );
gameLock.lock(); // lock game to signal other player to go
try
otherPlayerTurn.signal(); // signal other player to continue
} // end try
finally
gameLock.unlock(); // unlock game after signaling
} // end finally
return true; // notify player that move was valid
} // end if
else // move was not valid
return false; // notify player that move was invalid
} // end method validateAndMove
// determine whether location is occupied
public boolean isOccupied( int location )
if ( board[ location ].equals( MARKS[ PLAYER_X ] ) ||
board [ location ].equals( MARKS[ PLAYER_O ] ) )
return true; // location is occupied
else
return false; // location is not occupied
} // end method isOccupied
// place code in this method to determine whether game over
public boolean isGameOver()
for (int x = 0; x < 2; x++)
if ((board[0].equals(MARKS[x]) && board[1].equals(MARKS[x]) && board[2].equals(MARKS[x])) ||
(board[3].equals(MARKS[x]) && board[4].equals(MARKS[x]) && board[5].equals(MARKS[x])) ||
(board[6].equals(MARKS[x]) && board[7].equals(MARKS[x]) && board[8].equals(MARKS[x])) ||
(board[0].equals(MARKS[x]) && board[4].equals(MARKS[x]) && board[8].equals(MARKS[x])) ||
(board[6].equals(MARKS[x]) && board[4].equals(MARKS[x]) && board[2].equals(MARKS[x])) ||
(board[0].equals(MARKS[x]) && board[3].equals(MARKS[x]) && board[6].equals(MARKS[x])) ||
(board[1].equals(MARKS[x]) && board[4].equals(MARKS[x]) && board[7].equals(MARKS[x])) ||
(board[2].equals(MARKS[x]) && board[5].equals(MARKS[x]) && board[8].equals(MARKS[x]))
winner = x;
return true;
return false; // this is left as an exercise
} // end method isGameOver
// private inner class Player manages each Player as a runnable
private class Player implements Runnable
private Socket connection; // connection to client
private Scanner input; // input from client
private Formatter output; // output to client
private int playerNumber; // tracks which player this is
private String mark; // mark for this player
private boolean suspended = true; // whether thread is suspended
// set up Player thread
public Player( Socket socket, int number )
playerNumber = number; // store this player's number
mark = MARKS[ playerNumber ]; // specify player's mark
connection = socket; // store socket for client
try // obtain streams from Socket
input = new Scanner( connection.getInputStream() );
output = new Formatter( connection.getOutputStream() );
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end Player constructor
// send message that other player moved
public void otherPlayerMoved( int location )
output.format( "Opponent moved\n" );
output.format( "%d\n", location ); // send location of move
output.flush(); // flush output
} // end method otherPlayerMoved
// control thread's execution
public void run()
// send client its mark (X or O), process messages from client
try
displayMessage( "Player " + mark + " connected\n" );
output.format( "%s\n", mark ); // send player's mark
output.flush(); // flush output
// if player X, wait for another player to arrive
if ( playerNumber == PLAYER_X )
output.format( "%s\n%s", "Player X connected",
"Waiting for another player\n" );
output.flush(); // flush output
gameLock.lock(); // lock game to wait for second player
try
while( suspended )
otherPlayerConnected.await(); // wait for player O
} // end while
} // end try
catch ( InterruptedException exception )
exception.printStackTrace();
} // end catch
finally
gameLock.unlock(); // unlock game after second player
} // end finally
// send message that other player connected
output.format( "Other player connected. Your move.\n" );
output.flush(); // flush output
} // end if
else
output.format( "Player O connected, please wait\n" );
output.flush(); // flush output
} // end else
// while game not over
while ( !isGameOver() )
int location = 0; // initialize move location
if ( input.hasNext() )
location = input.nextInt(); // get move location
// check for valid move
if ( validateAndMove( location, playerNumber ) )
displayMessage( "\nlocation: " + location );
output.format( "Valid move.\n" ); // notify client
output.flush(); // flush output
} // end if
else // move was invalid
output.format( "Invalid move, try again\n" );
output.flush(); // flush output
} // end else
} // end while
output.format( "Game Over.\n" ); // notify client
if (winner == 0)
output.format("Winner is X\n");
if (winner == 1)
output.format("Winner is O\n");
output.flush(); // flush output
gameLock.unlock();
} // end try
finally
try
connection.close(); // close connection to client
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
System.exit( 1 );
} // end catch
} // end finally
} // end method run
// set whether or not thread is suspended
public void setSuspended( boolean status )
suspended = status; // set value of suspended
} // end method setSuspended
} // end class Player
} // end class TicTacToeServer
Client Code:
TicTacToeClientTest.java
// Tests the TicTacToeClient class.
import javax.swing.JFrame;
public class TicTacToeClientTest
public static void main( String args[] )
TicTacToeClient application; // declare client application
// if no command line args
if ( args.length == 0 )
application = new TicTacToeClient( "127.0.0.1" ); // localhost
else
application = new TicTacToeClient( args[ 0 ] ); // use args
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
} // end main
} // end class TicTacToeClientTest
TicTacToeClient.java
// Client that let a user play Tic-Tac-Toe with another across a network.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.Socket;
import java.net.InetAddress;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.util.Formatter;
import java.util.Scanner;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class TicTacToeClient extends JFrame implements Runnable
private JTextField idField; // textfield to display player's mark
private JTextArea displayArea; // JTextArea to display output
private JPanel boardPanel; // panel for tic-tac-toe board
private JPanel panel2; // panel to hold board
private Square board[][]; // tic-tac-toe board
private Square currentSquare; // current square
private Socket connection; // connection to server
private Scanner input; // input from server
private Formatter output; // output to server
private String ticTacToeHost; // host name for server
private String myMark; // this client's mark
private boolean myTurn; // determines which client's turn it is
private final String X_MARK = "X"; // mark for first client
private final String O_MARK = "O"; // mark for second client
// set up user-interface and board
public TicTacToeClient( String host )
ticTacToeHost = host; // set name of server
displayArea = new JTextArea( 4, 30 ); // set up JTextArea
displayArea.setEditable( false );
add( new JScrollPane( displayArea ), BorderLayout.SOUTH );
boardPanel = new JPanel(); // set up panel for squares in board
boardPanel.setLayout( new GridLayout( 3, 3, 0, 0 ) );
board = new Square[ 3 ][ 3 ]; // create board
// loop over the rows in the board
for ( int row = 0; row < board.length; row++ )
// loop over the columns in the board
for ( int column = 0; column < board[ row ].length; column++ )
// create square
board[ row ][ column ] = new Square( " ", row * 3 + column );
boardPanel.add( board[ row ][ column ] ); // add square
} // end inner for
} // end outer for
idField = new JTextField(); // set up textfield
idField.setEditable( false );
add( idField, BorderLayout.NORTH );
panel2 = new JPanel(); // set up panel to contain boardPanel
panel2.add( boardPanel, BorderLayout.CENTER ); // add board panel
add( panel2, BorderLayout.CENTER ); // add container panel
setSize( 300, 225 ); // set size of window
setVisible( true ); // show window
startClient();
} // end TicTacToeClient constructor
// start the client thread
public void startClient()
try // connect to server, get streams and start outputThread
// make connection to server
connection = new Socket(
InetAddress.getByName( ticTacToeHost ), 12345 );
// get streams for input and output
input = new Scanner( connection.getInputStream() );
output = new Formatter( connection.getOutputStream() );
} // end try
catch ( IOException ioException )
ioException.printStackTrace();
} // end catch
// create and start worker thread for this client
ExecutorService worker = Executors.newFixedThreadPool( 1 );
worker.execute( this ); // execute client
} // end method startClient
// control thread that allows continuous update of displayArea
public void run()
myMark = input.nextLine(); // get player's mark (X or O)
SwingUtilities.invokeLater(
new Runnable()
public void run()
// display player's mark
idField.setText( "You are player \"" + myMark + "\"" );
} // end method run
} // end anonymous inner class
); // end call to SwingUtilities.invokeLater
myTurn = ( myMark.equals( X_MARK ) ); // determine if client's turn
// receive messages sent to client and output them
while ( true )
if ( input.hasNextLine() )
processMessage( input.nextLine() );
} // end while
} // end method run
// process messages received by client
private void processMessage( String message )
// valid move occurred
if ( message.equals( "Valid move." ) )
displayMessage( "Valid move, please wait.\n" );
setMark( currentSquare, myMark ); // set mark in square
} // end if
else if ( message.equals( "Invalid move, try again" ) )
displayMessage( message + "\n" ); // display invalid move
myTurn = true; // still this client's turn
} // end else if
else if ( message.equals( "Opponent moved" ) )
int location = input.nextInt(); // get move location
input.nextLine(); // skip newline after int location
int row = location / 3; // calculate row
int column = location % 3; // calculate column
setMark( board[ row ][ column ],
( myMark.equals( X_MARK ) ? O_MARK : X_MARK ) ); // mark move
displayMessage( "Opponent moved. Your turn.\n" );
myTurn = true; // now this client's turn
} // end else if
else
displayMessage( message + "\n" ); // display the message
} // end method processMessage
// manipulate outputArea in event-dispatch thread
private void displayMessage( final String messageToDisplay )
SwingUtilities.invokeLater(
new Runnable()
public void run()
displayArea.append( messageToDisplay ); // updates output
} // end method run
} // end inner class
); // end call to SwingUtilities.invokeLater
} // end method displayMessage
// utility method to set mark on board in event-dispatch thread
private void setMark( final Square squareToMark, final String mark )
SwingUtilities.invokeLater(
new Runnable()
public void run()
squareToMark.setMark( mark ); // set mark in square
} // end method run
} // end anonymous inner class
); // end call to SwingUtilities.invokeLater
} // end method setMark
// send message to server indicating clicked square
public void sendClickedSquare( int location )
// if it is my turn
if ( myTurn )
output.format( "%d\n", location ); // send location to server
output.flush();
myTurn = false; // not my turn anymore
} // end if
} // end method sendClickedSquare
// set current Square
public void setCurrentSquare( Square square )
currentSquare = square; // set current square to argument
} // end method setCurrentSquare
// private inner class for the squares on the board
private class Square extends JPanel
private String mark; // mark to be drawn in this square
private int location; // location of square
public Square( String squareMark, int squareLocation )
mark = squareMark; // set mark for this square
location = squareLocation; // set location of this square
addMouseListener(
new MouseAdapter() {
public void mouseReleased( MouseEvent e )
setCurrentSquare( Square.this ); // set current square
// send location of this square
sendClickedSquare( getSquareLocation() );
} // end method mouseReleased
} // end anonymous inner class
); // end call to addMouseListener
} // end Square constructor
// return preferred size of Square
public Dimension getPreferredSize()
return new Dimension( 30, 30 ); // return preferred size
} // end method getPreferredSize
// return minimum size of Square
public Dimension getMinimumSize()
return getPreferredSize(); // return preferred size
} // end method getMinimumSize
// set mark for Square
public void setMark( String newMark )
mark = newMark; // set mark of square
repaint(); // repaint square
} // end method setMark
// return Square location
public int getSquareLocation()
return location; // return location of square
} // end method getSquareLocation
// draw Square
public void paintComponent( Graphics g )
super.paintComponent( g );
g.drawRect( 0, 0, 29, 29 ); // draw square
g.drawString( mark, 11, 20 ); // draw mark
} // end method paintComponent
} // end inner-class Square
} // end class TicTacToeClientI'll look into doing it that way... One thing I don't understand is that when the winning player places it's final marker and gets the game over message the other player gets passed the Opponent moved message. So shouldn't I be able to pass a Game Over message to the other player after sending the Game Over message to the winning player? I'm not sure where in the code I'd need to put the output statement or what code I'd use to send it to the losing player instead of the winning player. I'm fairly new to threading and working on this for school, the book is not very much help in this area, so excuse my ignorance. Is it possible to send a message to the losing client right after sending one to the winning client after the main while loop exits around line 309 of TicTacToeServer.java? Or is this not possible because of how threading works?
Maybe you are looking for
-
How do I eliminate VCR transfer artifact? (the thin line on screen bottom)
Hi, The source I am working with is a DVD, however given the age, quality of the material and artifact in question, I am 99.9% sure the original source was a VHS tape. What is the best way - with respect to quality - to get rid of the thin buzzing bl
-
Late 2011 macbook pro running slow
Hi my macbook has been running pretty sluggish lately. I haven't upgraded anything since I've purchased it. Any thoughts? I just ran an EtreCheck a few minutes hoping it helps. Thanks in advance! EtreCheck version: 2.1.5 (108) Report generated Januar
-
Controlling time of EDI dispatch in output type for invoice
Hi Gurus, I am trying to change the setting for invoice dispatch through EDI Currently the system is set so that invoice is sent (EDI) upon saving - and the desire it to make a manual decision when to send invoice I have looked at output types in SPR
-
Sync suddenly stopped working..?
Ok so I recently set-up Sync when I heard Xmarks was going down. I installed it on my desktop and laptop without a problem. But recently I noticed things weren't syncing, and it's always written "connect" next to the sync icon in firefox on my deskto
-
Many times when I make a new adjustment level, CS6 defaults to "Levels" even though I had selected "Threshold" or Color Balance". I am trying to do an accurate color adjustment using the "Threshold" darkest and lightest sample point, new layer-50%