I'm relatively new to java and have been working on a simple Blackjack program using Java Swing, but I'm having trouble getting setAlignmentX to work in OverlayLayout.
Basically the idea is to have two cards generate on the left side of the play area (the red rectangle), then add another card (on top and to the right of the previous cards) when the player clicks "Draw".
Picture Link because I'm too new to Stack Overflow
I try to do this by adding a card (JLabel with image icon) with a .setAlignmentX that is greater than the previous card.
However, there are two problems. The first is that when a single card is generated, it is able to stick all the way to the left of the rectangle. However, when two cards are generated, they both generate further to the right, away from the side.
The second is that the new card is adding itself below, and to the left, of the previous cards (instead of above and to the right). Furthermore, as per the two cards, the whole chunk is moving rightwards on every draw.
Another Picture Link
Here is the relevant code:
ArrayList<JLabel> tuCardsPanelList = new ArrayList<>();
...
for(int i = 0; i < 9; i++){
tuCardsPanelList.add(new JLabel());
}
tuCardsPanel = new JPanel(new BorderLayout());
tuCardsPanel.setBackground(new Color(130, 30, 40));
tuCardsPanel.setBorder(new LineBorder(Color.yellow));
tuCardsPanel.setPreferredSize(new Dimension(400, 200));
tuCardsPanel.setLayout(new OverlayLayout(tuCardsPanel));
...
//display first two cards
ImageIcon image = new ImageIcon(getClass().getResource(activePlayer.hand.get(0).imageLocation));
tuCardsPanelList.get(0).setIcon(new ImageIcon(image.getImage().getScaledInstance(121, 185, Image.SCALE_SMOOTH)));
tuCardsPanelList.get(0).setPreferredSize(new Dimension(121, 185));
tuCardsPanelList.get(0).setAlignmentX(0.0f);//SETALIGNMENTX HERE
tuCardsPanelList.get(0).setAlignmentY(0.5f);
ImageIcon image1 = new ImageIcon(getClass().getResource(activePlayer.hand.get(1).imageLocation));
tuCardsPanelList.get(1).setIcon(new ImageIcon(image1.getImage().getScaledInstance(121, 185, Image.SCALE_SMOOTH)));
tuCardsPanelList.get(1).setPreferredSize(new Dimension(121, 185));
tuCardsPanelList.get(1).setAlignmentX(0.16f); //SETALIGNMENTX HERE
tuCardsPanelList.get(1).setAlignmentY(0.5f);
tuCardsPanel.add(tuCardsPanelList.get(0));
tuCardsPanel.add(tuCardsPanelList.get(1));
...
//when "Draw" button is pressed
activePlayer.drawFrom(deck);
tuLabel3.setText("Total: " + activePlayer.valueOfHand());
int currentNewCard = activePlayer.hand.size() - 1;
ImageIcon image = new ImageIcon(getClass().getResource(activePlayer.hand.get(currentNewCard).imageLocation));
tuCardsPanelList.get(currentNewCard).setIcon(new ImageIcon(image.getImage().getScaledInstance(121, 185, Image.SCALE_SMOOTH)));
tuCardsPanelList.get(currentNewCard).setPreferredSize(new Dimension(121, 185));
tuCardsPanelList.get(currentNewCard).setAlignmentY(0.5f);
tuCardsPanelList.get(currentNewCard).setAlignmentX(0.32f); //SETALIGNMENTX HERE
If it helps, one really weird thing I found was that the second card (with .setAlignmentX(0.16f)) is actually on the left of the first card (which has a .setAlignmentX(0f)!)
I think they are all symptoms of a property of .setAlignmentX or OverlayLayout that I'm misusing, but I just can't figure it out. Google didn't help either.
Any help will be greatly appreciated! :)
Related
I'm working on a GUI for a Tic Tac Toe project, in which I want to get an image (the player's move) to show up when clicking the corresponding area. However, I can't figure out how to display a JLabel (the move) on top of another JLabel (the background).
I have searched and tried to use layeredpanes, but it just fails to show the entire frame when I run it. I am new to GUI, so I am not quite sure if I implemented it correctly.
layer = new JLayeredPane();
//set up the board as background
String path = "sampleUrl";
URL url = new URL(path);
BufferedImage image = ImageIO.read(url);
bg4 = new JLabel(new ImageIcon(image));
layer.add(bg4, new Integer(-1));
frame.add(layer);
frame.pack();
frame.addMouseListener(new MouseListener4());
String xPath = "sampleUrl";
URL xUrl = new URL(xPath);
BufferedImage x = ImageIO.read(xUrl);
icon = new JLabel(new ImageIcon(x));
layer.add(icon);
It just shows up a window with minimum width and height, without displaying the background. Is there something wrong with this code, or any other ways for me to put a JLabel on top of another JLabel?
You can add one label object into another, as JLabel is a container. Try something like this.
JLabel parentLabel = new JLabel("Parent");
JLabel childLabel = new JLabel("Child");
parentLabel.add(childLabel );
I highly recommend you to read about javafx if you are new in GUI.you can merge nodes in any way you need.you can put labels on each other using stackpane,and display them top and down of each other using gridpane very easily.
more information on:
https://docs.oracle.com/javafx/2/
this is a problem that I've been really struggling with
I need to create a game for some University coursework. The game is basically a 4x4 grid. When i click a button, the player should move randomly within 1 square of it's location.
There's enemy spaceships that are generated randomly over the grid, and if the player lands on the spaceship, it destroys it. if there's two enemy ships on the same sqaure and the player lands on that square, the player is destroyed.
I've created a GIU using gridlayout and the button that I need to move the player, but I'm having problems trying to figure out how to actually use the grid. I've created an element class to create objects for the grid (ie, a list of enemy ships), but I don't know how to use this class with my gridlayout. I know I also have to redraw the grid after each move to reflect the changes, but I don't know if I would need to create a custom redraw method for this.
Any push in the correct direction so I can get my program actually doing something would be really helpful.
Some time ago I created a card game that also operated based on a GridLayout. Below is some of the code that was used to drive major events:
CardPanel extends JPanel {
public CardPanel() {
setLayout(gridLayout);
placeCards(N);
chatBoxText = new JTextArea(5, 30);
}
public void placeCards(int numCards) {
for (int i = 0; i < numCards; i++) {
Card card = deck.distributeCard();
String cardImageName = card.getImageName();
JLabel jLabel = makeImage(cardImageName);
cardSet.add(new GraphicCard(card, jLabel));
add(jLabel);
jLabel.addMouseListener(this);
}
if (GameLogic.noSetsOnBoard(cardSet)) {
gridLayout.setRows(gridLayout.getRows() + 1);
placeCards(3);
}
}
public void updateCard(Integer location) {
Card card = deck.distributeCard();
String cardImageName = card.getImageName();
JLabel jLabel = makeImage(cardImageName);
cardSet.set(location, new GraphicCard(card, jLabel));
jLabel.addMouseListener(this);
}
}
The CardPanel here is an object that represents the GridLayout (you see the constructor) as well as some of those helper methods.
Further on, on particular actions, I have the following code:
cardPanel.removeAll();
// Some other logic here
for (GraphicCard card: cardSet) {
cardPanel.add(card.getJLabel());
}
cardPanel.revalidate();
cardPanel.repaint();
In short, yes, it is custom, but it is not difficult. There are better ways to do it than the above such that you do not need to empty the entire panel in order to refresh it, the logic I have omitted above merited this particular solution.
The approach I used kept track of a CardPanel object which was an abstraction that contained not only the information that each box represented (in my case a card with some values), but also the graphic element to be rendered.
This was some time ago, so I don't recall the exact details but hopefully this is helpful.
so I'm trying to make a battleship game, and I implemented a 10x10 grid containing gifs of some pixelated water. Now, what I'm trying to do is offset the grid one cell down and to the right so I can place the numbers and letters along the side and top like in a real battleship game. The problem is that when I try to offset it, it removes either the entire right side column of cells and reduces the window accordingly, and visa versa with the bottom. Here's my code:
EDIT 3: I have replaced the gif so that it can be used by everyone, simply copy the code and run it.
public class ButtonGrid {
JFrame frame=new JFrame(); //creates frame
JLabel[][] grid; //names the grid of buttons
public ButtonGrid(int width, int length) throws MalformedURLException{
URL urlPic = new URL("http://i47.tinypic.com/14wswi9.gif");
ImageIcon urlPicture = new ImageIcon(urlPic);
frame.setLayout(new GridLayout(width,length)); //set layout
grid=new JLabel[width][length]; //allocate the size of grid
for(int y=0; y<length; y++){
for(int x=0; x<width; x++){
grid[x][y]= new JLabel(urlPicture); //creates new button
frame.add(grid[x][y]); //adds button to grid
}
}
grid[1][1].setForeground(Color.red);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(270, 400);
frame.pack(); //sets appropriate size for frame
frame.setVisible(true); //makes frame visible
}
public static void main(String[] args) throws MalformedURLException{
new ButtonGrid(11,11);//makes new ButtonGrid with 2 parameters
}
}
EDIT: It seems that I may not have made this really clear. On a real battleship game, there is a row of numbers and a column of letters. The rest of the grid is simply water with the ships inside of it. With the code I have provided, the entire grid is water, and I want to offset to place a row of numbers and a column of letters just like in a real battleship board. If I try to place anything on top of the current grid, it doesn't change anything. I tried to change the foreground color and even changed the picture of one of the cells to something different, and the grid still remained the same; a 11 x 11 grid of animated pixel water.
Second EDIT: I have rewritten my code to draw a grid on top and on the left of the window, but now I am getting a null pointer exception. I don't exactly know what is wrong with this:
EDIT FOUR: Removed un-needed code.
One way to get what you need is to use the same technique I used in the Chess GUI with the columns (A-H) and rows (8-1) as seen below. Have a look over the code and see if you can implement that in your own code.
Failing that, post an MCVE (Minimal Complete and Verifiable Example) of your own (as opposed to uncompilable code snippets). One way to get image(s) for an example is to hot-link to the images seen in this answer (again as the linked code does).
Not sure I really understand the question, but I would think you should be using a GridLayout if you want to display components in a Grid.
//frame.setLayout(new FlowLayout());
frame.setLayout( new GridLayout(0, 11) );
Or maybe you would do something like this
JPanel topPanel = new JPanel( new GridLayout(1, 11) );
// use a loop to create 11 labels for the letters and add the labels to the panel
JPanel leftPanel = new JPanel( new GridLayout(10, 1) )
// use a loop to create 10 labels for the letters and and the labels to the panel
Use your current loop to create your "gamePanel" with the 10 x 10 grid of labels.
Then you add the 3 panels to the frame using:
frame.add(topPanel, BorderLayout.NORTH);
frame.add(leftPanel, BorderLayout.WEST);
frame.add(gamePanel, BorderLayout.CENTER);
I tried looking but no questions were helpful.
Here's my code to begin with:
Player player = new Player();
Block1 block1 = new Block1();
JFrame ow = new JFrame();
ow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ow.setSize(500,500);
ow.setTitle("My Game");
ow.setVisible(true);
ow.setLocation(400, 100);
ow.add(block1);
ow.add(player);
but it will only add the last one, someone said (when I searched old questions) that it erases the previous one because they are both in the same location.
So I modified it this way:
JPanel jp = new JPanel();
jp.setSize(500, 500);
Player player = new Player();
Block1 block1 = new Block1();
JFrame ow = new JFrame();
jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS));
jp.add(player);
jp.add(block1);
ow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ow.setSize(500,500);
ow.setTitle("My Game");
ow.setVisible(true);
ow.setLocation(400, 100);
ow.add(jp);
It did work, putting them both visible but... it sort of made two square panels so I can't go near block 1 with my player.
Any help?
JFrame by default uses BorderLayout. If you don't specify where you will put the component, it's going to be put in BorderLayout.CENTER. You can't put 2 or more components in the same position. To prevent this undesired behaviour you have to set different constraints.
For example:
jframe.add(someComponent, BorderLayout.LINE_END);//constraint indicating position
Read more in tutorials : How to use BorderLayout.
If this layout don't fit what you need, try to use another LayoutManager or mix them.
Take a look at A Visual Guide to LayoutManagers
I have a JPanel in which I need to add bunch of JLabels at a required coordinates. These JLabels will have key Listeners assigned to them that will determine new position using arrow keys.
To be more specific I know how to do it when there is only one JLabel but whenever I put a more of them the things mess up. while I use arrow key the first JLabel moves but all other JLabel disappears.
Can Anyone give me some hints to write a method to put a JLabel in a specific coordinate and also move them using arrow key later without making other JLabels dissapear?
Huge Thanks in Advance
You can try using JDesktopPane or JLayeredPane, it works the same as the JPanels, but you won't use layouts, with these you will use Bounds, you always have to set the bound of a jlabel like this.
JLabel label = new JLabel("Hello");
label.setBounds(0, 0, 100, 20);
//label.setBounds(x, y, width, height);
pane.add(label)
if you need to move that label, then you can use something like
int xx = label.getBounds().getX();
int yy = label.getBounds().getY();
int ww = label.getBounds().getWidth();
int hh = label.getBounds().getHeight();
//to the right 10 units
xx+=10;
label.setBounds( xx, yy, ww, hh );
I assume you are using repaint() to update the UI. Btw, upon which component you are calling repaint()?