How to implement my last Method(paint) here? - java

So, i kinda wrote this Code for the game called "towers of hanoi".
The code i had before was showing the moves for every step in the console. I am trying to show the moves graphically.
I think i came pretty far, but i cant implement the paint Method.
I tried several things like g.drawRect(s1.x,s1.y+200,s1.width,s1.height); but its just showing an rectangle, no moves etc.
Heres my Code:
import java.io.*;
import java.util.*;
import java.awt.*;
public class hanoi {
public static void ziehe_scheibe(MyFrame f,Pole von, Pole nach) {
int hs = von.onPole.size();
int ht = nach.onPole.size();
int hy = -25*(ht-hs+1);
int hx = (nach.xPos - von.xPos);
String d = von.scheibenehmen();
nach.scheibelegen(d);
f.moveDisk(d,hx,hy);
}
public static void hanoi(MyFrame f,int n, Pole platz1, Pole platz2, Pole hilfsplatz) {
if ( n==1 )
ziehe_scheibe(f,platz1,platz2);
else
{ hanoi(f,n-1,platz1,hilfsplatz,platz2);
ziehe_scheibe(f,platz1,platz2);
hanoi(f,n-1,hilfsplatz,platz2,platz1);
}
}
public static int xSize(String d) {
if ( d == "klein" ) return 30;
if ( d == "mittel" ) return 40;
else return 50;
}
public static void main(String args[]) {
Pole p1 = new Pole("a",60);
Pole p2 = new Pole("b",180);
Pole p3 = new Pole("c",300);
p1.scheibelegen("groß");
p1.scheibelegen("mittel");
p1.scheibelegen("klein");
Rectangle r1 = new Rectangle(p1.xPos-50,50,100,20);
Rectangle r2 = new Rectangle(p1.xPos-40,25,80,20);
Rectangle r3 = new Rectangle(p1.xPos-30,0,60,20);
MyFrame fff = new MyFrame(r1,r2,r3);
fff.setSize(800,600);
fff.setVisible(true);
hanoi(fff,3,p1,p3,p2);
}
}
// Frame-Klasse zur Anzeige des Zustandes
class MyFrame extends Frame {
public Rectangle s1, s2, s3;
public MyFrame(Rectangle a, Rectangle b, Rectangle c) {
s1 = a; s2 = b; s3 = c;
}
public void paint(Graphics g) {
}
public Rectangle xRect(String d) {
if ( d == "klein" ) return s3;
if ( d == "mittel" ) return s2;
else return s1;
}
public void moveDisk(String name,int dx,int dy)
{ xRect(name).translate(dx,dy);
repaint();
try
{ System.in.read();System.in.read(); }
catch (Exception e) {}
}
}
// Pole-Klasse: Repräsentation eines Stabes
class Pole {
public String label;
public Vector onPole;
public int xPos;
public Pole(String s, int i) {
onPole=new Vector();
label = s; xPos = i;
}
public void scheibelegen(String d) {
this.onPole.addElement(d);
}
public String scheibenehmen() {
Object lastEl = this.onPole.lastElement();
String lastElStr = lastEl.toString();
this.onPole.removeElement(lastEl);
return lastElStr;
}
}
Maybe you guys can take a look on it
btw excuse my bad english

Try
public static int xSize(String d) {
if ( d.equals("klein")) return 30;
if ( d.equals("mittel")) return 40;
else return 50;
}

Related

Swing draws 3 JLabels instead of one

I don't really understand why this program draws three pawns instead of one and two of which seem to have a random(probably not so random) positions. enter image description here
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GamePanel extends JPanel implements MouseListener {
static final int SCREEN_EDGE = 800;
static final int GAME_UNITS = 64;
static final int UNIT_SIZE = 100;
final int[] x = new int[GAME_UNITS];
final int[] y = new int[GAME_UNITS];
boolean running = false;
public GamePanel() {
this.setPreferredSize(new Dimension(SCREEN_EDGE, SCREEN_EDGE));
this.setFocusable(true);
this.addKeyListener(new MyKeyAdapter());
startGame();
int[] position = {0,0};
int[] position1 = {1, 0};
new Pawn(position,-1);
}
private void startGame() {
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g){
int counter = 1;
for (int y = 0; y < SCREEN_EDGE/UNIT_SIZE; y++) {
// 1 == "white" 2 == "black"
int color = (y % 2 == 0) ? 1 : 2;
for (int x = 0; x < SCREEN_EDGE/UNIT_SIZE; x++) {
g.setColor(color == 1 ? new Color(239,217, 181) : new Color(180, 136,98));
g.fillRect(x*UNIT_SIZE, y*UNIT_SIZE, UNIT_SIZE, UNIT_SIZE);
color = color == 1 ? 2 : 1;
}
}
for (int i = 0; i < Figure.figures.length; i++) {
JLabel figureSprite = new JLabel(Figure.figures[i].image, JLabel.CENTER);
figureSprite.setSize(90,90);
figureSprite.setLocation(Figure.figures[i].position[0] + 5,Figure.figures[i].position[1] + 5);
this.add(figureSprite);
}
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
public class MyKeyAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
}
}
}
import javax.swing.*;
public abstract class Figure{
protected int value;
protected ImageIcon image;
protected int[][] possibleMoves;
public int[] position;
// white = -1 black = 1
protected int whiteOrBlack;
protected static int figureCount = 1;
// int[figureCount][0 = x][1 = y][2 = color]
public static Figure[] figures = new Figure[figureCount];
public Figure(int value, int[] position, int[][] possibleMoves , int whiteOrBlack) {
this.value = value;
this.position = position;
this.possibleMoves = possibleMoves;
this.whiteOrBlack = whiteOrBlack;
Figure[] oldFigures = figures;
figures = new Figure[figureCount];
for (int i = 0; i < oldFigures.length; i++) {
figures[i] = oldFigures[i];
}
figures[figureCount - 1] = this;
figureCount++;
}
public abstract void move(int[] coordinates);
}
import javax.swing.*;
import java.awt.*;
import java.io.*;
public class Pawn extends Figure{
public Pawn(int[] position, int whiteOrBlack) {
super(1, position, new int[3][2], whiteOrBlack);
super.image = new ImageIcon(getClass().getClassLoader().getResource("graphics/" + (whiteOrBlack == -1 ? "whitePawn.png" : "blackPawn.png")));
Image newImage = super.image.getImage().getScaledInstance(90,90, Image.SCALE_AREA_AVERAGING);
super.image = new ImageIcon(newImage);
}
public void checkMoves(){
for (int i = 0; i < figures.length; i++) {
if((position[0] - 1) == figures[i].position[0] && (position[1] + this.whiteOrBlack) == figures[i].position[1] && figures[i].whiteOrBlack != this.whiteOrBlack) {
possibleMoves[0][0] = position[0] - 1;
possibleMoves[0][1] = position[1] + this.whiteOrBlack;
}else possibleMoves[0] = new int[2];
if((position[0]) != figures[i].position[0] && (position[1]) != figures[i].position[1]){
possibleMoves[1][0] = position[0];
possibleMoves[1][1] = position[1] + 1;
}else possibleMoves[1] = new int[2];
if((position[0] + 1) == figures[i].position[0] && (position[1] + this.whiteOrBlack) == figures[i].position[1] && figures[i].whiteOrBlack != this.whiteOrBlack) {
possibleMoves[2][0] = position[0] + 1;
possibleMoves[2][1] = position[1] + this.whiteOrBlack;
}else possibleMoves[2] = new int[2];
}
}
#Override
public void move(int[] coordinates) {
}
}
import javax.swing.*;
public class GameFrame extends JFrame {
public GameFrame(){
this.add(new GamePanel());
this.setTitle("Chess");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setResizable(false);
this.setVisible(true);
this.setLocationRelativeTo(null);
}
}
public class ChessGame {
public static void main(String[] args) {
new GameFrame();
}
}
I tried few thing like changing JLabel to BufferedImage but it would've generate other problems down the line like not being able to use MouseListener so i feel stuck. I would love to know why this code generates 3 textures too.
It looks like you are adding FigureSprites from within the drawComponent() method. The more often you draw the window, the more figures you have to draw.
Instead within drawComponent() just draw the current state but do not modify it. Adding figures has to come from somewhere else. For example, you could create the necessary pawns in the constructor. Or in extra methods that might get triggered based on user input.
In case you modify the GamePanel's state enough so that it should get painted freshly, just invoke repaint(). Swing will mark this component for repainting and decide on it's own when to run the paint() method, which in turn will run paintComponent().

JButtons not showing up after initialisation [Java Swing]

I know there are super many questions here on stack overflow about JElements not showing up, all because someone forgot to add a setVisible(true) at the end of the constructor. But at least I belive my problem is something different. I am currently creating a chess-game for college, and for that I have the
Game class: here it all comes together
the abstract Piece class extending JButton in package Pieces
and a class for Each Piece (Rook, Bishop, ...) each extending Piece and being located in the Pieces package
before I write much more and it is a dumb error again, here the code:
import javax.swing.*;
import Pieces.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Game extends JFrame {
private static final int width = 8;
private static final int height = 8;
private static Piece clicked;
private static Piece[][] fields = new Piece[width][height];
private JPanel main = new JPanel();
public static void init(JPanel g) {
for (int y = 0; y < fields.length; y++) {
for (int x = 0; x < fields[y].length; x++) {
if (y == 1) fields[y][x] = new Pawn(x, y, true); //2nd or 7th row is filled with pawns
else if (y == 6) fields[y][x] = new Pawn(x, y, false);
else {
fields[y][x] = new Empty(x,y,true);
}
fields[y][x].addActionListener(e -> {
var p = (Piece) e.getSource();
System.out.println(p.getX() + p.getY());
});
g.add(fields[y][x]);
}
}
}
public Game() {
main.setBackground(Color.blue.darker());
main.setLayout(new GridLayout(8,8));
this.setSize(800,800);
init(main);
this.add(main);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
var g = new Game();
}
}
package Pieces;
import javax.swing.*;
public abstract class Piece extends JButton {
private int x;
private int y;
private final boolean isWhite;
public Piece(int x, int y, boolean isWhite) {
this.x = x;
this.y = y;
this.isWhite = isWhite;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public boolean isWhite() {
return isWhite;
}
public boolean canMoveTo(int toX, int toY) {
return true;
}
}
each Piece-extending class is setup exactly like this:
package Pieces;
import java.awt.*;
public class Pawn extends Piece{
public Pawn(int x, int y, boolean isWhite) {
super(x, y, isWhite);
this.setText(isWhite ? "Pawn" : "pawn");
}
}
Expected behavior:
open a window with 64 JButtons in it, displaying the name of the Piece they represent (there is indeed an Empty-class for non-used fields)
Actual behavior:
opens a window with one button at the top left but first when I go over the fields with my cursor the buttons start appearing
state 1: state 1
state 2: state 2
You can't override getX and getY like this, these properties are used by the layout managers to layout the components.
Instead, maybe make use of Point to store the virtual or "cell" position
public static abstract class Piece extends JButton {
private final boolean isWhite;
private Point cell;
public Piece(int x, int y, boolean isWhite) {
cell = new Point(x, y);
this.isWhite = isWhite;
}
public Point getCell() {
return cell;
}
public boolean isWhite() {
return isWhite;
}
public boolean canMoveTo(int toX, int toY) {
return true;
}
}
Runnable example...
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.GridLayout;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new BoardPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BoardPane extends JPanel {
private static final int width = 8;
private static final int height = 8;
private Piece clicked;
private Piece[][] fields = new Piece[width][height];
public BoardPane() {
setBackground(Color.blue.darker());
setLayout(new GridLayout(8, 8));
buildBoard();
}
protected void buildBoard() {
for (int y = 0; y < fields.length; y++) {
for (int x = 0; x < fields[y].length; x++) {
if (y == 1) {
fields[y][x] = new Pawn(x, y, true); //2nd or 7th row is filled with pawns
} else if (y == 6) {
fields[y][x] = new Pawn(x, y, false);
} else {
fields[y][x] = new Empty(x,y,true);
}
fields[y][x].addActionListener(e -> {
var p = (Piece) e.getSource();
System.out.println(p.getCell());
});
add(fields[y][x]);
}
}
}
}
public static abstract class Piece extends JButton {
private final boolean isWhite;
private Point cell;
public Piece(int x, int y, boolean isWhite) {
cell = new Point(x, y);
this.isWhite = isWhite;
}
public Point getCell() {
return cell;
}
public boolean isWhite() {
return isWhite;
}
public boolean canMoveTo(int toX, int toY) {
return true;
}
}
public static class Pawn extends Piece {
public Pawn(int x, int y, boolean isWhite) {
super(x, y, isWhite);
this.setText(isWhite ? "Pawn" : "pawn");
}
}
public static class Empty extends Piece {
public Empty(int x, int y, boolean isWhite) {
super(x, y, isWhite);
this.setText("X");
}
}
}

Keybind action being run at start but not from actual key press

I'm coding a game for my final project in Java, our teacher provided us with a Board class that is a component that allows us to place and remove pegs on a virtual game board instead of having to code one ourselves. I'm trying to add Key Binding to the Board component but the action I want performed on key press is happening when I run the program but It won't run when I type a Key.
The board class already has a method for getting the position clicked on the component and I think this might be interfering with my Code but I'm not sure.
This is my game class where I tried to add keybinding
package rpgGame;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
public class RPGGame
{
public static final GameWorld WORLD_MAP = new GameWorld();
public static Board LOCAL_MAP = new Board(20,50);
public static List<Mobile> allMobs = new ArrayList<Mobile>();
public static final Player PLAYER = new Player();
public static int xIndex = ((GameWorld.WORLD_SIZE-1)/2) - (50/2);
public static int yIndex = ((GameWorld.WORLD_SIZE-1)/2) - (20/2);
public static boolean boardUpdate = true;
public enum Direction {RIGHT,LEFT,UP,DOWN}
private static final String MOVE_PLAYER_UP = "move up";
private static final String MOVE_PLAYER_LEFT = "move left";
private static final String MOVE_PLAYER_RIGHT = "move right";
private static final String MOVE_PLAYER_DOWN = "move down";
public static final Thread SYNC_BOARD = new Thread()
{
public synchronized void run()
{
while (boardUpdate)
{
for (int i = 0; i < 50; i++)
{
for (int j = 0; j < 20; j++)
{
if (WORLD_MAP.isOccupied(i+xIndex, j+yIndex))
{
LOCAL_MAP.putPeg(Color.RED, j, i);
System.out.println("Successfully Updated");
}
else
{
LOCAL_MAP.putPeg(Color.GRAY, j,i);
}
}
}
boardUpdate = false;
}
}
};
public RPGGame()
{
generateMobs(200);
placeMobs();
placePlayer();
SYNC_BOARD.run();
LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), MOVE_PLAYER_UP);
LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), MOVE_PLAYER_UP);
LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), MOVE_PLAYER_LEFT);
LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), MOVE_PLAYER_LEFT);
LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), MOVE_PLAYER_RIGHT);
LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), MOVE_PLAYER_RIGHT);
LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), MOVE_PLAYER_DOWN);
LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), MOVE_PLAYER_DOWN);
LOCAL_MAP.getActionMap().put(MOVE_PLAYER_UP, new MoveAction(Direction.UP));
LOCAL_MAP.getActionMap().put(MOVE_PLAYER_LEFT, new MoveAction(Direction.LEFT));
LOCAL_MAP.getActionMap().put(MOVE_PLAYER_RIGHT, new MoveAction(Direction.RIGHT));
LOCAL_MAP.getActionMap().put(MOVE_PLAYER_DOWN, new MoveAction(Direction.DOWN));
}
public static void main(String[] args)
{
new RPGGame();
}
public static void generateMobs(int numOfMobs)
{
for (int i=0; i<numOfMobs; i++)
{
allMobs.add(new Mobile());
}
}
public static void generateMobs()
{
int numOfMobs = (int)(Math.random()*500);
for (int i=0;i<numOfMobs; i++)
{
allMobs.add(new Mobile());
}
}
public static void placeMobs()
{
for (int i=0; i<allMobs.size(); i++)
{
//i is used as a placeholder value for points until I create a random number generator.
WORLD_MAP.placeCharacter(i, i,allMobs.get(i));
allMobs.get(i).setLocation(i, i);
}
}
public static void placePlayer()
{
WORLD_MAP.placeCharacter(249, 249, PLAYER);
PLAYER.setLocation(249, 249);
}
#SuppressWarnings("serial")
public class MoveAction extends AbstractAction
{
Direction direction;
public MoveAction(Direction direction)
{
if (direction.equals(Direction.RIGHT))
{
int x = PLAYER.getX();
int y = PLAYER.getY();
WORLD_MAP.moveCharacter(x+1, y, x, y);
PLAYER.move(1, 0);
boardUpdate = true;
System.out.println("MOVE RIGHT");
}
if (direction.equals(Direction.LEFT))
{
int x = PLAYER.getX();
int y = PLAYER.getY();
WORLD_MAP.moveCharacter(x, y, x-1, y);
PLAYER.move(-1, 0);
boardUpdate = true;
System.out.println("MOVE LEFT");
}
if (direction.equals(Direction.UP))
{
int x = PLAYER.getX();
int y = PLAYER.getY();
WORLD_MAP.moveCharacter(x, y, x, y+1);
PLAYER.move(0, 1);
boardUpdate = true;
System.out.println("MOVE UP");
}
if (direction.equals(Direction.DOWN))
{
int x = PLAYER.getX();
int y = PLAYER.getY();
WORLD_MAP.moveCharacter(x, y, x, y-1);
PLAYER.move(0, -1);
boardUpdate = true;
System.out.println("MOVE DOWN");
}
}
#Override
public void actionPerformed(ActionEvent e)
{
}
}
}
This is the Board class
package rpgGame;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/** Board GUI for implementation with various games
* Author: Kirill Levin, Troy Vasiga, Chris Ingram
*/
#SuppressWarnings("serial")
public class Board extends JPanel
{
private static final int X_DIM = 60;
private static final int Y_DIM = 60;
private static final int X_OFFSET = 30;
private static final int Y_OFFSET = 30;
private static final double MIN_SCALE = 0.25;
private static final int GAP = 10;
private static final int FONT_SIZE = 16;
// Grid colours
private static final Color GRID_COLOR_A = new Color(153,255,102);
private static final Color GRID_COLOR_B = new Color(136,255,77);
private Color[][] grid;
private Point lastClick; // How the mouse handling thread communicates
// to the board where the last click occurred
private String message = "";
private int numLines = 0;
private double[][] line = new double[4][100]; // maximum number of lines is 100
private int columns, rows;
private int originalWidth;
private int originalHeight;
private double scale;
/** A constructor to build a 2D board.
*/
public Board (int rows, int columns)
{
super( true );
JFrame boardFrame = new JFrame( "Board game" );
this.columns = columns;
this.rows = rows;
originalWidth = 2*X_OFFSET+X_DIM*columns;
originalHeight = 2*Y_OFFSET+Y_DIM*rows+GAP+FONT_SIZE;
this.setPreferredSize( new Dimension( originalWidth, originalHeight ) );
boardFrame.setResizable(true);
this.grid = new Color[columns][rows];
this.addMouseListener(
new MouseInputAdapter()
{
/** A method that is called when the mouse is clicked
*/
public void mouseClicked(MouseEvent e)
{
int x = (int)e.getPoint().getX();
int y = (int)e.getPoint().getY();
// We need to by synchronized to the parent class so we can wake
// up any threads that might be waiting for us
synchronized(Board.this)
{
int curX = (int)Math.round(X_OFFSET*scale);
int curY = (int)Math.round(Y_OFFSET*scale);
int nextX = (int)Math.round((X_OFFSET+X_DIM*grid.length)*scale);
int nextY = (int)Math.round((Y_OFFSET+Y_DIM*grid[0].length)*scale);
// Subtract one from high end so clicks on the black edge
// don't yield a row or column outside of board because of
// the way the coordinate is calculated.
if (x >= curX && y >= curY && x < nextX && y < nextY)
{
lastClick = new Point(y,x);
// Notify any threads that would be waiting for a mouse click
Board.this.notifyAll() ;
} /* if */
} /* synchronized */
} /* mouseClicked */
} /* anonymous MouseInputAdapater */
);
boardFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
boardFrame.setContentPane( this );
boardFrame.pack();
boardFrame.setVisible(true);
}
/** A constructor to build a 1D board.
*/
public Board (int cols)
{
this(1, cols);
}
private void paintText(Graphics g)
{
g.setColor( this.getBackground() );
g.setFont(new Font(g.getFont().getFontName(), Font.ITALIC+Font.BOLD, (int)(Math.round(FONT_SIZE*scale))));
int x = (int)Math.round(X_OFFSET*scale);
int y = (int)Math.round((Y_OFFSET+Y_DIM*grid[0].length)*scale + GAP ) ;
g.fillRect(x,y, this.getSize().width, (int)Math.round(GAP+FONT_SIZE*scale) );
g.setColor( Color.black );
g.drawString(message, x, y + (int)Math.round(FONT_SIZE*scale));
}
private void paintGrid(Graphics g)
{
for (int i = 0; i < this.grid.length; i++)
{
for (int j = 0; j < this.grid[i].length; j++)
{
if ((i%2 == 0 && j%2 != 0) || (i%2 != 0 && j%2 == 0))
g.setColor(GRID_COLOR_A);
else
g.setColor(GRID_COLOR_B);
int curX = (int)Math.round((X_OFFSET+X_DIM*i)*scale);
int curY = (int)Math.round((Y_OFFSET+Y_DIM*j)*scale);
int nextX = (int)Math.round((X_OFFSET+X_DIM*(i+1))*scale);
int nextY = (int)Math.round((Y_OFFSET+Y_DIM*(j+1))*scale);
int deltaX = nextX-curX;
int deltaY = nextY-curY;
g.fillRect( curX, curY, deltaX, deltaY );
Color curColour = this.grid[i][j];
if (curColour != null) // Draw pegs if they exist
{
g.setColor(curColour);
g.fillOval(curX+deltaX/4, curY+deltaY/4, deltaX/2, deltaY/2);
}
}
}
((Graphics2D) g).setStroke( new BasicStroke(0.5f) );
g.setColor(Color.BLACK);
int curX = (int)Math.round(X_OFFSET*scale);
int curY = (int)Math.round(Y_OFFSET*scale);
int nextX = (int)Math.round((X_OFFSET+X_DIM*grid.length)*scale);
int nextY = (int)Math.round((Y_OFFSET+Y_DIM*grid[0].length)*scale);
g.drawRect(curX, curY, nextX-curX, nextY-curY);
}
private void drawLine(Graphics g)
{
for (int i =0; i < numLines; i++ )
{
((Graphics2D) g).setStroke( new BasicStroke( 5.0f*(float)scale) );
g.drawLine( (int)Math.round((X_OFFSET+X_DIM/2.0+line[0][i]*X_DIM)*scale),
(int)Math.round((Y_OFFSET+Y_DIM/2.0+line[1][i]*Y_DIM)*scale),
(int)Math.round((X_OFFSET+X_DIM/2.0+line[2][i]*X_DIM)*scale),
(int)Math.round((Y_OFFSET+Y_DIM/2.0+line[3][i]*Y_DIM)*scale) );
}
}
/**
* Convert a String to the corresponding Color defaulting to Black
* with an invald input
*/
/*private Color convertColour( String theColour )
{
for( int i=0; i<COLOUR_NAMES.length; i++ )
{
if( COLOUR_NAMES[i].equalsIgnoreCase( theColour ) )
return COLOURS[i];
}
return DEFAULT_COLOUR;
}*/
/** The method that draws everything
*/
public void paintComponent( Graphics g )
{
this.setScale();
this.paintGrid(g);
this.drawLine(g);
this.paintText(g);
}
public void setScale()
{
double width = (0.0+this.getSize().width) / this.originalWidth;
double height = (0.0+this.getSize().height) / this.originalHeight;
this.scale = Math.max( Math.min(width,height), MIN_SCALE );
}
/** Sets the message to be displayed under the board
*/
public void displayMessage(String theMessage)
{
message = theMessage;
this.repaint();
}
/** This method will save the value of the colour of the peg in a specific
* spot. theColour is restricted to
* "yellow", "blue", "cyan", "green", "pink", "white", "red", "orange"
* Otherwise the colour black will be used.
*/
public void putPeg(Color colour, int row, int col)
{
this.grid[col][row] = colour;
this.repaint();
}
/** Same as putPeg above but for 1D boards
*/
public void putPeg(Color colour, int col)
{
this.putPeg(colour, 0, col );
}
/** Remove a peg from the gameboard.
*/
public void removePeg(int row, int col)
{
this.grid[col][row] = null;
repaint();
}
/** Same as removePeg above but for 1D boards
*/
public void removePeg(int col)
{
this.grid[col][0] = null;
repaint();
}
/** Draws a line on the board using the given co-ordinates as endpoints
*/
public void drawLine(double row1, double col1, double row2, double col2)
{
this.line[0][numLines]=col1;
this.line[1][numLines]=row1;
this.line[2][numLines]=col2;
this.line[3][numLines]=row2;
this.numLines++;
repaint();
}
/** Removes one line from a board given the co-ordinates as endpoints
* If there is no such line, nothing happens
* If multiple lines, all copies are removed
*/
public void removeLine(int row1, int col1, int row2, int col2)
{
int curLine = 0;
while (curLine < this.numLines)
{
// Check for either endpoint being specified first in our line table
if ( (line[0][curLine] == col1 && line[1][curLine] == row1 &&
line[2][curLine] == col2 && line[3][curLine] == row2) ||
(line[2][curLine] == col1 && line[3][curLine] == row1 &&
line[0][curLine] == col2 && line[1][curLine] == row2) )
{
// found a matching line: overwrite with the last one
numLines--;
line[0][curLine] = line[0][numLines];
line[1][curLine] = line[1][numLines];
line[2][curLine] = line[2][numLines];
line[3][curLine] = line[3][numLines];
curLine--; // perhaps the one we copied is also a match
}
curLine++;
}
repaint();
}
/** Waits for user to click somewhere and then returns the click.
*/
public Point getClick()
{
Point returnedClick = null;
synchronized(this) {
lastClick = null;
while (lastClick == null)
{
try {
this.wait();
} catch(Exception e) {
// We'll never call Thread.interrupt(), so just consider
// this an error.
e.printStackTrace();
System.exit(-1) ;
} /* try */
}
int x = (int)Math.floor((lastClick.getY()-X_OFFSET*scale)/X_DIM/scale);
int y = (int)Math.floor((lastClick.getX()-Y_OFFSET*scale)/Y_DIM/scale);
// Put this into a new object to avoid a possible race.
returnedClick = new Point(x,y);
}
return returnedClick;
}
/** Same as getClick above but for 1D boards
*/
public double getPosition()
{
return this.getClick().getY();
}
public int getColumns()
{
return this.columns;
}
public int getRows()
{
return this.rows;
}
}
You're shooting yourself in the foot with that thread code -- you're calling run() not start() on it
SYNC_BOARD.run();
This will run on the Swing event thread and risks completely freezing your GUI.
As a general rule, you should almost never extend Thread but rather implement Runnable, but regardless, don't use that Thread code -- Instead use a Swing Timer since your code has no breaks in it, no Thread.sleeps and it will make your CPU awfully busy, and the Swing Timer will help make sure that your code obeys Swing threading rules.
Also your MoveAction is wrong. Most of that code should go in the actionPerformed method. The constructor should just set the direction field and that's it.
Something like:
#SuppressWarnings("serial")
public class MoveAction extends AbstractAction {
Direction direction;
public MoveAction(Direction direction) {
// this is the only code the constructor should have!
this.direction = direction;
}
#Override
public void actionPerformed(ActionEvent e) {
// use direction to help make move in here
}
}
Understand that this is likely causing some major problems, since the constructor is called on program creation (hence your key bindings "work" when the program starts), but it's the actionPerformed that actually gets called when the right key is pressed.

Please Help:Grid of JButtons in a JPanel shows one JButton instead of 400 when GridLayout(20,20) is used

Thank you for trying to help me.
I want to create a grid of 20*20 squares.It is for my A-Star Algorithm Demo.
For experiment purpose I wrote the following code:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class Node extends JButton {
Node(){
super();
setSize(new Dimension(20,20));
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0,0,getHeight(),getWidth());
}
}
public class Map
{
static final int n = 20;
JPanel p;
public JPanel init() {
p=new JPanel();
p.setLayout(new GridLayout(n, n));
p.setBackground(Color.black);
p.setFont(new Font("SansSerif", Font.BOLD, 24));
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
p.add(new Node());
}
}
return p;
}
}
public class Display extends JApplet{
public void init(){
Map m=new Map();
add(m.init());
}
}`
I got the following output:
Please load the code & check.I cannot post image since I lack 10 reputation
However,when I am trying to add the experiment code with my original code for the demo
it is not showing the desired output.My original code is as follows:
import java.util.ArrayList;
import javax.swing.*;
import java.awt.*;
public class Node extends JButton implements Comparable<Node> {
/* Nodes that this is connected to */
private Node north;
private Node east;
private Node south;
private Node west;
private ArrayList<Node> neighbourList;
private boolean visited;
private float g;
private float h;
private Node parent;
private int x;
private int y;
private boolean isObstacle;
private boolean isStart;
private boolean isGoal;
Node(int x, int y) {
super();
neighbourList = new ArrayList<Node>();
this.x = x;
this.y = y;
this.visited = false;
this.g = Integer.MAX_VALUE;
this.isObstacle = false;
this.isStart = false;
this.isGoal = false;
}
public void setNorth(Node north) {
//replace the old Node with the new one in the neighbourList
if (neighbourList.contains(this.north))
neighbourList.remove(this.north);
neighbourList.add(north);
//set the new Node
this.north = north;
}
public void setEast(Node east) {
//replace the old Node with the new one in the neighbourList
if (neighbourList.contains(this.east))
neighbourList.remove(this.east);
neighbourList.add(east);
//set the new Node
this.east = east;
}
public void setSouth(Node south) {
//replace the old Node with the new one in the neighbourList
if (neighbourList.contains(this.south))
neighbourList.remove(this.south);
neighbourList.add(south);
//set the new Node
this.south = south;
}
public void setWest(Node west) {
//replace the old Node with the new one in the neighbourList
if (neighbourList.contains(this.west))
neighbourList.remove(this.west);
neighbourList.add(west);
//set the new Node
this.west = west;
}
public ArrayList<Node> getneighbourList() {
return neighbourList;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
public float getG() {
return g;
}
public void setG(float f) {
this.g = f;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public float getH() {
return h;
}
public void setH(float h) {
this.h = h;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public boolean isObstacle() {
return isObstacle;
}
public void setObstacle(boolean isObstacle) {
this.isObstacle = isObstacle;
}
public boolean isStart() {
return isStart;
}
public void setStart(boolean isStart) {
this.isStart = isStart;
}
public boolean isGoal() {
return isGoal;
}
public void setGoal(boolean isGoal) {
this.isGoal = isGoal;
}
public boolean equals(Node node) {
return (node.x == x) && (node.y == y);
}
public int compareTo(Node otherNode) {
float thisTotalDistanceFromGoal = h + g;
float otherTotalDistanceFromGoal = otherNode.getH() + otherNode.getG();
if (thisTotalDistanceFromGoal < otherTotalDistanceFromGoal)
return -1;
else if (thisTotalDistanceFromGoal > otherTotalDistanceFromGoal)
return 1;
else
return 0;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0,0,getHeight()-1,getWidth()-1);
}
}
public class Map {
private int mapWidth;
private int mapHeight;
private ArrayList<ArrayList<Node>> map;
private int startLocationX = 0;
private int startLocationY = 0;
private int goalLocationX = 0;
private int goalLocationY = 0;
private int[][] obstacleMap;
private JPanel p;
private Logger log = new Logger();
Image buffer;
Map(int mapWidth, int mapHeight, int[][] obstacleMap) {
this.mapWidth = mapWidth;
this.mapHeight = mapHeight;
this.obstacleMap = obstacleMap;
createMap();
log.addToLog("\tMap Created");
registerEdges();
log.addToLog("\tMap Node edges registered");
}
private void createMap() {
Node node;
map = new ArrayList<ArrayList<Node>>();
for (int x=0; x<mapWidth; x++) {
map.add(new ArrayList<Node>());
for (int y=0; y<mapHeight; y++) {
node = new Node(x,y);
if (obstacleMap[x][y] == 1)
node.setObstacle(true);
map.get(x).add(node);
}
}
}
/**
* Registers the nodes edges (connections to its neighbours).
*/
private void registerEdges() {
for ( int x = 0; x < mapWidth-1; x++ ) {
for ( int y = 0; y < mapHeight-1; y++ ) {
Node node = map.get(x).get(y);
if (!node.isObstacle()){
if (!(y==0))
node.setNorth(map.get(x).get(y-1));
if (!(x==mapWidth))
node.setEast(map.get(x+1).get(y));
if (!(y==mapHeight))
node.setSouth(map.get(x).get(y+1));
if (!(x==0))
node.setWest(map.get(x-1).get(y));
}
}
}
}
public ArrayList<ArrayList<Node>> getNodes() {
return map;
}
public void setObstacle(int x, int y, boolean isObstacle) {
map.get(x).get(y).setObstacle(isObstacle);
}
public Node getNode(int x, int y) {
return map.get(x).get(y);
}
public void setStartLocation(Node start) {
map.get(startLocationX).get(startLocationY).setStart(false);
map.get(start.getX()).get(start.getY()).setStart(true);
startLocationX = start.getX();
startLocationY = start.getY();
}
public void setStartLocation(int x, int y) {
map.get(startLocationX).get(startLocationY).setStart(false);
map.get(x).get(y).setStart(true);
startLocationX = x;
startLocationY = y;
}
public void setGoalLocation(Node goal) {
map.get(goalLocationX).get(goalLocationY).setGoal(false);
map.get(goal.getX()).get(goal.getY()).setGoal(true);
goalLocationX = goal.getX();
goalLocationY = goal.getY();
}
public void setGoalLocation(int x, int y) {
map.get(goalLocationX).get(goalLocationY).setGoal(false);
map.get(x).get(y).setGoal(true);
goalLocationX = x;
goalLocationY = y;
}
public int getStartLocationX() {
return startLocationX;
}
public int getStartLocationY() {
return startLocationY;
}
public Node getStartNode() {
return map.get(startLocationX).get(startLocationY);
}
public int getGoalLocationX() {
return goalLocationX;
}
public int getGoalLocationY() {
return goalLocationY;
}
public Node getGoalLocation() {
return map.get(goalLocationX).get(goalLocationY);
}
public float getDistanceBetween(Node node1, Node node2) {
//if the nodes are on top or next to each other, return 1
if (node1.getX() == node2.getX() || node1.getY() == node2.getY()){
return 1;
} else { //if they are diagonal to each other return diagonal distance: sqrt(1^2+1^2)
return (float) 1.4;
}
}
public int getMapWidth() {
return mapWidth;
}
public int getMapHeight() {
return mapHeight;
}
public JPanel init(){
int n=20;
p=new JPanel();
p.setLayout(new GridLayout(n, n));
p.setSize(400,400);
p.setFont(new Font("SansSerif", Font.BOLD, 24));
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
p.add(map.get(j).get(i));
}
}
return p;
}
public void clear() {
startLocationX = 0;
startLocationY = 0;
goalLocationX = 0;
goalLocationY = 0;
createMap();
registerEdges();
}
}
public class Display extends JApplet
{
private static int[][] M = {{0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0},
{0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0},
{0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,0},
{0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,0,0},
{1,1,1,1,1,1,1,1,0,0,0,0,1,1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0},
{0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0},
{0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
public void init()
{
JRootPane rootPane = this.getRootPane();
rootPane.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
Map m=new Map(20,20,M);
add(m.init());
}
}
This is the output that I got from the above code:
Please load the code & check.I cannot post image since I lack 10 reputation
Within the Node class, the methods getParent, getX, and getY are overriding methods in the super class JButton. When the layout manager calls getX and getY your methods get called which confuses the layout manager. Rename your three methods to anything else, for example nodeGetParent, nodeGetX, and nodeGetY.
The lesson to learn here is that you must be careful when extending a class that you don't accidentally override the super class' methods.

What's wrong with my getArea method?

This is a homework problem. There are a few other java files involved. Note that shapes.Rectangle and shapes.Oval contain a getArea method. I'm having a maddening time trying to figure this out any help is appreciated.
package model;
import java.awt.Color;
import java.awt.Container;
import shapes.Line;
import shapes.Oval;
import shapes.Rectangle;
import shapes.Shape;
import shapes.Triangle;
import interfaces.ComparableShape;
import interfaces.Resettable;
public class Model implements Resettable,ComparableShape {
private Container container;
private String message;
private String action = DRAW;
private boolean fill = false;
private String currentShapeType;
private Shape currentShape;
private Color fillColor = Color.gray;
public Color lineColor;
public final static String DRAW = "Draw";
public final static String MOVE = "Move";
public final static String REMOVE = "Remove";
public final static String RESIZE = "Resize";
public final static String FILL = "Fill";
public final static String CHANGE = "Change";
public final static String RECTANGLE = "Rectangle";
public final static String OVAL = "Oval";
public final static String LINE = "Line";
public final static String TRIANGLE = "Triangle";
public static String[] selections = {"Rectangle", "Oval", "Line", "Triangle"};
//project 9 begin
public Shape[] myShapes = new Shape[2];
//project 9 stop
public Shape createShape() {
if(currentShapeType == RECTANGLE){
currentShape = new Rectangle(0, 0, 0, 0, lineColor, fillColor, fill);
}
if(currentShapeType == OVAL) {
currentShape = new Oval(0,0,0,0, lineColor, fillColor, fill);
}
if(currentShapeType == LINE) {
currentShape = new Line(0,0,0,0, lineColor, fillColor, fill);
}
if(currentShapeType == TRIANGLE) {
currentShape = new Triangle(0,0,0,0, lineColor, fillColor, fill);
}
//project 9 start
if(myShapes[0] == null) {
myShapes[0]=currentShape;
}
else {
myShapes[1]=currentShape;
}
//project 9 stop
return currentShape;
}
public Shape getCurrentShape() {
return currentShape;
}
//project 9 begin
public Shape[] getMyShapearray() {
return myShapes;
}
//project 9 end
public String getCurrentShapeType(){
return currentShapeType;
}
public void setCurrentShapeType(String shapeType){
currentShapeType = shapeType;
}
public Model(Container container) {
this.container = container;
}
public void repaint() {
container.repaint();
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public boolean isFill() {
return fill;
}
public void setFill(boolean fill) {
this.fill = fill;
}
public void setMessage(String msg) {
this.message = msg;
}
public String getMessage() {
return this.message;
}
public Color getLineColor() {
return this.lineColor;
}
public void setLineColor(Color c) {
this.lineColor = c;
}
public String toString() {
return "Model:\n\tAction: " + action + "\n\tFill: " + fill + "\n\tArea: " ;
}
public void resetComponents() {
action = DRAW;
currentShape = null;
myShapes = null;
if (container instanceof Resettable) {
((Resettable) container).resetComponents();
}
}
//Add a method to your model called compareShapes(),
//which will return either 0, 1, or 2--1 if the area of the first Shape is bigger than the second,
//2 if it is smaller, and 0 if the two Shapes are the same size.
//Create an interface named ComparableShape that will be used by the shape objects.
//The interface should require implementing classes to have a
//method getArea() capable of returning the area of the object. Obviously, only closed shapes can do this.
//The instanceof operator will be handy here.
public int getArea() {
return getWidth()*getHeight();
}
private int getHeight() {
///what goes here?!
return 0;
}
private int getWidth() {
//what goes here?!
return 0;
}
public int compareShapes(ComparableShape b) {
ComparableShape oneToCompare = null;
if (b instanceof ComparableShape) {
oneToCompare = (ComparableShape)b;
if (getArea() < oneToCompare.getArea()) return 2; // this one is smaller
if (getArea() > oneToCompare.getArea()) return 1; // this one is larger
return 0;
}
return 0;
}
}
Your getArea() should have something like this:-
If currentShapeType is not a LINE (since a line is not closed shape), then calculate and return area of currentShape based on the currentShapeType.
The area of a rectangle is length*width. It's different for the other shapes though. So for a rectangle you need access to its length and width. For a circle you would need its radius. The area of a circle is piR^2.
As someone mentioned below, for an ellipse:
The area of an ellipse is pi*a*b, where a and b are half the length of the major and minor axes. The area of a circle could be written as pi*r*r or pi*r^2 since a and b would be equal.

Categories

Resources