I have a JFrame with a JLabel on top called "coloredLabel", an instance of the class it's in is running on both of them. a random amount of objects move around on the frame and label and don't directly interact with them.
The only problem is that there is a bit of the frame visable above the label, what I want is that the label fully alligns with the frame, without pasting over the objects (which are painted in with an override paint method and mentioned as "game.newBall" and "game.moveBall". "test" is the name of the class.
Here is how my main thread looks, the frame and the label are declared within it:
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("Bounce 2.0");
JLabel coloredLabel = new JLabel("");
test game = new test();
frame.add(game);
frame.setSize(300, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
coloredLabel.setOpaque(true);
coloredLabel.setBackground(game.backgroundColor);
coloredLabel.setPreferredSize(new Dimension(1000000,1000000));
frame.getContentPane().add(coloredLabel,BorderLayout.LINE_START);
game.add(coloredLabel);
for(int a = randInt(0,9); a<10; a++)
game.newBall(randInt(0,300),randInt(0,400));
while (true) {
double height = frame.getContentPane().getSize().getHeight();
double width = frame.getContentPane().getSize().getWidth();
int n = 0;
while(game.exists(n)==true){
game.moveBall(n,width,height);
n++;
}
game.repaint();
Thread.sleep(10);
}
}
So my question is:
How do I allign the JLabel with the JFrame? so there is no space in between the JLabel and the frame.
I searched for this on this site, but couldn't find the same problem or something similar enough so I could fix this.
solved - game.setBackground(...);
The only problem is that there is a bit of the frame visable above the label,
game.add(coloredLabel);
I'm guessing "game" is a JPanel. By default a JPanel uses a FlowLayout and by default the FlowLayout has horizontal and vertical gaps of 5 pixels.
Get rid of the gap in the FlowLayout. Read the API for the constructors/methods of the FlowLayout to customize its behaviour.
But of course the bigger issue is the design of your app. I don't understand your point of using the label and attempting to take up all the space of the frame. Just set the background of the game panel by using:
game.setBackground(...);
Also class names should:
start with an upper case character and
be descriptive.
"test" is neither.
Related
I managed to fix it but I don't understand why the same code results in different results. Some classmates have had the same problem.
The issue is that it I use miVentana.setVisible(true); before chicha(); the elements inside the JPanel will show when executing but if I run it again sometimes they won't ve visible until I resize the window, a few times not even the JPanel background color was visible. Just clicking the "Run" bottom on the IDE without changing anything else.
I just tried it 10 consecutive times and the elements were only visible on the 4th attempt.
Could this come from some memory garbage remaining from previous executions of the code?
I'm using Eclipse Version: Photon Release (4.8.0).
This is the code with the weird behaviour:
public class Ej10 extends JFrame {
public Ej10() {
setLayout(null);
}
static Ej10 miVentana = new Ej10();
public static void main(String[] args) {
miVentana.setTitle("Ejercicio10");
miVentana.setBounds(20, 20, 500, 600);
miVentana.setLocationRelativeTo(null);
miVentana.setVisible(true);
chicha();
//miVentana.setVisible(true);
}
static void chicha() {
JPanel miPanel = new JPanel();
miPanel.setLayout(new BoxLayout(miPanel, BoxLayout.PAGE_AXIS));
miPanel.setBounds(20, 20, 350, 450);
miPanel.setBackground(Color.CYAN);
JLabel lUsuario = new JLabel("Usuario:");
lUsuario.setVisible(true);
JTextField campoUsuario = new JTextField();
JLabel lPwd = new JLabel("ContraseƱa:");
JPasswordField campoPwd = new JPasswordField();
JButton bAcceso = new JButton("Acceder");
miPanel.add(lUsuario);
miPanel.add(campoUsuario);
miPanel.add(lPwd);
miPanel.add(campoPwd);
miPanel.add(bAcceso);
miPanel.setVisible(true);
miVentana.add(miPanel);
}
}
Components need to be added to the frame BEFORE the frame is made visible.
One of the functions of the setVisible() method is to invoke the layout manager. Otherwise components have a size() of (0, 0) so there is nothing to paint.
Also, all GUI components should be created on the Event Dispatch Thread (EDT), otherwise you can have random results. Read the section from the Swing tutorial on Concurrency for more information.
Take a look at the FrameDemo from How to Make Frames for the most basic example of how your code should be structured to avoid problems. It shows how to create components on the EDT and how to make the frame visible.
they won't ve visible until I resize the window,
Resizing the frame will also cause the layout manager to be invoked.
miPanel.setBounds(20, 20, 350, 450);
That statement will do nothing because the layout manager of the frame will determine the size and location of the panel based on the rules of the layout manager. The default layout manager for a frame is a BorderLayout, so basically the panel will get all the space available to the frame.
The tutorial also has a section on Layout Managers that you should read.
I am adding JLabels from an Arraylist to a JPanel and they will only display if i set a layout on the panel but i want to set the location of the labels myself when i try panel = new JPanel(null); all labels are not displayed.
Frame:
public static void Frame(){
panel = new JPanel(null);
JFrame frame = new JFrame("New");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
frame.setSize(400,400);
frame.add(panel);
}
ArrayList iteration that adds labels to panel
private static void printArray() {
for(int i = 0; i < food.size(); i++){
component = new JLabel(new Food(food.get(i).getColor(),
food.get(i).getIconHeight(), food.get(i).getIconWidth(),
food.get(i).getLocationX(), food.get(i).getLocationY()));
panel.add(component);
component.setLocation(food.get(i).getLocationX(),
food.get(i).getLocationY());
}
}
I can see from Debug it is definitely getting the location information, so why is it not putting it in this location.
The reason to set layout as null is so i can update the position of the label so i can "move" it around with keyboard input
The first thing you need to do is understand what job the layout manager actually does, because if you're going to remove it, you're going to need to take over it's work.
Layout managers are responsible for determining both the size and position of the components. They do this through a variety of means, but can make use of the getPreferred/Minimum/MaximumSize methods of the components.
So this would suggest you need to make your own determinations about these values, for example...
component = new JLabel(new Food(food.get(i).getColor(),
food.get(i).getIconHeight(), food.get(i).getIconWidth(),
food.get(i).getLocationX(), food.get(i).getLocationY()));
component.setSize(component.getPreferredSize());
component.setLocation(food.get(i).getLocationX(), food.get(i).getLocationY());
I'd also recommend using the Key Bindings over KeyListener, it doesn't suffer from the same focus related issues
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 know I'm bound to take flak for it, but I'm attempting to set up a JFrame that uses a null layout in its content pane so that I can use absolute positioning for my components.
The problem I'm having is that there is always this gap in between the bottom and right sides of my components and the edge of the window. I thought maybe I was just positioning/sizing things wrong, so I tested using a single JPanel and giving it the same bounds as the content pane, but there was still the gap.
It's equal on both sides and looks like it's the twice width of the window's border. Here's the code:
public static void main(String[] args) {
JFrame mainWindow = new JFrame("test");
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel root = new JPanel();
root.setSize(1280, 720);
root.setPreferredSize(new Dimension(1280, 720));
root.setBackground(Color.GREEN);
root.setLayout(null);
mainWindow.setContentPane(root);
JPanel p1 = new JPanel();
p1.setBounds(root.getBounds());
p1.setBackground(Color.RED);
root.add(p1);
mainWindow.pack();
mainWindow.setVisible(true);
mainWindow.setResizable(false);
}
I thought that maybe not using a layout manager was the problem, so I tried leaving the root JPanel with its default flow layout and giving p1 a preferred size (of 1280x720). But, that had no effect other than centering p1 in the window. I've also tried not changing the content pane but rather adding root to it and then adding p1 to root (exactly like in the above code, except calling mainWindow.getContentPane().add(root); instead of mainWindow.setContentPane(root);) but there was no change.
The only thing I can think of at this point is that something is going on when the JFrame tries to size itself. Any ideas?
The problem I'm having is that there is always this gap in between the bottom and right sides of my components and the edge of the window
mainWindow.setResizable(false);
The above statement should be executed BEFORE the frame is packed.
I know I'm bound to take flak for it, but I'm attempting to set up a JFrame that uses a null layout in its content pane so that I can use absolute positioning for my components
Don't use a null layout unless your application supports dragging of components to random position. In this case the layout manager can't predict the location of the component. Otherwise use a layout manager.
Not quite sure if this is what you are looking for but it works with a BorderLayout:
public static void main(String[] args) {
JFrame mainWindow = new JFrame("test");
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel root = new JPanel(new BorderLayout());
root.setSize(1280, 720);
root.setPreferredSize(new Dimension(1280, 720));
root.setBackground(Color.GREEN);
JPanel p1 = new JPanel(null);
p1.setBounds(root.getBounds());
p1.setBackground(Color.RED);
root.add(p1);
mainWindow.setContentPane(root);
mainWindow.pack();
mainWindow.setVisible(true);
mainWindow.setResizable(false);
}
I wanna fix a 2D board for a game. I've already fixed other panels for the Gui and everything goes well. But the panel for the board cant be printed on the window. I'm a bit confused about it as i think i've followed the same ideas as for the others panels i need.
Here's what i've done:
EDIT:
what I'm trying to do is fix a board panel for the game according to the dimensions of the it,hold every square in an array in order to use it after wherever it;s needed. I draw each little square of it with the method draw and put it back to the panel. So, each square on the board is a panel. This is the idea. But as u can see. There are troubles/errors on it.
EDIT: code updated.
just found a part of the problem. i thought first that i had set background to squared, but i didnt. with this one it appears on the panel a wide black "column". Unfortunately,still none squares. :(
One More EDIT:
Also,i realized that draw method is never called. when i put the draw method in the following method i can see the squares but they remain small. I redefine them with setSize but still no change.
How can I use paint method to edit the panels properly???? As it is now it can't. Even it can't return an object(eg panel) as it's polymorphic void!
/**
*Method used to construct the square in the area of the
*gui's grid. In this stage a GUISquare array is being constructed,
* used in the whole game as
*a mean of changing a square graphical state.
*#param squares is the squares array from whom the gui grid will be
*constructed.
*#see getSquare about the correspondance beetween a squareModel and
* a GUISquare.
*/
private void initBoardPanel(SquareModel[][] squares){
BoardPanel.setLayout(new GridLayout(height ,width )); //set layout
SquareRenderer[][] Squares;
JPanel[][] grid;
Squares=new GUISquare[height][width()];
grid=new JPanel[height()][width()];
for (int i=0; i<height(); i++){
for (int j=0; j<width() ; j++){
SquareRenderer kou=new SquareRenderer(i,j);
kou.setSquare(myGame.getSquares()[i][j]);
//NOTE: THE FOLLOWING DRAW METHOD CANT BE CALLED!!!?
if (myGame.getSquares()[i][j] instanceof SimpleSq ){
kou .paintPanel(i,j,"");}
else if (myGame.getSquares()[i][j] instanceof ActionSq )
{ kou .paintPanel(i,j);
}
//JUST BECAUSE DRAW CANT BE CALLED I PUT ITS CODE HERE:
//JUST TO CHECK:
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JLabel label1 = new JLabel("Move To "+myGame.getSquares()[i][j].getGoTo());
JLabel label2 = new JLabel(""+myGame.getSquares()[i][j].getSquare());
panel.setBackground(Color.ORANGE);
panel.add(label2, BorderLayout.NORTH);
panel.add(label1, BorderLayout.CENTER);
panel.setSize(250,250);
///////// <--until here ---paint method<---
kou.add(panel);
kou.setVisible(true);
kou.setBackground(Color.BLACK);
Squares[i][j]= kou;
BoardPanel.add(kou);
BoardPanel.setVisible(true);
BoardPanel.setBackground(Color.WHITE);
}
}
this.add(BoardPanel,BorderLayout.WEST);
// this.pack(); //sets appropriate size for frame
this.setVisible(true); //makes frame visible
}
IMPLEMENTED BY SQUARERENDERER:
/**
* Transformer for Snake/Ladder
* <br>This method is used to display a square on the screen.
*/
public void paintPanel(int i,int j) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JLabel label1 = new JLabel("Move To"+myGame.getSquares()[i][j].getGoTo());
JLabel label2 = new JLabel(""+myGame.getSquares()[i][j].getSquare());
JSeparator CellSeparator = new JSeparator(orientation);
panel.add(CellSeparator);
panel.setForeground(Color.ORANGE);
panel.add(label2, BorderLayout.NORTH);
panel.add(label1, BorderLayout.CENTER);
}
I see a couple things that are problematic:
When using a layout manager, you should avoid calling setSize. Most layout managers will simply override it. You should use setPreferredSize, setMinimumSize, and setMaximumSize instead, which provide hints to the layout manager.
It doesn't look like the draw method of SquareRenderer ever adds the panel you create to anything. You should either add panel to the SquareRenderer in the last line of draw or (better) add the sub-components directly to the SquareRenderer instead.