So i was wondering I'm new to java but I know my way around it but I wanted to make a 2d tile game.
Now I heard that you can do this with a 2d Array to make the map.
But how do you make the map appear on the screen, JFrame, as pictures?
So an example of the array/map here:
1111111111
1011011001
1001100011
0000100011
0000000000
2222222222
0 = blueSky.png
1 = cloud.png
2 = grass.png
Thanks!
EDIT 2
So i have now this:
import javax.swing.*;
import java.awt.*;
public class Game extends JFrame {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
ImageIcon sky = new ImageIcon ("/Users/pro/Desktop/sky.png");
JPanel grid = new JPanel();
grid.setLayout(new GridLayout(25, 25));
for (int i = 0; i < 25; i++) {
for (int n = 0; n < 25; n++) {
grid.add(new JLabel(sky));
}
}
JFrame frame = new JFrame("Map");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setPreferredSize(new Dimension(640, 400));
frame.add(grid);
frame.pack();
frame.setVisible(true);
}
}
this prints some tiles with the sky picture but how do i make the bottom row an other picture?
I'd consider the 2D array as the non-GUI model, that the data itself would likely be held in some data file, perhaps a text file, that there would be methods for reading the data in to be held by a 2D array of perhaps ints, perhaps custom Cell classes (again, still all non-GUI). Then the GUI would have to interpret the model and display the data in some logical way. This could perhaps be done by creating a 2D grid of JLabels held by a JPAnel that uses GridLayout, and then use ImageIcons to hold the images, and set the icon of each JLabel based on the state of the model.
Edit 1
So possible classes used include:
TileType: an enum that associates the tile concept with the numbers held by the data file
TileCell: non-GUI class, holds a TileType field, also may hold a List of items that can be found on the cell (if the game needs this). May have information about its neighbors.
TileCellGrid: non-GUI class holding a 2D grid of TileCells.
GridDataIO: utility class to read in and write out grid data to a file.
GameGrid: GUI class that would hold a GridLayout using JPanel that holds JLabels whose ImageIcons display the images you list in your OP.
Edit 2
regarding your question:
Alright how can i set the right picture for everyLabel ?
I would use an observer/observable pattern and add a listener to the model. Whenever the model changes it should thus notify the GUI or view. Then the view would request the data array, would iterate through it and would change the image icons that need changing as it loops through the array.
I suggest you use JLabels with icons and lay them out using GridLayout.
Related question / answer with sample code and screen shot:
Tiled images in swing
Related
I have a JTable and I want to make a tic tac toe themed table. I have managed to get rid of three borders without really knowing how...
Here's my code:
public class Table extends JPanel {
public static void main( String[] args ) {
JFrame jFrame = new JFrame();
JTable table = new JTable(3, 3);
table.setBounds(90, 20, 200, 200);
for(int i = 0; i < 3; i++) {
table.setRowHeight(i, 67);
}
table.setBackground(Color.black);
table.setGridColor(Color.white);
table.setForeground(Color.white);
// content pane so I can set the background
jFrame.getContentPane().add(table);
jFrame.getContentPane().setBackground(Color.black);
jFrame.setSize(400, 400);
jFrame.setLayout(null);
jFrame.setVisible(true);
}
}
I also have some stuff that initializes the table more like setting values but I don't think that will matter but I can add it if you want. So how could I get the right border of the table to disappear too?
When I compile this code, the top, left and bottom borders are not visible
You can usesetBorder method with a LineBorder in order to fill it:
table.setGridColor(Color.white);
table.setBorder(BorderFactory.createLineBorder(table.getGridColor()));
By the way, setLayout(null) and setBounds is a bad practice that is going to give you hard time in the future (plus it is not user-friendly, since you cannot resize your frame and won't work in different screen sizes). Try to use LayoutManagers and let them do the work for you.
Also, take a look at initial threads. All swing applications should run on their own thread and not in the main thread.
The only way, as far as I know, to put a JButton or a JLabel is via creating the GUI structure through Containers and placing those components on it.
Are there other methods to add components randomly into the frame and resize accordingly ,as can be done in Visual C# for example? What is the method to do it?
Yes.
You could use a null Layout and then place components using setBounds().
For example:
JPanel panel = new JPanel(null);
for (int i = 0; i < 4; i++) {
JButton b = new JButton("JButton-"+i);
b.setBounds(50+i*10, 50+i*10, 100, 100);
panel.add(b);
}
If you want random placing, you could random the first 2 (x,y) values.
You will need to provide on your own valid values to be placed inside the parent container.
I am developing a program that will populate an array with 52 images of cards from a file. I would like to display these images in a gui window. This is for a program that will select five random card images and display them in a gui window. So, right now, i am trying to develop the part of the code which will display images from an array in a window and i am at a loss as to how to display png images in a jframe. This is the code i have so far. I used a system.out.println statement so i know that the array of 52 card images is populating correctly, however, i do not know how to display them properly in a window.
String[] cardsArray = new String[52];
for (int i = 0; i < 52; i++)
{
cardsArray[i] = "C:\\Users\\mike\\Documents\\NetBeansProjects\\card shuffler\\cards\\\"+String.valueOf(i+1)+".png";
}
System.out.println(Arrays.toString(cardsArray));
additional note. I have to use a jframe to display the results in a side by side layout. I thought to use flowLayout to accomplish this, but, i a not sure how to pass in an array of images. I have no problem doing it with a single image from a file. I am using the code below as a guide.
JFrame myJFrame = new JFrame();
// create and assign a FlowLayout for myFrame
myJFrame.setLayout(new FlowLayout());
// Create a label with an image icon
JLabel jlCSCI = new JLabel(new ImageIcon("CSCI.jpg"));
// add the Label to the frame
myJFrame.add(jlCSCI); // Add thelabel to MyGridLayout
// set the title, size, location and exit behavior for the frame
myJFrame.setTitle("ImageIcon Demo");
myJFrame.setSize(240, 200);
myJFrame.setLocation(200, 100);
myJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// make the frame visible (activate the GUI frame)
myJFrame.setVisible(true);
I am not sure how to develop the statement that would utilize an array that i created within the program.
Maybe like this?
for (String imgName : cardsArray)
{
myJFrame.add(new JLabel(new ImageIcon(imgName)));
}
Hope this helps.
EDIT:
I simply added a JLabel with an Icon to the frame. The ImageIcon class is just an implementation of the Icon interface and it creates an icon by reading an image from file. Creating a JLabel with an Icon will display the icon instead of the text. You can also combine the text and the icon. For more info, check the documentation.
The scenario: I have a UI that contains a JPanel (call it topGrid) with a grid layout in a JFrame at the top level. Within topGrid, I have placed another JPanel (midGrid) with grid layout. Inside midGrid, is another JPanel (bottomGrid) that has a JLabel that I populate with images depending on an array and what their instance is within that array.
The goal: I would like the topGrid to center its view on a specific object found in bottomGrid. (Picture a game that as the player icon moves, the game's grid moves to center on that icon and also when the game is started it is already centered for the user.)
I've considered getting the Point from bottomGrid and trying to pass it over to topGrid but doesn't seem to pull the correct information. The only way i know to find where the player is, is to iterate through all the components and check instances. this would have to be done once for the topGrid and again for midGrid to find the player at bottomGrid. then pass the Point data. Then use setLocation() on the appropriate JPanel minus the distance from the center.
Has anyone else tried this and have a more effective or elegant way to go about it? What other options could I explore?
Thanks for any feedback.
Creating the grid within topGrid's JPanel:
public void createTopGrid()
{
int rows = galaxy.getNumRows();
int columns = galaxy.getNumColumns();
pnlGrid.removeAll();
pnlGrid.setLayout(new GridLayout(rows, columns));
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
Position pos = new Position(galaxy, row, col);
Sector sector = galaxy.getSector(pos);
GalaxySector sectorUI = new GalaxySector(sector);
pnlGrid.add(sectorUI);
}
}
}
Creating the grid within midGrid's JPanel:
public void createOccupantIcons()
{
pnlGridOccupants.removeAll();
Occupant[] occs = sector.getOccupantsAsArray();
for ( Occupant occ : occs )
{
GalaxyOccupant occupant = new GalaxyOccupant(occ, sector);
pnlGridOccupants.add(occupant);
}
}
The Image icons for each occupant in the midGrid are pulled from an IconRep String in the model in the bottomGrid class' JPanel and added into a JLabel as needed in FlowLayout.
For visual reference:
Where green square is topGrid JPanel, red squares are midGrid JPanel, and the black square is the bottomGrid JPanel with the white circle for the player image inside a JLabel. The blue circle represents a viewport the user will see the game through and is where I want the player icon to be centered to. Currently the user can move the grid's using very inelegant buttons in the area around the viewport. That might be sufficient but at the start of the game the player has to move the grid around until they can locate their icon.
You might also look at JScrollNavigator, examined here. It would allow you to navigate on a thumbnail image of your entire world, seen at full size in an adjacent scroll pane.
Off the top of my head, I would store all the references you want to in some kind of model.
You could use this model to update the views based on selection requirements.
This allows the you to centralise the logic for finding and updating the elements without knowing or caring out the other UI elements
(second question in a few hours)
Kay so I'm making a chess variant in java, I have my console program working how I want it but now I'm trying to convert it to a swing GUI while STILL keeping the console things intact. So up to now I have my array of squares with pieces in them for the console, and a 2-dimensional array of JPanels with pieces in them for the GUI. I haven't implemented moving pieces in the GUI yet so I'm still doing it from the console but the actual GUI doesn't update after I've moved a piece...even though it does on the console (sorry if this is confusing).
The GUI consists of a constructor which calls some methods drawBoard() and drawSidebar() and sets sizes, titles etcetc...so this is what the main method looks like:
public static void main(String args[]) {
ChessGUI GUI = new ChessGUI();
Board console = new Board();
do {
console.printBoard();
console.getScore();
console.getMove();
GUI.boardPanel.revalidate();
GUI.sidePanel.revalidate();
GUI.repaint();
} while (true);
}
and drawBoard() incase it makes any difference:
public void drawBoard() {
LayoutManager layout = new GridLayout(NUMBER_OF_ROWS, NUMBER_OF_COLS);
boardPanel.setLayout(layout);
boardPanel.setPreferredSize(new Dimension(200, 450));
chessBoard = new JPanel[NUMBER_OF_ROWS][NUMBER_OF_COLS];
for (int i = 0; i < NUMBER_OF_ROWS; i++) {
for (int j = 0; j < NUMBER_OF_COLS; j++) {
chessBoard[i][j] = new JPanel();
chessBoard[i][j].setBackground(getColor(i,j));
int index = i * 4 + j;
if (!(boardArray.chessBoard[index].square.isEmpty())) {
Piece piece = (Piece) boardArray.chessBoard[index].square.firstElement();
chessBoard[i][j].add(new JLabel(piece.toString()));
}
boardPanel.add(chessBoard[i][j]);
}
}
}
the repaint and revalidate methods don't seem to be calling at all, even though the console is being updated :(
I don't really understand what you are doing. But it doesn't make sense to recreate the entire board panel every time a move is made. All Swing components can only have a single parent, to the easier solution is to just move the piece from one panel to the other. So the code would be something like:
previousPanel.remove( piece );
currentPanel.add( piece );
previousPanel.revalidate();
previousPanel.repaint();
currentPanel.revalidate();
It looks like you're never actually removing anything from 'boardPanel,' even though you are resetting its LayoutManager.
A safer approach might be to remove 'boardPanel' from its container, then create a new instance for 'boardPanel,' add that to the container, then add the other JPanel pieces to this new 'boardPanel.' Effectively, you would be reconstructing the entire JPanel hierarchy after every move.
As you've noticed, Swing can be quite finicky once you start trying to add/move/remove components after they've been added to containers. For games, often the best approach would be to have 1 JComponent/Component and use Java2D methods to draw on top of it. Swing is typically only used for forms-based applications.
Changing the layout doesn't do anything.
You need to call boardPanel.removeChildren()
However, this is going to be extremely slow.
Really, what you should be doing is have your own JPanel, overwrite paintComponent() and draw the images into the appropriate dimensions using Java Graphics.