I'm creating a dice game where 2 players have their own dice, each has his own turn to throw his dice , players can either lose the score entirely or gain score depending on where they stand on the window , and the game ends when any player stands on the finish lane first , the winner is the player with the highest score, I've worked on the design of the game so far but haven't worked on the logic yet.
This link is a picture of how the game should look like :
I would like to know how can I add the player 1 and player 2 as in the photo above on each tile , so basically every time time a player plays his turn ,I want his name to start moving depending on the number he gets when he throws the dice.
Code :
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class diceGame {
public static void main(String[] args) {
new RollDicePanel();
}
}
class RollDicePanel extends JFrame {
private Dice myLeftDie;
private Dice myRightDie;
JPanel mainPanel;
JPanel topLeft,topCenter,topRight;
JPanel centerLeft,centerCenter,centerRight;
JPanel bottomLeft,bottomCenter,bottomRight;
JLabel tLeft,tRight,tCenter,cLeft,cCenter1,cCenter2,cRight,bLeft,bCenter,bRight;
RollDicePanel() {
myLeftDie = new Dice();
myRightDie = new Dice();
JButton rollButton1 = new JButton("Player 1");
rollButton1.setFont(new Font("Sansserif", Font.BOLD, 5));
rollButton1.addActionListener(new RollListener1());
JButton rollButton2 = new JButton("Player 2");
rollButton2.setFont(new Font("Sansserif", Font.BOLD, 5));
rollButton2.addActionListener(new RollListener2());
topLeft = new JPanel();
tLeft = new JLabel("+20");
tLeft.setFont(new Font("Sansserif", Font.BOLD, 20));
tLeft.setLayout(new FlowLayout(FlowLayout.CENTER));
topLeft.add(tLeft,BorderLayout.WEST);
topLeft.setBackground(Color.RED);
topRight = new JPanel();
tRight = new JLabel("-50");
tRight.setFont(new Font("Sansserif", Font.BOLD, 20));
topRight.add(tRight,BorderLayout.EAST);
topRight.setBackground(Color.ORANGE);
topCenter = new JPanel();
tCenter = new JLabel("Try Again");
tCenter.setFont(new Font("Sansserif", Font.BOLD, 20));
topCenter.add(tCenter,BorderLayout.CENTER);
topCenter.setBackground(Color.BLUE);
centerCenter = new JPanel();
cCenter1 = new JLabel("Player 1");
cCenter2 = new JLabel("Player 2");
centerCenter.add(rollButton1,BorderLayout.NORTH);
centerCenter.add(myLeftDie,BorderLayout.SOUTH);
centerCenter.add(rollButton2,BorderLayout.NORTH);
centerCenter.add(myRightDie,BorderLayout.EAST);
centerLeft = new JPanel();
cLeft = new JLabel("Finish");
cLeft.setFont(new Font("Sansserif", Font.BOLD, 20));
centerLeft.add(cLeft,BorderLayout.WEST);
centerLeft.setBackground(Color.YELLOW);
centerRight = new JPanel();
cRight = new JLabel("Lost All");
cRight.setFont(new Font("Sansserif", Font.BOLD, 20));
centerRight.add(cRight,BorderLayout.EAST);
centerRight.setBackground(Color.GREEN);
bottomRight = new JPanel();
bRight = new JLabel("+30");
bRight.setFont(new Font("Sansserif", Font.BOLD, 20));
bottomRight.add(bRight,BorderLayout.EAST);
bottomRight.setBackground(Color.CYAN);
bottomCenter = new JPanel();
bCenter = new JLabel("+10");
bCenter.setFont(new Font("Sansserif", Font.BOLD, 20));
bottomCenter.add(bCenter,BorderLayout.CENTER);
bottomCenter.setBackground(Color.magenta);
bottomLeft = new JPanel();
bLeft = new JLabel("-10");
bLeft.setFont(new Font("Sansserif", Font.BOLD, 20));
bLeft.setForeground(Color.WHITE);
bottomLeft.add(bLeft,BorderLayout.WEST);
bottomLeft.setBackground(Color.BLACK);
mainPanel = new JPanel();
mainPanel.setLayout(new GridLayout(3,3));
mainPanel.add(topLeft,BorderLayout.NORTH);
mainPanel.add(topCenter,BorderLayout.NORTH);
mainPanel.add(topRight,BorderLayout.NORTH);
mainPanel.add(centerLeft,BorderLayout.CENTER);
mainPanel.add(centerCenter,BorderLayout.CENTER);
mainPanel.add(centerRight,BorderLayout.CENTER);
mainPanel.add(bottomLeft,BorderLayout.SOUTH);
mainPanel.add(bottomCenter,BorderLayout.SOUTH);
mainPanel.add(bottomRight,BorderLayout.SOUTH);
this.setTitle("Dice Game");
this.setBounds(200, 200, 700, 700);
this.add(mainPanel);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
}
private class RollListener1 implements ActionListener {
public void actionPerformed(ActionEvent e) {
myLeftDie.roll();
}
}
private class RollListener2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
myRightDie.roll();
}
}
}
class Dice extends JPanel {
private static final int SPOT_DIAMETER = 4;
private int myFaceValue;
public Dice() {
setBackground(Color.white);
setPreferredSize(new Dimension(15,15));
roll();
}
int roll() {
int val = (int)(6*Math.random() + 1);
setValue(val);
return val;
}
public int getValue() {
return myFaceValue;
}
public void setValue(int spots) {
myFaceValue = spots;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
g.drawRect(0, 0, w-1, h-1);
switch (myFaceValue) {
case 1: drawSpot(g, w/2, h/2);
break;
case 3: drawSpot(g, w/2, h/2);
case 2: drawSpot(g, w/4, h/4);
drawSpot(g, 3*w/4, 3*h/4);
break;
case 5: drawSpot(g, w/2, h/2);
case 4: drawSpot(g, w/4, h/4);
drawSpot(g, 3*w/4, 3*h/4);
drawSpot(g, 3*w/4, h/4);
drawSpot(g, w/4, 3*h/4);
break;
case 6: drawSpot(g, w/4, h/4);
drawSpot(g, 3*w/4, 3*h/4);
drawSpot(g, 3*w/4, h/4);
drawSpot(g, w/4, 3*h/4);
drawSpot(g, w/4, h/2);
drawSpot(g, 3*w/4, h/2);
break;
}
}
private void drawSpot(Graphics g, int x, int y) {
g.fillOval(x-SPOT_DIAMETER/2, y-SPOT_DIAMETER/2, SPOT_DIAMETER, SPOT_DIAMETER);
}
}
I fixed up your GUI.
I started your GUI with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
I created the JFrame in your class constructor. I created an outer JPanel, eight inner JPanels, and a center JPanel. The JFrame methods must be executed in a specific order. This is the order I use for my Swing GUIs.
The outer JPanel uses a GridLayout to organize the inner JPanels. The eight inner JPanels are similar, so I used a method to create them.
The center JPanel uses a GridBagLayout to organize the JButtons and die images.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DiceGame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new RollDicePanel();
}
});
}
}
class RollDicePanel extends JFrame {
private static final long serialVersionUID = 1L;
private Dice myLeftDie;
private Dice myRightDie;
public RollDicePanel() {
this.setTitle("Dice Game");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(createOuterPanel(), BorderLayout.CENTER);
this.pack();
this.setLocationByPlatform(true);
this.setVisible(true);
}
private JPanel createOuterPanel() {
JPanel panel = new JPanel(new GridLayout(0, 3));
panel.add(createInnerPanel("+20", new Color(152, 254, 152),
Color.BLACK));
panel.add(createInnerPanel("Try Again...", new Color(252, 252, 201),
Color.BLACK));
panel.add(createInnerPanel("-50", new Color(254, 152, 152),
Color.BLACK));
panel.add(createInnerPanel("Finish!",new Color(0, 203, 101),
Color.BLACK));
panel.add(createCenterPanel());
panel.add(createInnerPanel("Lost All",new Color(252, 48, 99),
Color.BLACK));
panel.add(createInnerPanel("-10", new Color(254, 203, 203),
Color.BLACK));
panel.add(createInnerPanel("+10", new Color(203, 254, 203),
Color.BLACK));
panel.add(createInnerPanel("+30", new Color(49, 253, 0),
Color.BLACK));
return panel;
}
private JPanel createInnerPanel(String text, Color backgroundColor,
Color foregroundColor) {
JPanel panel = new JPanel();
panel.setBackground(backgroundColor);
JLabel label = new JLabel(text);
label.setFont(new Font("Sansserif", Font.BOLD, 20));
label.setForeground(foregroundColor);
panel.add(label);
return panel;
}
private JPanel createCenterPanel() {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.NONE;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
JButton rollButton1 = new JButton("Player 1");
rollButton1.setFont(new Font("Sansserif", Font.BOLD, 10));
rollButton1.addActionListener(new RollListener1());
panel.add(rollButton1, gbc);
gbc.gridx++;
JButton rollButton2 = new JButton("Player 2");
rollButton2.setFont(new Font("Sansserif", Font.BOLD, 10));
rollButton2.addActionListener(new RollListener2());
panel.add(rollButton2, gbc);
gbc.gridx = 0;
gbc.gridy++;
myLeftDie = new Dice();
panel.add(myLeftDie, gbc);
gbc.gridx++;
myRightDie = new Dice();
panel.add(myRightDie, gbc);
return panel;
}
private class RollListener1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
myLeftDie.roll();
}
}
private class RollListener2 implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
myRightDie.roll();
}
}
}
class Dice extends JPanel {
private static final long serialVersionUID = 1L;
private static final int SPOT_DIAMETER = 4;
private int myFaceValue;
public Dice() {
setBackground(Color.white);
setPreferredSize(new Dimension(15, 15));
roll();
}
int roll() {
int val = (int) (6 * Math.random() + 1);
setValue(val);
return val;
}
public int getValue() {
return myFaceValue;
}
public void setValue(int spots) {
myFaceValue = spots;
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
g.drawRect(0, 0, w - 1, h - 1);
switch (myFaceValue) {
case 1:
drawSpot(g, w / 2, h / 2);
break;
case 3:
drawSpot(g, w / 2, h / 2);
case 2:
drawSpot(g, w / 4, h / 4);
drawSpot(g, 3 * w / 4, 3 * h / 4);
break;
case 5:
drawSpot(g, w / 2, h / 2);
case 4:
drawSpot(g, w / 4, h / 4);
drawSpot(g, 3 * w / 4, 3 * h / 4);
drawSpot(g, 3 * w / 4, h / 4);
drawSpot(g, w / 4, 3 * h / 4);
break;
case 6:
drawSpot(g, w / 4, h / 4);
drawSpot(g, 3 * w / 4, 3 * h / 4);
drawSpot(g, 3 * w / 4, h / 4);
drawSpot(g, w / 4, 3 * h / 4);
drawSpot(g, w / 4, h / 2);
drawSpot(g, 3 * w / 4, h / 2);
break;
}
}
private void drawSpot(Graphics g, int x, int y) {
g.fillOval(x - SPOT_DIAMETER / 2, y - SPOT_DIAMETER / 2,
SPOT_DIAMETER, SPOT_DIAMETER);
}
}
Update 1
I went ahead and finished the game.
I created a logical model to hold the board squares and the player positions and score for player 1 and player 2.
I modified the view to use the logical model.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class DiceGame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new RollDicePanel();
}
});
}
}
class RollDicePanel extends JFrame {
private static final long serialVersionUID = 1L;
private final DiceGameModel model;
private Dice myLeftDie;
private Dice myRightDie;
private InnerSquarePanel[] innerPanels;
private JTextField scoreField1;
private JTextField scoreField2;
public RollDicePanel() {
this.model = new DiceGameModel();
this.setTitle("Dice Game");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(createOuterPanel(), BorderLayout.CENTER);
this.pack();
this.setLocationByPlatform(true);
this.setVisible(true);
}
private JPanel createOuterPanel() {
int length = model.getBoardSquares().size();
this.innerPanels = new InnerSquarePanel[length];
for (int index = 0; index < length; index++) {
innerPanels[index] = new InnerSquarePanel(
model.getBoardSquares().get(index));
}
JPanel panel = new JPanel(new GridLayout(0, 3));
panel.add(innerPanels[1].getPanel());
panel.add(innerPanels[2].getPanel());
panel.add(innerPanels[3].getPanel());
panel.add(innerPanels[0].getPanel());
panel.add(createCenterPanel());
panel.add(innerPanels[4].getPanel());
panel.add(innerPanels[7].getPanel());
panel.add(innerPanels[6].getPanel());
panel.add(innerPanels[5].getPanel());
innerPanels[0].getPlayer1Label().setText("Player 1");
innerPanels[0].getPlayer2Label().setText("Player 2");
return panel;
}
private JPanel createCenterPanel() {
JPanel panel = new JPanel(new GridBagLayout());
Font font = new Font("Arial", Font.BOLD, 12);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.NONE;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
JButton rollButton1 = new JButton("Player 1");
rollButton1.setFont(font);
rollButton1.addActionListener(new RollListener1());
panel.add(rollButton1, gbc);
gbc.gridx++;
JButton rollButton2 = new JButton("Player 2");
rollButton2.setFont(font);
rollButton2.addActionListener(new RollListener2());
panel.add(rollButton2, gbc);
gbc.gridx = 0;
gbc.gridy++;
myLeftDie = new Dice();
panel.add(myLeftDie, gbc);
gbc.gridx++;
myRightDie = new Dice();
panel.add(myRightDie, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel label = new JLabel("Score");
label.setFont(font);
panel.add(label, gbc);
gbc.gridx++;
label = new JLabel("Score");
label.setFont(font);
panel.add(label, gbc);
gbc.gridx = 0;
gbc.gridy++;
scoreField1 = new JTextField(4);
scoreField1.setEditable(false);
scoreField1.setFont(font);
scoreField1.setHorizontalAlignment(JTextField.CENTER);
panel.add(scoreField1, gbc);
gbc.gridx++;
scoreField2 = new JTextField(4);
scoreField2.setEditable(false);
scoreField2.setFont(font);
scoreField2.setHorizontalAlignment(JTextField.CENTER);
panel.add(scoreField2, gbc);
return panel;
}
private class RollListener1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
int position = model.getPlayer1position();
int roll = myLeftDie.roll();
model.incrementPlayer1position(roll);
BoardSquare boardSquare = model.getBoardSquares().get(
model.getPlayer1position());
int score = boardSquare.execute(model.getPlayer1score());
model.setPlayer1score(score);
innerPanels[position].getPlayer1Label().setText(" ");
innerPanels[model.getPlayer1position()].getPlayer1Label().
setText("Player 1");
scoreField1.setText(Integer.toString(score));
}
}
private class RollListener2 implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
int position = model.getPlayer2position();
int roll = myRightDie.roll();
model.incrementPlayer2position(roll);
BoardSquare boardSquare = model.getBoardSquares().get(
model.getPlayer2position());
int score = boardSquare.execute(model.getPlayer2score());
model.setPlayer2score(score);
innerPanels[position].getPlayer2Label().setText(" ");
innerPanels[model.getPlayer2position()].getPlayer2Label().
setText("Player 2");
scoreField2.setText(Integer.toString(score));
}
}
}
class Dice extends JPanel {
private static final long serialVersionUID = 1L;
private static final int SPOT_DIAMETER = 4;
private int myFaceValue;
public Dice() {
setBackground(Color.white);
setPreferredSize(new Dimension(15, 15));
roll();
}
int roll() {
int val = (int) (6 * Math.random() + 1);
setValue(val);
return val;
}
public int getValue() {
return myFaceValue;
}
public void setValue(int spots) {
myFaceValue = spots;
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
g.drawRect(0, 0, w - 1, h - 1);
switch (myFaceValue) {
case 1:
drawSpot(g, w / 2, h / 2);
break;
case 3:
drawSpot(g, w / 2, h / 2);
case 2:
drawSpot(g, w / 4, h / 4);
drawSpot(g, 3 * w / 4, 3 * h / 4);
break;
case 5:
drawSpot(g, w / 2, h / 2);
case 4:
drawSpot(g, w / 4, h / 4);
drawSpot(g, 3 * w / 4, 3 * h / 4);
drawSpot(g, 3 * w / 4, h / 4);
drawSpot(g, w / 4, 3 * h / 4);
break;
case 6:
drawSpot(g, w / 4, h / 4);
drawSpot(g, 3 * w / 4, 3 * h / 4);
drawSpot(g, 3 * w / 4, h / 4);
drawSpot(g, w / 4, 3 * h / 4);
drawSpot(g, w / 4, h / 2);
drawSpot(g, 3 * w / 4, h / 2);
break;
}
}
private void drawSpot(Graphics g, int x, int y) {
g.fillOval(x - SPOT_DIAMETER / 2, y - SPOT_DIAMETER / 2,
SPOT_DIAMETER, SPOT_DIAMETER);
}
}
class InnerSquarePanel {
private JLabel player1Label;
private JLabel player2Label;
private final JPanel panel;
public InnerSquarePanel(BoardSquare boardSquare) {
this.panel = createInnerPanel(boardSquare);
}
private JPanel createInnerPanel(BoardSquare boardSquare) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(boardSquare.getBackgroundColor());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(10, 10, 10 ,10);
gbc.gridwidth = 2;
gbc.weightx = 1.0;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridx = 0;
gbc.gridy = 0;
JLabel label = new JLabel(boardSquare.getText());
label.setFont(new Font("Arial", Font.BOLD, 24));
label.setForeground(boardSquare.getForegroundColor());
label.setHorizontalAlignment(JLabel.CENTER);
panel.add(label, gbc);
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridwidth = 1;
gbc.gridy++;
player1Label = new JLabel(" ");
player1Label.setForeground(boardSquare.getForegroundColor());
player1Label.setHorizontalAlignment(JLabel.LEADING);
player1Label.setVerticalAlignment(JLabel.BOTTOM);
panel.add(player1Label, gbc);
gbc.anchor = GridBagConstraints.LINE_END;
gbc.gridx++;
player2Label = new JLabel(" ");
player2Label.setForeground(boardSquare.getForegroundColor());
player2Label.setHorizontalAlignment(JLabel.TRAILING);
player2Label.setVerticalAlignment(JLabel.BOTTOM);
panel.add(player2Label, gbc);
return panel;
}
public JLabel getPlayer1Label() {
return player1Label;
}
public JLabel getPlayer2Label() {
return player2Label;
}
public JPanel getPanel() {
return panel;
}
}
class DiceGameModel {
private int player1position;
private int player2position;
private int player1score;
private int player2score;
private final List<BoardSquare> boardSquares;
public DiceGameModel() {
this.player1position = 0;
this.player2position = 0;
this.player1score = 0;
this.player2score = 0;
this.boardSquares = new ArrayList<>();
boardSquares.add(new FinishSquare());
boardSquares.add(new Square1());
boardSquares.add(new Square2());
boardSquares.add(new Square3());
boardSquares.add(new Square4());
boardSquares.add(new Square5());
boardSquares.add(new Square6());
boardSquares.add(new Square7());
}
public int getPlayer1position() {
return player1position;
}
public void incrementPlayer1position(int increment) {
this.player1position = (player1position + increment) %
boardSquares.size();
}
public int getPlayer2position() {
return player2position;
}
public void incrementPlayer2position(int increment) {
this.player2position = (player2position + increment) %
boardSquares.size();
}
public int getPlayer1score() {
return player1score;
}
public void setPlayer1score(int player1score) {
this.player1score = player1score;
}
public int getPlayer2score() {
return player2score;
}
public void setPlayer2score(int player2score) {
this.player2score = player2score;
}
public List<BoardSquare> getBoardSquares() {
return boardSquares;
}
}
class FinishSquare extends BoardSquare {
public FinishSquare() {
super("Finish!", 0, new Color(0, 203, 101), Color.WHITE);
}
#Override
public int execute(int score) {
return score;
}
}
class Square1 extends BoardSquare {
public Square1() {
super("+20", 1, new Color(152, 254, 152), Color.BLACK);
}
#Override
public int execute(int score) {
return score + 20;
}
}
class Square2 extends BoardSquare {
public Square2() {
super("Try Again", 2, new Color(252, 252, 201), Color.BLACK);
}
#Override
public int execute(int score) {
return score;
}
}
class Square3 extends BoardSquare {
public Square3() {
super("-50", 3, new Color(254, 152, 152), Color.BLACK);
}
#Override
public int execute(int score) {
return score - 50;
}
}
class Square4 extends BoardSquare {
public Square4() {
super("Lost All", 4, new Color(252, 48, 99), Color.WHITE);
}
#Override
public int execute(int score) {
return 0;
}
}
class Square5 extends BoardSquare {
public Square5() {
super("+30", 5, new Color(49, 253, 0), Color.BLACK);
}
#Override
public int execute(int score) {
return score + 30;
}
}
class Square6 extends BoardSquare {
public Square6() {
super("+10", 6, new Color(203, 254, 203), Color.BLACK);
}
#Override
public int execute(int score) {
return score + 10;
}
}
class Square7 extends BoardSquare {
public Square7() {
super("-10", 7, new Color(254, 203, 203), Color.BLACK);
}
#Override
public int execute(int score) {
return score - 10;
}
}
abstract class BoardSquare {
private final int position;
private final Color backgroundColor;
private final Color foregroundColor;
private final String text;
public BoardSquare(String text, int position,
Color backgroundColor, Color foregroundColor) {
this.text = text;
this.position = position;
this.backgroundColor = backgroundColor;
this.foregroundColor = foregroundColor;
}
public abstract int execute(int score);
public int getPosition() {
return position;
}
public String getText() {
return text;
}
public Color getBackgroundColor() {
return backgroundColor;
}
public Color getForegroundColor() {
return foregroundColor;
}
}
Related
In my code i generate randoms integer between 0 and 60 and i draw lines based on these.
I just want my lines fit the ordinate vertical line without touching my randoms integer... I guess it's kind of a mathematics problem but i'm really stuck here!
Here's my code first:
Windows.java:
public class Window extends JFrame{
Panel pan = new Panel();
JPanel container, north,south, west;
public JButton ip,print,cancel,start,ok;
JTextArea timeStep;
JLabel legend;
double time=0;
double temperature=0.0;
Timer chrono;
public static void main(String[] args) {
new Window();
}
public Window()
{
System.out.println("je suis là");
this.setSize(1000,400);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setTitle("Assignment2 - CPU temperature");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
container = new JPanel(new BorderLayout());
north = new JPanel();
north.setLayout(new BorderLayout());
ip = new JButton ("New");
north.add(ip, BorderLayout.WEST);
print = new JButton ("Print");
north.add(print,BorderLayout.EAST);
JPanel centerPanel = new JPanel();
centerPanel.add(new JLabel("Time Step (in s): "));
timeStep = new JTextArea("0.1",1,5);
centerPanel.add(timeStep);
start = new JButton("OK");
ListenForButton lForButton = new ListenForButton();
start.addActionListener(lForButton);
ip.addActionListener(lForButton);
print.addActionListener(lForButton);
centerPanel.add(start);
north.add(centerPanel, BorderLayout.CENTER);
west = new JPanel();
JLabel temp = new JLabel("°C");
west.add(temp);
container.add(north, BorderLayout.NORTH);
container.add(west,BorderLayout.WEST);
container.add(pan, BorderLayout.CENTER);
this.setContentPane(container);
this.setVisible(true);
}
private class ListenForButton implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==start)
{
time=Double.parseDouble(timeStep.getText());
System.out.println(time);
chrono = new Timer((int)(1000*time),pan);
chrono.start();
}
if(e.getSource()==ip)
{
JPanel options = new JPanel();
JLabel address = new JLabel("IP Address:");
JTextField address_t = new JTextField(15);
JLabel port = new JLabel("Port:");
JTextField port_t = new JTextField(5);
options.add(address);
options.add(address_t);
options.add(port);
options.add(port_t);
int result = JOptionPane.showConfirmDialog(null, options, "Please Enter an IP Address and the port wanted", JOptionPane.OK_CANCEL_OPTION);
if(result==JOptionPane.OK_OPTION)
{
System.out.println(address_t.getText());
System.out.println(port_t.getText());
}
}
if(e.getSource()==print)
{
chrono.stop();
}
}
}
}
Panel.java:
public class Panel extends JPanel implements ActionListener {
int rand;
int lastrand=0;
ArrayList<Integer> randL = new ArrayList<>();
ArrayList<Integer> tL = new ArrayList<>();
int lastT = 0;
Color red = new Color(255,0,0);
Color green = new Color(0,200,0);
Color blue = new Color (0,0,200);
Color yellow = new Color (200,200,0);
int max=0;
int min=0;
int i,k,inc = 0,j;
int total,degr,moyenne;
public Panel()
{
super();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(1.8f));
g2.drawLine(20, 20, 20, this.getHeight()-50);
g2.drawLine(20, this.getHeight()-50, this.getWidth()-50, this.getHeight()-50);
g2.drawLine(20, 20, 15, 35);
g2.drawLine(20, 20, 25, 35);
g2.drawLine(this.getWidth()-50, this.getHeight()-50, this.getWidth()-65, this.getHeight()-45);
g2.drawLine(this.getWidth()-50, this.getHeight()-50, this.getWidth()-65, this.getHeight()-55);
g.drawString("10", 0, this.getHeight()-85);
g.drawString("20", 0, this.getHeight()-125);
g.drawString("30", 0, this.getHeight()-165);
g.drawString("40", 0, this.getHeight()-205);
g.drawString("50", 0, this.getHeight()-245);
g2.drawString("Maximum: ", 20, this.getHeight()-20);
g2.drawString(Integer.toString(max), 80, this.getHeight()-20);
g2.drawString("Minimum: ", 140, this.getHeight()-20);
g2.drawString(Integer.toString(min), 200, this.getHeight()-20);
g2.drawString("Average: ", 260, this.getHeight()-20);
g2.drawString(Integer.toString(moyenne), 320, this.getHeight()-20);
g2.setColor(red);
g2.drawLine(500, this.getHeight()-25, 540, this.getHeight()-25);
g2.setColor(new Color(0,0,0));
g2.drawString(": Maximum", 560, this.getHeight()-20);
g2.setColor(blue);
g2.drawLine(640, this.getHeight()-25, 680, this.getHeight()-25);
g2.setColor(new Color(0,0,0));
g2.drawString(": Minimum", 700, this.getHeight()-20);
g2.setColor(green);
g2.drawLine(780, this.getHeight()-25, 820, this.getHeight()-25);
g2.setColor(new Color(0,0,0));
g2.drawString(": Average", 840, this.getHeight()-20);
if(!randL.isEmpty()){
g2.setColor(red);
g2.drawLine(15, this.getHeight()-50-max, this.getWidth()-50,this.getHeight()-50-max);
g2.setColor(blue);
g2.drawLine(15, this.getHeight()-50-min, this.getWidth()-50,this.getHeight()-50-min);
g2.setColor(green);
g2.drawLine(15, this.getHeight()-50-moyenne, this.getWidth()-50,this.getHeight()-50-moyenne);
}
for(i = 0; i<tL.size(); i++){
int temp = randL.get(i);
int t = tL.get(i);
g2.setColor(new Color(0,0,0));
g2.drawLine(20+t, this.getHeight()-50-temp, 20+t, this.getHeight()-50);
// Ellipse2D circle = new Ellipse2D.Double();
//circle.setFrameFromCenter(20+t, this.getHeight()-50, 20+t+2, this.getHeight()-52);
}
for(j=0;j<5;j++)
{
inc=inc+40;
g2.setColor(new Color(0,0,0));
g2.drawLine(18, this.getHeight()-50-inc, 22, this.getHeight()-50-inc);
}
inc=0;
}
#Override
public void actionPerformed(ActionEvent e) {
rand = (int)(Math.random() * (60));
lastT += 80;
randL.add(rand);
tL.add(lastT);
Object obj = Collections.max(randL);
max = (int) obj;
Object obj2 = Collections.min(randL);
min = (int) obj2;
if(!randL.isEmpty()) {
degr = randL.get(k);
total += degr;
moyenne=total/randL.size();
}
k++;
if(randL.size()>=12)
{
randL.removeAll(randL);
tL.removeAll(tL);
lastT = 0;
k=0;
degr=0;
total=0;
moyenne=0;
}
repaint();
}
}
And here it what i gives me :
Sorry it's a real mess!
Any thoughts ?
Thanks.
You need to stop working with absolute/magical values, and start using the actual values of the component (width/height).
The basic problem is a simple calculation which takes the current value divides it by the maximum value and multiples it by the available width of the allowable area
int length = (value / max) * width;
value / max generates a percentage value of 0-1, which you then use to calculate the percentage of the available width of the area it will want to use.
The following example places a constraint (or margin) on the available viewable area, meaning all the lines need to be painted within that area and not use the entire viewable area of the component
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawLine {
public static void main(String[] args) {
new DrawLine();
}
public DrawLine() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int margin = 20;
int width = getWidth() - (margin * 2);
int height = getHeight() - (margin * 2);
int x = margin;
for (int index = 0; index < 4; index++) {
int y = margin + (int)(((index / 3d) * height));
int length = (int)(((index + 1) / 4d) * width);
g2d.drawLine(x, y, x + length, y);
}
g2d.dispose();
}
}
}
Ok, so I am making a monopoly game. I so far have a JFrame, with a JPanel acting as a board. I have loaded all necessary images. I create a Player object which extends JLabel, to represent the player on the board.
I am trying to set the location of (in hopes of moving pieces around the board) Player object (which is a JLabel), on the board (which is a JPanel). I tried the .setLocation method, .setBounds method.
For some reason, no matter what i do the Player object only shows up on the top middle of the JPanel. I was wondering how I could move the Player object on my board.
JFrame code (I attempt to move the JLabel in the bottom of the constructor):
package com.Game.Monopoly;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Timer;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import net.miginfocom.swing.MigLayout;
//a class that represent the board (JFrame) and all of it components
public class GameFrame extends JFrame {
private final double SCALE;
// all the graphical components
private Board board;
private JLabel lblPlayerMoney;
private JLabel lblCurrentPlayer;
private JLabel lblDice1;
private JLabel lblDice2;
private JList lstPropertiesList;
private JButton btnEndTurn;
private JButton btnBuyProperty;
private JButton btnRollDice;
// all images needed
private ImageIcon imgDice1;
private ImageIcon imgDice2;
private ImageIcon imgDice3;
private ImageIcon imgDice4;
private ImageIcon imgDice5;
private ImageIcon imgDice6;
private ImageIcon icnAirplane;
// all players
private Player[] playerList;
// all properties
private Property[] propertiesList;
public GameFrame(double scale) {
// SCALE = scale;
SCALE = 1;
// set up the JFrame
setResizable(true);
setTitle("Monopoly");
// etUndecorated(true);
// set size to a scale of 1080p
setSize((int) (1920 * SCALE), (int) (1080 * SCALE));
setLayout(new MigLayout());
loadImages();
// add the components to the frame
board = new Board(SCALE);
board.setPreferredSize(new Dimension((int) (1024 * SCALE),
(int) (1024 * SCALE)));
board.setBackground(Color.BLACK);
add(board, "east, gapbefore 80");
lblCurrentPlayer = new JLabel("Current Player:" + " Player 1");
add(lblCurrentPlayer, "wrap");
lblPlayerMoney = new JLabel("Player1's money:" + "$14000000");
add(lblPlayerMoney, "wrap");
lstPropertiesList = new JList();
add(new JScrollPane(lstPropertiesList),
"span 2 2, grow, height 70:120:200");
btnRollDice = new JButton("Roll Dice");
add(btnRollDice, "wrap");
lblDice1 = new JLabel(imgDice1);
add(lblDice1);
lblDice2 = new JLabel(imgDice1);
add(lblDice2, "wrap");
btnBuyProperty = new JButton("Buy Property");
add(btnBuyProperty, "wrap, top");
btnEndTurn = new JButton("End Turn");
add(btnEndTurn, "aligny bottom");
setUpEventListeners();
loadProperties();
// load players
playerList = new Player[6];
playerList[0] = new Player("Player 1", icnAirplane);
// add Players to the board
board.add(playerList[0]);
playerList[0].setLocation(new Point(500, 230));
}
public static void main(String[] args) {
GameFrame board = new GameFrame(1);
board.setVisible(true);
}
// method to add event listeners
public void setUpEventListeners() {
// roll dice
btnRollDice.addActionListener(new ActionListener() {
// creates an object with an timers to help with rolling dice
class RollDice implements ActionListener {
private Timer time = new Timer(152, this);
private int count = 0;
public void actionPerformed(ActionEvent e) {
count++;
if (count == 21)
time.stop();
int whatDice1 = (int) (Math.random() * 6) + 1;
int whatDice2 = (int) (Math.random() * 6) + 1;
// set the icons of the labels according to the random
// number
if (whatDice1 == 1)
lblDice1.setIcon(imgDice1);
else if (whatDice1 == 2)
lblDice1.setIcon(imgDice2);
else if (whatDice1 == 3)
lblDice1.setIcon(imgDice3);
else if (whatDice1 == 4)
lblDice1.setIcon(imgDice4);
else if (whatDice1 == 5)
lblDice1.setIcon(imgDice5);
else if (whatDice1 == 6)
lblDice1.setIcon(imgDice6);
if (whatDice2 == 1)
lblDice2.setIcon(imgDice1);
else if (whatDice2 == 2)
lblDice2.setIcon(imgDice2);
else if (whatDice2 == 3)
lblDice2.setIcon(imgDice3);
else if (whatDice2 == 4)
lblDice2.setIcon(imgDice4);
else if (whatDice2 == 5)
lblDice2.setIcon(imgDice5);
else if (whatDice2 == 6)
lblDice2.setIcon(imgDice6);
}
public void roll() {
count = 0;
time.start();
}
}
// create a new dice roll object
RollDice roll = new RollDice();
// if the roll dice button is clicked
public void actionPerformed(ActionEvent arg0) {
roll.roll();
}
});
}
// load all images to memory
public void loadImages() {
BufferedImage i = null;
try {
i = ImageIO.read((getClass().getResource("/resources/Dice 1.png")));
imgDice1 = new ImageIcon(i.getScaledInstance(100, 100,
java.awt.Image.SCALE_SMOOTH));
i = ImageIO.read((getClass().getResource("/resources/Dice 2.png")));
imgDice2 = new ImageIcon(i.getScaledInstance(100, 100,
java.awt.Image.SCALE_SMOOTH));
i = ImageIO.read((getClass().getResource("/resources/Dice 3.png")));
imgDice3 = new ImageIcon(i.getScaledInstance(100, 100,
java.awt.Image.SCALE_SMOOTH));
i = ImageIO.read((getClass().getResource("/resources/Dice 4.png")));
imgDice4 = new ImageIcon(i.getScaledInstance(100, 100,
java.awt.Image.SCALE_SMOOTH));
i = ImageIO.read((getClass().getResource("/resources/Dice 5.png")));
imgDice5 = new ImageIcon(i.getScaledInstance(100, 100,
java.awt.Image.SCALE_SMOOTH));
i = ImageIO.read((getClass().getResource("/resources/Dice 6.png")));
imgDice6 = new ImageIcon(i.getScaledInstance(100, 100,
java.awt.Image.SCALE_SMOOTH));
i = ImageIO.read((getClass()
.getResource("/resources/Airplane Icon.png")));
icnAirplane = new ImageIcon(i.getScaledInstance(40, 40,
java.awt.Image.SCALE_SMOOTH));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// load all properties
public void loadProperties() {
propertiesList = new Property[40];
// set up the properties list
// (name, index, isBuyable, price, initial rent)
propertiesList[0] = new Property("Go", 0, false, 0, 0);
propertiesList[1] = new Property("Jacob's Field", 1, true, 600000,
20000);
propertiesList[2] = new Property("Community Chest", 2, false, 0, 0);
propertiesList[3] = new Property("Texas Stadium", 3, true, 600000,
40000);
propertiesList[4] = new Property("Income Tax", 4, false, 0, 0);
propertiesList[5] = new Property("O'Hare International Airport", 5,
true, 2000000, 250000);
propertiesList[6] = new Property("Grand Ole Opry", 6, true, 1000000,
60000);
propertiesList[7] = new Property("Chance", 7, false, 0, 0);
}
}
JPanel Code:
package com.Game.Monopoly;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Board extends JPanel {
private static final long serialVersionUID = 1L;
private Image board;
public Board(double scale) {
this.setPreferredSize(new Dimension((int) (1024 * scale),
(int) (1024 * scale)));
BufferedImage i = null;
try {
i = ImageIO.read((getClass().getResource("/resources/monopoly-board-web.jpg")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
board = i.getScaledInstance((int) (1024 * scale), (int) (1024 * scale), java.awt.Image.SCALE_SMOOTH);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(board, 0, 0, this);
}
}
Player Object Code:
package com.Game.Monopoly;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
//a class representing a player with its graphical component
public class Player extends JLabel {
private String playerName;
private int money;
private Property[] propertiesOwned;
public Player(String n, ImageIcon icon) {
playerName = n;
this.setIcon(icon);
}
// changes the amount of money available
public void changeMoney(int amount) {
money = money + amount;
}
public void movePlayer(int x, int y){
this.setLocation(x, y);
}
}
There are a couple of ways you can achieve this, personally, the simplest would be to use custom painting directly and not bother with using Swing based components for the players.
The basic problem you have is JPanel uses a FlowLayout by default, which means that you will always be fighting layout manager. In this case you might consider using a custom layout manager, for example...
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager2;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Monopoly {
public static void main(String[] args) {
new Monopoly();
}
public Monopoly() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MonopolyBoard());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MonopolyBoard extends JPanel {
private List<JLabel> players;
public MonopolyBoard() {
setLayout(new MonopolyBoardLayout());
players = new ArrayList<>(2);
try {
players.add(makePlayer("/Dog.png"));
players.add(makePlayer("/Car.png"));
for (JLabel player : players) {
add(player, new Integer(0));
}
} catch (IOException exp) {
exp.printStackTrace();
}
Timer timer = new Timer(1000, new ActionListener() {
private int count = 0;
private Random rnd = new Random();
#Override
public void actionPerformed(ActionEvent e) {
int playerIndex = count % players.size();
JLabel player = players.get(playerIndex);
MonopolyBoardLayout layout = (MonopolyBoardLayout) getLayout();
int position = layout.getPosition(player);
position += rnd.nextInt(5) + 1;
if (position > 35) {
position -= 35;
}
layout.setPosition(player, position);
revalidate();
repaint();
count++;
}
});
timer.start();
}
protected JLabel makePlayer(String path) throws IOException {
JLabel label = new JLabel(new ImageIcon(ImageIO.read(getClass().getResource(path))), JLabel.CENTER);
return label;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
for (int index = 0; index < 36; index++) {
Rectangle bounds = MonopolyBoardLayoutHelper.getCellBounds(index, width, height);
g2d.draw(bounds);
}
g2d.dispose();
}
}
public static class MonopolyBoardLayoutHelper {
private static Map<Integer, Point> mapBoardCells;
static {
mapBoardCells = new HashMap<>(25);
mapBoardCells.put(10, new Point(0, 8));
mapBoardCells.put(11, new Point(0, 7));
mapBoardCells.put(12, new Point(0, 6));
mapBoardCells.put(13, new Point(0, 5));
mapBoardCells.put(14, new Point(0, 4));
mapBoardCells.put(15, new Point(0, 3));
mapBoardCells.put(16, new Point(0, 2));
mapBoardCells.put(17, new Point(0, 1));
mapBoardCells.put(18, new Point(0, 0));
mapBoardCells.put(0, new Point(9, 9));
mapBoardCells.put(1, new Point(8, 9));
mapBoardCells.put(2, new Point(7, 9));
mapBoardCells.put(3, new Point(6, 9));
mapBoardCells.put(4, new Point(5, 9));
mapBoardCells.put(5, new Point(4, 9));
mapBoardCells.put(6, new Point(3, 9));
mapBoardCells.put(7, new Point(2, 9));
mapBoardCells.put(8, new Point(1, 9));
mapBoardCells.put(9, new Point(0, 9));
mapBoardCells.put(19, new Point(1, 0));
mapBoardCells.put(20, new Point(2, 0));
mapBoardCells.put(21, new Point(3, 0));
mapBoardCells.put(22, new Point(4, 0));
mapBoardCells.put(23, new Point(5, 0));
mapBoardCells.put(24, new Point(6, 0));
mapBoardCells.put(25, new Point(7, 0));
mapBoardCells.put(26, new Point(8, 0));
mapBoardCells.put(27, new Point(9, 0));
mapBoardCells.put(28, new Point(9, 1));
mapBoardCells.put(29, new Point(9, 2));
mapBoardCells.put(30, new Point(9, 3));
mapBoardCells.put(31, new Point(9, 4));
mapBoardCells.put(32, new Point(9, 5));
mapBoardCells.put(33, new Point(9, 6));
mapBoardCells.put(34, new Point(9, 7));
mapBoardCells.put(35, new Point(9, 8));
}
public static Rectangle getCellBounds(int index, int width, int height) {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
int size = Math.min(width, height);
int cellSize = size / 10;
int xOffset = (width - size) / 2;
int yOffset = (height - size) / 2;
Point point = mapBoardCells.get(index);
if (point != null) {
int x = xOffset + (point.x * cellSize);
int y = yOffset + (point.y * cellSize);
bounds = new Rectangle(x, y, cellSize, cellSize);
}
return bounds;
}
}
public static class MonopolyBoardLayout implements LayoutManager2 {
public static final int DEFAULT_CELL_SIZE = 64;
private Map<Component, Integer> cellConstraints;
public MonopolyBoardLayout() {
cellConstraints = new HashMap<>(5);
}
public Integer getPosition(Component comp) {
return cellConstraints.get(comp);
}
public void setPosition(Component comp, int position) {
cellConstraints.put(comp, position);
}
#Override
public void addLayoutComponent(Component comp, Object constraints) {
if (constraints instanceof Integer) {
int cell = (int) constraints;
if (cell >= 0 && cell <= 35) {
cellConstraints.put(comp, cell);
} else {
throw new IllegalArgumentException(constraints + " is not within the bounds of a valid cell reference (0-35)");
}
} else {
throw new IllegalArgumentException(constraints + " is not a valid cell reference (integer within 0-35)");
}
}
#Override
public Dimension maximumLayoutSize(Container target) {
return new Dimension(DEFAULT_CELL_SIZE * 10, DEFAULT_CELL_SIZE * 10);
}
#Override
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
#Override
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
#Override
public void invalidateLayout(Container target) {
}
#Override
public void addLayoutComponent(String name, Component comp) {
}
#Override
public void removeLayoutComponent(Component comp) {
cellConstraints.remove(comp);
}
#Override
public Dimension preferredLayoutSize(Container parent) {
return new Dimension(DEFAULT_CELL_SIZE * 10, DEFAULT_CELL_SIZE * 10);
}
#Override
public Dimension minimumLayoutSize(Container parent) {
return new Dimension(DEFAULT_CELL_SIZE * 10, DEFAULT_CELL_SIZE * 10);
}
#Override
public void layoutContainer(Container parent) {
int width = parent.getWidth();
int height = parent.getHeight();
Map<Integer, List<Component>> components = new HashMap<>(25);
for (Component child : parent.getComponents()) {
Integer cell = cellConstraints.get(child);
if (cell != null) {
List<Component> children = components.get(cell);
if (children == null) {
children = new ArrayList<>(4);
components.put(cell, children);
}
children.add(child);
} else {
child.setBounds(0, 0, 0, 0);
}
}
for (Map.Entry<Integer, List<Component>> entry : components.entrySet()) {
int index = entry.getKey();
Rectangle bounds = MonopolyBoardLayoutHelper.getCellBounds(index, width, height);
List<Component> comp = entry.getValue();
int xDelta = 0;
int yDelta = 0;
int availableWidth = bounds.width;
int availableHeight = bounds.height;
switch (comp.size()) {
case 2:
availableWidth /= 2;
xDelta = availableWidth;
break;
case 3:
case 4:
availableWidth /= 2;
xDelta = availableWidth;
availableHeight /= 2;
yDelta = availableHeight;
break;
}
int x = bounds.x;
int y = bounds.y;
for (int count = 0; count < comp.size() && count < 4; count++) {
Component child = comp.get(count);
child.setSize(availableWidth, availableHeight);
child.setLocation(x, y);
x += xDelta;
if (x >= bounds.x + bounds.width) {
x = bounds.x;
y += yDelta;
}
}
}
}
}
}
As you can see, this becomes real complicated real quick. This example currently only allows 4 players per cell, so if you want more, then you're going to have to create your own algorithim
I have JTable in that I need to Show Chart but i have tired several Code but not able to achieve waht i wanted to make. here what i have tried so far
http://www.jroller.com/Thierry/entry/swing_barchart_rendering_in_a
and i want to achieve according to this image
but how ever i dont get any Render-er for same.
Please Any suggestion will be welcomed.
I would try 3 columns table. For the middle column I would use a custom renderer - a JPanel with JLabels on it. The labels could have different columns and sizes.
The TableModel should keep datasource for the bars and preparing renderer component means reading the cell value, extracting barchar data from the cell and setting colors/sizes for the JLabels in the JPanel (renderer component)
Okay, here's an idea...
Instead of using a JTable, you could create a layout manager which would calculate the offsets and allow for elements to overlap "columns"
Prototype example - !! DO NOT USE IN PRODUCTION !!
This is an EXAMPLE only and should be used to LEARN from, do not try using this in production, there is a lot that needs to improved, such as a proper event notification API
This example makes use of the JIDE Common Layer API (the JideScrollPane in particular), you can get a copy from here
import com.jidesoft.swing.JideScrollPane;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.ScrollPaneConstants;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
public class WorkSheetReport {
public static final Color WORKING_HOURS_COLOR = new Color(93, 89, 88);
public static final Color LUNCH_HOURS_COLOR = new Color(215, 142, 27);
public static final Color OTHER_HOURS_COLOR = new Color(30, 141, 213);
public static void main(String[] args) {
new WorkSheetReport();
}
public WorkSheetReport() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
DefaultTimeSheetReport report = new DefaultTimeSheetReport();
report.add(createTimeSheet(
"NWD/Full"));
report.add(createTimeSheet(
"Present",
new DefaultTimeEntry(WorkType.WORK, 10, 12.5),
new DefaultTimeEntry(WorkType.LUNCH, 12.5, 13.25),
new DefaultTimeEntry(WorkType.WORK, 13.25, 18),
new DefaultTimeEntry(WorkType.OTHER, 18, 18.5),
new DefaultTimeEntry(WorkType.WORK, 18.5, 20.5)));
report.add(createTimeSheet(
"0.5UUPL",
new DefaultTimeEntry(WorkType.WORK, 10, 12.5),
new DefaultTimeEntry(WorkType.LUNCH, 12.5, 17.75),
new DefaultTimeEntry(WorkType.OTHER, 17.75, 18),
new DefaultTimeEntry(WorkType.WORK, 18, 20)));
report.add(createTimeSheet(
"Present",
new DefaultTimeEntry(WorkType.WORK, 11, 13),
new DefaultTimeEntry(WorkType.LUNCH, 13, 13.5),
new DefaultTimeEntry(WorkType.WORK, 13.5, 17.75),
new DefaultTimeEntry(WorkType.OTHER, 17.75, 18),
new DefaultTimeEntry(WorkType.WORK, 18, 20.5)));
report.add(createTimeSheet(
"Present",
new DefaultTimeEntry(WorkType.WORK, 10, 12.75),
new DefaultTimeEntry(WorkType.LUNCH, 12.75, 13.5),
new DefaultTimeEntry(WorkType.WORK, 13.5, 17.5),
new DefaultTimeEntry(WorkType.OTHER, 17.5, 17.75),
new DefaultTimeEntry(WorkType.WORK, 17.75, 20.5)));
report.add(createTimeSheet(
"Present",
new DefaultTimeEntry(WorkType.WORK, 9.75, 12),
new DefaultTimeEntry(WorkType.LUNCH, 12, 12.5),
new DefaultTimeEntry(WorkType.WORK, 12.5, 17.25),
new DefaultTimeEntry(WorkType.OTHER, 17.25, 17.75),
new DefaultTimeEntry(WorkType.WORK, 17.75, 20)));
report.add(createTimeSheet(
"Present",
new DefaultTimeEntry(WorkType.WORK, 10, 11.75),
new DefaultTimeEntry(WorkType.LUNCH, 11.75, 12.25),
new DefaultTimeEntry(WorkType.WORK, 12.25, 17.5),
new DefaultTimeEntry(WorkType.OTHER, 17.5, 18),
new DefaultTimeEntry(WorkType.WORK, 18, 20.25)));
report.add(createTimeSheet(
"NWD/Full"));
report.add(createTimeSheet(
"Present",
new DefaultTimeEntry(WorkType.WORK, 10, 12.5),
new DefaultTimeEntry(WorkType.LUNCH, 12.5, 13.5),
new DefaultTimeEntry(WorkType.WORK, 13.5, 18),
new DefaultTimeEntry(WorkType.OTHER, 18, 18.5),
new DefaultTimeEntry(WorkType.WORK, 18.5, 20.5)));
TimeSheetReportPane pane = new TimeSheetReportPane(report);
JFrame frame = new JFrame("Testing");
frame.getContentPane().setBackground(Color.BLACK);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JideScrollPane sp = new JideScrollPane(pane);
sp.setColumnHeadersHeightUnified(true);
frame.add(sp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected TimeSheet createTimeSheet(String name, TimeEntry... entries) {
DefaultTimeSheet ts = new DefaultTimeSheet(name);
for (TimeEntry entry : entries) {
ts.add(entry);
}
return ts;
}
protected static String format(double time) {
time *= 60 * 60; // to seconds
int hours = (int) Math.floor(time / (60 * 60));
double remainder = time % (60 * 60);
int mins = (int) Math.floor(remainder / 60);
int secs = (int) Math.floor(time % 60);
return hours + ":" + mins + ":" + secs;
}
public class TimeSheetReportPane extends JPanel {
private TimeSheetReport report;
private int columnWidth;
private int rowHeight;
public TimeSheetReportPane(TimeSheetReport report) {
this.report = report;
setLayout(new GridBagLayout());
setBackground(Color.BLACK);
FontMetrics fm = getFontMetrics(UIManager.getFont("Label.font"));
columnWidth = fm.stringWidth("0000");
rowHeight = fm.getHeight() + 8;
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(0, 0, 1, 0);
int count = 0;
for (TimeSheet ts : report) {
Color color = getColorForSheet(count);
TimeSheetPane pane = new TimeSheetPane(this, ts);
pane.setBackground(color);
add(pane, gbc);
count++;
}
gbc.weighty = 1;
JPanel fill = new JPanel();
fill.setOpaque(false);
add(fill, gbc);
}
public Color getColorForSheet(int index) {
Color endColor = Color.GRAY;
Color startColor = Color.DARK_GRAY;
double progress = (double) index / (double) getReport().size();
return blend(startColor, endColor, progress);
}
public TimeSheetReport getReport() {
return report;
}
public int getRowHeight() {
return rowHeight;
}
public int getColumnWidth() {
return columnWidth;
}
#Override
public void addNotify() {
super.addNotify();
configureEnclosingScrollPane();
}
protected void configureEnclosingScrollPane() {
Container parent = getParent();
if (parent instanceof JViewport) {
JViewport viewport = (JViewport) parent;
parent = viewport.getParent();
if (parent instanceof JideScrollPane) {
JideScrollPane sp = (JideScrollPane) parent;
sp.setRowFooterView(new RowFooter(this));
}
if (parent instanceof JScrollPane) {
JScrollPane sp = (JScrollPane) parent;
JLabel leftHeader = new JLabel("Status");
leftHeader.setForeground(Color.WHITE);
leftHeader.setBackground(Color.BLACK);
leftHeader.setOpaque(true);
leftHeader.setHorizontalAlignment(JLabel.CENTER);
leftHeader.setVerticalAlignment(JLabel.TOP);
leftHeader.setBorder(new EdgeBorder(EdgeBorder.Edge.RIGHT, Color.WHITE, Color.BLACK));
sp.setCorner(ScrollPaneConstants.UPPER_LEFT_CORNER, leftHeader);
JLabel rightHeader = new JLabel("Working Hr");
rightHeader.setForeground(Color.WHITE);
rightHeader.setBackground(Color.BLACK);
rightHeader.setOpaque(true);
rightHeader.setHorizontalAlignment(JLabel.CENTER);
rightHeader.setBorder(new EdgeBorder(EdgeBorder.Edge.LEFT, Color.WHITE, Color.BLACK));
sp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, rightHeader);
sp.setRowHeaderView(new RowHeader(this));
sp.setColumnHeaderView(new ColumnHeader(this));
}
}
}
}
public class ColumnHeader extends JPanel {
private TimeSheetReportPane reportPane;
public ColumnHeader(TimeSheetReportPane tsrp) {
reportPane = tsrp;
setBackground(Color.BLACK);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridheight = GridBagConstraints.REMAINDER;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.VERTICAL;
gbc.ipady = 8;
Border border = new MatteBorder(0, 0, 0, 1, Color.GRAY);
for (int hour = 8; hour < 25; hour++) {
JLabel label = new JLabel(Integer.toString(hour)) {
#Override
public Dimension getPreferredSize() {
Dimension dim = super.getPreferredSize();
dim.width = reportPane.getColumnWidth();
return dim;
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
};
label.setVerticalAlignment(JLabel.TOP);
label.setHorizontalAlignment(JLabel.CENTER);
label.setForeground(Color.WHITE);
label.setBorder(border);
add(label, gbc);
}
gbc.weightx = 1;
JPanel fill = new JPanel();
fill.setOpaque(false);
add(fill, gbc);
}
}
public class RowHeader extends JPanel {
private TimeSheetReportPane reportPane;
public RowHeader(TimeSheetReportPane tsrp) {
reportPane = tsrp;
setBackground(Color.BLACK);
setLayout(new GridBagLayout());
TimeSheetReport tsr = reportPane.getReport();
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.ipadx = 16;
gbc.ipady = 2;
gbc.insets = new Insets(0, 0, 1, 0);
int index = 0;
for (TimeSheet ts : tsr) {
JLabel label = new JLabel(ts.getName()) {
#Override
public Dimension getPreferredSize() {
Dimension dim = super.getPreferredSize();
dim.height = reportPane.getRowHeight();
return dim;
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
};
label.setHorizontalAlignment(JLabel.CENTER);
label.setForeground(Color.WHITE);
label.setBackground(reportPane.getColorForSheet(index));
label.setOpaque(true);
add(label, gbc);
index++;
}
gbc.weighty = 1;
JPanel fill = new JPanel();
fill.setOpaque(false);
add(fill, gbc);
}
}
public class RowFooter extends JPanel {
private TimeSheetReportPane reportPane;
public RowFooter(TimeSheetReportPane tsrp) {
reportPane = tsrp;
setBackground(Color.BLACK);
setLayout(new GridBagLayout());
TimeSheetReport tsr = reportPane.getReport();
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.ipadx = 36;
gbc.ipady = 2;
gbc.insets = new Insets(0, 0, 1, 0);
int index = 0;
for (TimeSheet ts : tsr) {
double time = ts.getWorkingHours();
String workHrs = "";
if (time > 0) {
workHrs = format(time);
}
JLabel label = new JLabel(workHrs) {
#Override
public Dimension getPreferredSize() {
Dimension dim = super.getPreferredSize();
dim.height = reportPane.getRowHeight();
return dim;
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
};
label.setHorizontalAlignment(JLabel.CENTER);
label.setForeground(Color.WHITE);
label.setBackground(reportPane.getColorForSheet(index));
label.setOpaque(true);
add(label, gbc);
index++;
}
gbc.weighty = 1;
JPanel fill = new JPanel();
fill.setOpaque(false);
add(fill, gbc);
}
}
public static class EdgeBorder implements Border {
public enum Edge {
LEFT,
RIGHT
}
private Edge edge;
private Color startColor;
private Color endColor;
public EdgeBorder(Edge edge, Color startColor, Color endColor) {
this.edge = edge;
this.startColor = startColor;
this.endColor = endColor;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
int xPos = x;
switch (edge) {
case RIGHT:
xPos = x + (width - 1);
}
LinearGradientPaint lgp = new LinearGradientPaint(
new Point(x, 0),
new Point(x, height),
new float[]{0, 1},
new Color[]{startColor, endColor});
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(lgp);
g2d.drawLine(xPos, y, xPos, y + height);
}
#Override
public Insets getBorderInsets(Component c) {
int left = edge == Edge.LEFT ? 1 : 0;
int right = edge == Edge.RIGHT ? 1 : 0;
return new Insets(0, left, 0, right);
}
#Override
public boolean isBorderOpaque() {
return false;
}
}
/**
* Blend two colors.
*
* #param color1 First color to blend.
* #param color2 Second color to blend.
* #param ratio Blend ratio. 0.5 will give even blend, 1.0 will return color1,
* 0.0 will return color2 and so on.
* #return Blended color.
*/
public static Color blend(Color color1, Color color2, double ratio) {
float r = (float) ratio;
float ir = (float) 1.0 - r;
float rgb1[] = new float[3];
float rgb2[] = new float[3];
color1.getColorComponents(rgb1);
color2.getColorComponents(rgb2);
float red = rgb1[0] * r + rgb2[0] * ir;
float green = rgb1[1] * r + rgb2[1] * ir;
float blue = rgb1[2] * r + rgb2[2] * ir;
if (red < 0) {
red = 0;
} else if (red > 255) {
red = 255;
}
if (green < 0) {
green = 0;
} else if (green > 255) {
green = 255;
}
if (blue < 0) {
blue = 0;
} else if (blue > 255) {
blue = 255;
}
Color color = null;
try {
color = new Color(red, green, blue);
} catch (IllegalArgumentException exp) {
exp.printStackTrace();
}
return color;
}
public class TimeSheetPane extends JPanel {
private final JPanel timeEntriesPane;
public TimeSheetPane(TimeSheetReportPane reportPane, TimeSheet ts) {
timeEntriesPane = new JPanel(new TimeSheetLayoutManager(reportPane.getColumnWidth(), reportPane.getRowHeight()));
timeEntriesPane.setBackground(Color.BLACK);
setBorder(new EmptyBorder(1, 0, 1, 0));
setLayout(new BorderLayout());
add(timeEntriesPane);
for (TimeEntry te : ts) {
JLabel label = createLabel(te.getType().getColor());
String startTime = format(te.getStartTime());
String duration = format(te.getDuration());
label.setToolTipText("<html>StartTime: " + startTime + "<br>Duration: " + duration);
timeEntriesPane.add(label, te);
}
}
protected JLabel createLabel(Color color) {
JLabel label = new JLabel();
label.setOpaque(true);
label.setBackground(color);
return label;
}
}
public class TimeSheetLayoutManager implements LayoutManager2 {
private Map<Component, TimeEntry> mapConstraints;
private int colWidth;
private int rowHeight;
public TimeSheetLayoutManager(int colWidth, int rowHeight) {
mapConstraints = new HashMap<>(25);
this.colWidth = colWidth;
this.rowHeight = rowHeight;
}
#Override
public void addLayoutComponent(Component comp, Object constraints) {
if (constraints instanceof TimeEntry) {
mapConstraints.put(comp, (TimeEntry) constraints);
} else {
throw new IllegalArgumentException(
constraints == null ? "Null is not a valid constraint"
: constraints.getClass().getName() + " is not a valid TimeEntry constraint"
);
}
}
#Override
public Dimension maximumLayoutSize(Container target) {
return preferredLayoutSize(target);
}
#Override
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
#Override
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
#Override
public void invalidateLayout(Container target) {
}
#Override
public void addLayoutComponent(String name, Component comp) {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void removeLayoutComponent(Component comp) {
mapConstraints.remove(comp);
}
#Override
public Dimension preferredLayoutSize(Container parent) {
return new Dimension(colWidth * (24 - 8), rowHeight);
}
#Override
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
#Override
public void layoutContainer(Container parent) {
Insets insets = parent.getInsets();
int width = parent.getWidth() - (insets.left + insets.right);
int height = rowHeight;
int hourWidth = colWidth;
int offset = 8;
for (Component comp : mapConstraints.keySet()) {
TimeEntry te = mapConstraints.get(comp);
double startTime = te.getStartTime();
double duration = te.getDuration();
startTime -= offset;
int x = (int) Math.round(startTime * hourWidth);
int unitWidth = (int) Math.round(duration * hourWidth);
comp.setLocation(x, insets.top);
comp.setSize(unitWidth, height);
}
}
}
public enum WorkType {
WORK(WORKING_HOURS_COLOR),
LUNCH(LUNCH_HOURS_COLOR),
OTHER(OTHER_HOURS_COLOR);
private Color color;
private WorkType(Color color) {
this.color = color;
}
public Color getColor() {
return color;
}
}
public interface TimeEntry {
public WorkType getType();
public double getStartTime();
public double getDuration();
}
public interface TimeSheet extends Iterable<TimeEntry> {
public String getName();
public int size();
public TimeEntry get(int index);
public double getWorkingHours();
}
public interface TimeSheetReport extends Iterable<TimeSheet> {
public int size();
public TimeSheet get(int index);
}
public class DefaultTimeEntry implements TimeEntry {
private final double startTime;
private final double endTime;
private final WorkType workType;
public DefaultTimeEntry(WorkType type, double startTime, double endTime) {
this.startTime = startTime;
this.endTime = endTime;
this.workType = type;
}
#Override
public double getStartTime() {
return startTime;
}
public double getEndTime() {
return endTime;
}
#Override
public double getDuration() {
return endTime - startTime;
}
#Override
public WorkType getType() {
return workType;
}
}
public class DefaultTimeSheet implements TimeSheet {
private final List<TimeEntry> timeEntries;
private final String name;
public DefaultTimeSheet(String name) {
this.name = name;
timeEntries = new ArrayList<>(25);
}
public TimeSheet add(TimeEntry te) {
timeEntries.add(te);
return this;
}
#Override
public Iterator<TimeEntry> iterator() {
return timeEntries.iterator();
}
#Override
public int size() {
return timeEntries.size();
}
#Override
public TimeEntry get(int index) {
return timeEntries.get(index);
}
#Override
public String getName() {
return name;
}
#Override
public double getWorkingHours() {
double time = 0;
for (TimeEntry te : this) {
switch (te.getType()) {
case WORK:
time += te.getDuration();
break;
}
}
return time;
}
}
public class DefaultTimeSheetReport implements TimeSheetReport {
private final List<TimeSheet> timeSheets;
public DefaultTimeSheetReport() {
timeSheets = new ArrayList<>(25);
}
public DefaultTimeSheetReport add(TimeSheet ts) {
timeSheets.add(ts);
return this;
}
#Override
public int size() {
return timeSheets.size();
}
#Override
public TimeSheet get(int index) {
return timeSheets.get(index);
}
#Override
public Iterator<TimeSheet> iterator() {
return timeSheets.iterator();
}
}
}
I have a problem with my repaint in the method move. I dont know what to doo, the code is below
import java.awt.*;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.event.*;
import java.lang.*;
public class bbb extends JPanel
{
public Stack<Integer> stacks[];
public JButton auto, jugar, nojugar;
public JButton ok, ok2;
public JLabel info = new JLabel("Numero de Discos: ");
public JLabel instruc = new JLabel("Presiona la base de las torres para mover las fichas");
public JLabel instruc2 = new JLabel("No puedes poner una pieza grande sobre una pequenia!");
public JComboBox numeros = new JComboBox();
public JComboBox velocidad = new JComboBox();
public boolean seguir = false, parar = false, primera = true;
public int n1, n2, n3;
public int click1 = 0;
public int opcion = 1, tiempo = 50;
public int op = 1, continuar = 0, cont = 0;
public int piezas = 0;
public int posx, posy;
public int no;
public bbb() throws IOException
{
stacks = new Stack[3];
stacks[0] = new Stack<Integer>();
stacks[1] = new Stack<Integer>();
stacks[2] = new Stack<Integer>();
setPreferredSize(new Dimension(1366, 768));
ok = new JButton("OK");
ok.setBounds(new Rectangle(270, 50, 70, 25));
ok.addActionListener(new okiz());
ok2 = new JButton("OK");
ok2.setBounds(new Rectangle(270, 50, 70, 25));
ok2.addActionListener(new vel());
add(ok2);
ok2.setVisible(false);
auto = new JButton("Automatico");
auto.setBounds(new Rectangle(50, 80, 100, 25));
auto.addActionListener(new a());
jugar = new JButton("PLAY");
jugar.setBounds(new Rectangle(100, 100, 70, 25));
jugar.addActionListener(new play());
nojugar = new JButton("PAUSE");
nojugar.setBounds(new Rectangle(100, 150, 70, 25));
nojugar.addActionListener(new stop());
setLayout(null);
info.setBounds(new Rectangle(50, 50, 170, 25));
info.setForeground(Color.white);
instruc.setBounds(new Rectangle(970, 50, 570, 25));
instruc.setForeground(Color.white);
instruc2.setBounds(new Rectangle(970, 70, 570, 25));
instruc2.setForeground(Color.white);
add(instruc);
add(instruc2);
add(jugar);
add(nojugar);
jugar.setVisible(false);
nojugar.setVisible(false);
add(info);
info.setVisible(false);
add(ok);
ok.setVisible(false);
add(auto);
numeros.setBounds(new Rectangle(210, 50, 50, 25));
numeros.addItem(1);
numeros.addItem(2);
numeros.addItem(3);
numeros.addItem(4);
numeros.addItem(5);
numeros.addItem(6);
numeros.addItem(7);
numeros.addItem(8);
numeros.addItem(9);
numeros.addItem(10);
add(numeros);
numeros.setVisible(false);
velocidad.setBounds(new Rectangle(150, 50, 100, 25));
velocidad.addItem("Lenta");
velocidad.addItem("Intermedia");
velocidad.addItem("Rapida");
add(velocidad);
velocidad.setVisible(false);
}
public void Mover(int origen, int destino)
{
for (int i = 0; i < 3; i++)
{
System.out.print("stack " + i + ": ");
for (int n : stacks[i])
{
System.out.print(n + ";");
}
System.out.println("");
}
System.out.println("de <" + origen + "> a <" + destino + ">");
stacks[destino].push(stacks[origen].pop());
System.out.println("");
this.validate();
this.repaint();
}
public void hanoi(int origen, int destino, int cuantas)
{
while (parar)
{
}
if (cuantas <= 1)
{
Mover(origen, destino);
}
else
{
hanoi(origen, 3 - (origen + destino), cuantas - 1);
Mover(origen, destino);
hanoi(3 - (origen + destino), destino, cuantas - 1);
}
}
public void paintComponent(Graphics g)
{
ImageIcon fondo = new ImageIcon("fondo.jpg");
g.drawImage(fondo.getImage(), 0, 0, 1366, 768, null);
g.setColor(new Color((int) (Math.random() * 254),
(int) (Math.random() * 255),
(int) (Math.random() * 255)));
g.fillRect(0, 0, 100, 100);
g.setColor(Color.white);
g.fillRect(150, 600, 250, 25);
g.fillRect(550, 600, 250, 25);
g.fillRect(950, 600, 250, 25);
g.setColor(Color.red);
g.fillRect(270, 325, 10, 275);
g.fillRect(270 + 400, 325, 10, 275);
g.fillRect(270 + 800, 325, 10, 275);
int x, y, top = 0;
g.setColor(Color.yellow);
x = 150;
y = 580;
for (int ii : stacks[0])
{
g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
}
x = 550;
y = 580;
for (int ii : stacks[1])
{
g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
}
x = 950;
y = 580;
for (int ii : stacks[2])
{
g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
}
System.out.println("ENTRO");
setOpaque(false);
}
private class play implements ActionListener //manual
{
public void actionPerformed(ActionEvent algo)
{
parar = false;
if (primera = true)
{
hanoi(0, 2, no);
primera = false;
}
}
}
private class stop implements ActionListener //manual
{
public void actionPerformed(ActionEvent algo)
{
parar = true;
}
}
private class vel implements ActionListener //manual
{
public void actionPerformed(ActionEvent algo)
{
if (velocidad.getSelectedItem() == "Lenta")
{
tiempo = 150;
}
else if (velocidad.getSelectedItem() == "Intermedia")
{
tiempo = 75;
}
else
{
tiempo = 50;
}
ok2.setVisible(false);
jugar.setVisible(true);
nojugar.setVisible(true);
}
}
private class a implements ActionListener //auto
{
public void actionPerformed(ActionEvent algo)
{
auto.setVisible(false);
info.setVisible(true);
numeros.setVisible(true);
ok.setVisible(true);
op = 3;
}
}
private class okiz implements ActionListener //ok
{
public void actionPerformed(ActionEvent algo)
{
no = Integer.parseInt(numeros.getSelectedItem().toString());
piezas = no;
if (no > 0 && no < 11)
{
info.setVisible(false);
numeros.setVisible(false);
ok.setVisible(false);
for (int i = no; i > 0; i--)
{
stacks[0].push(i);
}
opcion = 2;
if (op == 3)
{
info.setText("Velocidad: ");
info.setVisible(true);
velocidad.setVisible(true);
ok2.setVisible(true);
}
}
else
{
}
repaint();
}
}
}
the code of the other class that calls the one up is below:
import java.awt.*;
import java.io.*;
import java.net.URL;
import javax.imageio.*;
import javax.swing.*;
import javax.swing.border.*;
import java.lang.*;
import java.awt.event.*;
public class aaa extends JPanel
{
private ImageIcon Background;
private JLabel fondo;
public static void main(String[] args) throws IOException
{
JFrame.setDefaultLookAndFeelDecorated(true);
final JPanel cp = new JPanel(new BorderLayout());
JFrame frame = new JFrame ("Torres de Hanoi");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setSize(550,550);
frame.setVisible(true);
bbb panel = new bbb();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
Assuming that you see the progress in the println statements but not on the screen, it is because a call to repaint is not synchronous. Swing has a special thread for handling UI - called Event Dispatch Thread. A call to repaint is handled by that thread, but asynchronously - after all the current events scheduled on that thread have been processed.
When you call hanoi in your actionPerformed, that is done on the same UI thread. What happens is that until your recursion is fully done, repaint() calls are just queued. Once the recursion completes (and all stacks have been moved in the model), the UI thread processes all repaint() requests, painting - what i assume - the final state.
What you need to do is to separate the model processing into a separate worker thread. On every recursion step, issue a repaint() call and sleep for a few hundred milliseconds. This will allow the UI thread to repaint the current state of the model and let the user actually trace the progress.
This one's a tough one - I have a JFrame that generates JTextFields. When I go from generating 2 JTextFields to 12 JTextfields (for example), I see some error where there is an extra differently-sized JTextField at the end. It seems to be a repaint error.
Main.java code:
import java.awt.*;
import javax.swing.*;
public class Main {
public static Display display = new Display();
public static void main(String[] args) {
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
display.setVisible(true);
}
}
Display.java code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Display extends JFrame {
final int FRAME_WIDTH = 820;
final int FRAME_HEIGHT = 700;
final int X_OFFSET = 40;
final int Y_OFFSET = 40;
final int GRAPH_OFFSETX = 35;
final int GRAPH_OFFSETY = 60;
final int GRAPH_WIDTH = 500;
final int GRAPH_HEIGHT = 500;
final int GRAPH_INTERVAL = 20;
JButton submit;
JTextField top;
JTextField bottom;
JTextField numPoint;
JPanel bpanel;
JPanel points;
int maxPoints;
public Display() {
init();
}
public void init() {
setBackground(Color.WHITE);
setLocation(X_OFFSET, Y_OFFSET);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setTitle("Geometric Transformations");
getContentPane().setLayout(null);
setDefaultLookAndFeelDecorated(true);
top = new JTextField(); // parameter is size of input characters
top.setText("1 2 3");
top.setBounds(590, 150, 120, 25);
bottom = new JTextField(); // parameter is size of input characters
bottom.setText("5 6 7");
bottom.setBounds(590, 200, 120, 25);
numPoint = new JTextField();
numPoint.setText("Number of Points?");
numPoint.setBounds(550,200,200,25);
this.add(numPoint);
SubmitButton submit = new SubmitButton("Submit");
submit.setBounds(570, 250, 170, 25);
bpanel = new JPanel(new GridLayout(2,3));
bpanel.add(top);
bpanel.add(bottom);
bpanel.add(submit);
points = new JPanel(new GridLayout(2,2));
points.setBounds(540,250,265,60);
this.add(points);
bpanel.setBounds(550,100,200,70);
this.add(bpanel, BorderLayout.LINE_START);
Component[] a = points.getComponents();
System.out.println(a.length);
repaint();
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.WHITE);
g.fillRect(100, 100, 20, 30);
g.setColor(Color.BLACK);
genGraph(g, GRAPH_OFFSETX, GRAPH_OFFSETY, GRAPH_WIDTH, GRAPH_HEIGHT, GRAPH_INTERVAL);
}
public void genGraph (Graphics g, int x, int y, int width, int height, int interval) {
// draw background
int border = 5;
g.setColor(Color.BLACK);
width = width - (width % interval);
height = height - (height % interval);
for (int col=x; col <= x+width; col+=interval) {
g.drawLine(col, y, col, y+height);
}
for (int row=y; row <= y+height; row+=interval) {
g.drawLine(x, row, x+width, row);
}
}
class SubmitButton extends JButton implements ActionListener {
public SubmitButton(String title){
super(title);
addActionListener(this);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
maxPoints = Integer.parseInt(numPoint.getText()) * 2;
points.removeAll();
for (int i=0; i<maxPoints; i++) {
JTextField textField = new JTextField();
points.add(textField);
}
points.validate(); // necessary when adding components to a JPanel
// http://stackoverflow.com/questions/369823/java-gui-repaint-problem-solved
// What to Check:
// Things between commas are either spaces (which will be stripped later)
// or numbers!
// Pairs must match up!
}
}
}
The new components are redrawn over the previous ones.
I added points.repaint(); after points.validate(); and the problem was gone.
Note: I was annoyed with the issue of repainting of the grid too (put the window in front then back, you will see).
From a quick search, it seems better to avoid painting directly on the JFrame, but instead delegate that to a sub-component. If I am wrong, somebody tell me.
Here is my solution (imperfect, I leave to you the task to improve it... :-P
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SODisplay extends JFrame {
final int FRAME_WIDTH = 820;
final int FRAME_HEIGHT = 700;
final int X_OFFSET = 40;
final int Y_OFFSET = 40;
JButton submit;
JTextField top;
JTextField bottom;
JTextField numPoint;
JPanel bpanel;
JPanel points;
GridPanel grid;
int maxPoints;
public SODisplay() {
init();
}
public void init() {
setBackground(Color.WHITE);
setLocation(X_OFFSET, Y_OFFSET);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setTitle("Geometric Transformations");
getContentPane().setLayout(null);
setDefaultLookAndFeelDecorated(true);
grid = new GridPanel();
grid.setBounds(0,0,530,FRAME_HEIGHT);
this.add(grid);
top = new JTextField(); // parameter is size of input characters
top.setText("1 2 3");
top.setBounds(590, 150, 120, 25);
bottom = new JTextField(); // parameter is size of input characters
bottom.setText("5 6 7");
bottom.setBounds(590, 200, 120, 25);
numPoint = new JTextField();
numPoint.setText("Number of Points?");
numPoint.setBounds(550,200,200,25);
this.add(numPoint);
SubmitButton submit = new SubmitButton("Submit");
submit.setBounds(570, 250, 170, 25);
bpanel = new JPanel(new GridLayout(2,3));
bpanel.add(top);
bpanel.add(bottom);
bpanel.add(submit);
points = new JPanel(new GridLayout(2,2));
points.setBounds(540,250,265,60);
this.add(points);
bpanel.setBounds(550,100,200,70);
this.add(bpanel, BorderLayout.LINE_START);
Component[] a = points.getComponents();
System.out.println(a.length);
repaint();
}
class SubmitButton extends JButton implements ActionListener {
public SubmitButton(String title){
super(title);
addActionListener(this);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
maxPoints = Integer.parseInt(numPoint.getText()) * 2;
points.removeAll();
for (int i=0; i<maxPoints; i++) {
JTextField textField = new JTextField();
points.add(textField);
}
points.validate(); // necessary when adding components to a JPanel
points.repaint();
// http://stackoverflow.com/questions/369823/java-gui-repaint-problem-solved
// What to Check:
// Things between commas are either spaces (which will be stripped later)
// or numbers!
// Pairs must match up!
}
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
SODisplay display = new SODisplay();
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
display.setVisible(true);
}
});
}
class GridPanel extends JPanel {
// Or drop the offset and adjust the placement of the component
final int GRAPH_OFFSETX = 35;
final int GRAPH_OFFSETY = 60;
final int GRAPH_WIDTH = 500;
final int GRAPH_HEIGHT = 500;
final int GRAPH_INTERVAL = 20;
public GridPanel() {
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.WHITE);
g.fillRect(100, 100, 20, 30);
g.setColor(Color.BLACK);
genGraph(g, GRAPH_OFFSETX, GRAPH_OFFSETY, GRAPH_WIDTH, GRAPH_HEIGHT, GRAPH_INTERVAL);
}
public void genGraph (Graphics g, int x, int y, int width, int height, int interval) {
// draw background
int border = 5;
g.setColor(Color.BLACK);
width = width - (width % interval);
height = height - (height % interval);
for (int col=x; col <= x+width; col+=interval) {
g.drawLine(col, y, col, y+height);
}
for (int row=y; row <= y+height; row+=interval) {
g.drawLine(x, row, x+width, row);
}
}
}
}
That's just my test code in one file for simplicity, you might want to dissect it differently, of course.