I´m creating a TileMap out of JLabels and my Problem is that the last Tile is not placed right.
For some reason the last JLablel is on a wrong position. I think this Image:
and the Code explains what my problem is.
Btw. I am using BlueJ (maybe there is a bug in it, that I dont know)
Thanks for help!!!
//create Frame
this.setSize((size+2)*imageSize+16,(size+2)*imageSize+39);
this.addKeyListener(this);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().setBackground(Color.black);
this.setVisible(true);
//create MapJLabels
for(int x = 0;x<size;x++){
for(int y = 0;y<size;y++){
mapJLabels[x][y] = new JLabel();
this.add(mapJLabels[x][y]);
mapJLabels[x][y].setSize(imageSize,imageSize);
mapJLabels[x][y].setLocation((x+1)*imageSize,(y+1)*imageSize);
mapJLabels[x][y].setVisible(true);
}
}
The code is attempting to set the size/location of the component. This implies you are using a null layout. Don't. Swing was designed to be used with layout managers. You should use the GridLayout. Read the section from the Swing tutorial on Layout Managers for more information.
You create an empty JLabel. By default a JLabel is transparent. I'm not sure now the picture you posted is created from the code you posted. I don't see how the grid is populated with images etc.
Swing components are visible by default so there is no need for the setVisible(true)
Your code attempts to set the size of the frame. Again, don't. When using layout managers you just pack() the frame and the size will be calculated automatically.
Your code attempts to leave space between the frame and labels. Don't. If you want extra space you can add an EmptyBorder to the panel. Read the section from the Swing tutorial on How to Use Borders
You code is using a KeyListener. Don't. Swing was designed to be used with Key Bindings
Components should be added to the frame BEFORE the frame is made visible.
The posted code looks reasonable, but since we can't see where you change the background of the labels or where you add icons to the labels, we don't know what the rest of your logic is doing. The problem could be there.
If you need more help after fixing the above problems then post a proper minimal, reproducible example that demonstrates your new problem.
Related
I am setting a JLabel for the error messages in my program, so initially the label is empty label.setText(""), but when there is an error it should change to something like label.setText("Error, you have entered invalid data...").
If I use setSize(x,y) on the label, it forces other components to displace when error message takes place. But using setPreferredSize(Dimension(x,y))doesn't impact them.
Q1. Why is that?
Q2. What is the difference between setSize(x,y) and setPreferredSize(Dimension(x,y))
Q3. Does it have to do anything with layout?
Thank you in advance for explanation!
P.S. I am using GridBagLayout for positioning my components on the JPanel.
Don’t use the setSize method.
setSize is called by LayoutManagers, like GridBagLayout, to lay out child components. When you call setSize explicitly, you are fighting with the GridBagLayout. Eventually, GridBagLayout will undo your setSize call, when it calls setSize for its own purposes.
In other words, any call to setSize eventually will be wiped out by the parent layout.
setPreferredSize will not be wiped out. Most LayoutManagers, including GridBagLayout, do their best to respect a component’s preferred size.
However, you should not be calling setPreferredSize. Components already have a preferred size by default, and it is almost certainly better than any numbers you can come up with. For instance, a JLabel’s default preferred size is the size which is just large enough to accommodate its text, icon, and borders.
Computing a preferred size is harder than you might think. How many pixels does text use? How many pixels high is a 12 point font? 12 points is not 12 pixels. 12 points is 12⁄72 inch. How many pixels is that? It depends on the user’s monitor and graphics resolution. All of this is known to the Swing rendering system, and JLabel uses all of that information to determine its default preferred size. You should not try to reinvent all of that work, and you should not try to replace that work with something simpler, as it will be inadequate.
If you just let the JLabel keep its preferred size, GridBagLayout will do its best to accommodate that. If the window itself does not have room to display the JLabel’s new text, you probably should call the window’s pack() method after changing the text.
Update: This appears to be an XY problem—you really want a message that you can show and hide.
You want your layout to be big enough to accommodate your message text as soon as you create it. This is typically done with a CardLayout, which lets you place several components on top of each other, with only one of them visible at any given moment. Since you want to show no text at all, initially, you would add an empty JLabel as the first component in the CardLayout, so it is shown by default:
JLabel label = new JLabel("Error, you have entered invalid data...");
CardLayout messageLayout = new CardLayout();
JPanel messagePane = new JPanel(messageLayout);
messagePane.add(new JLabel(), "blank");
messagePane.add(label, "message");
// Do not add label directly to your user interface.
// Add messagePane instead.
mainWindow.add(messagePane);
// ...
// Show message
messageLayout.show(messagePane, "message");
// ...
// Hide message
messageLayout.show(messagePane, "blank");
"message" and "blank" are never seen by the user. They are just unique identifiers for each component (“card”) in the CardLayout. You can make them anything you want.
The setSize() function sets the size not based on any LayoutManager. Thats why you should always use setPrefferedSize() when working with a LayoutManager. setPrefferedSize() firstly tries to be conform with the LayoutManagers dimensions if then possible Java tries to set the size of the Label according to your setPrefferedSize() input.
So yes, it does have anything to do with layout. If possible, you should only use setPrefferedSize() as you are working with layout managers.
Before I start, I'm aware that its a bad idea to not use a Layout Manager and usually I do use one, however, I also have all my components automatically re-size and relocate based on the size of the window. In addition the program I'm working on is only intended to run on 1 machine throughout its entire lifetime. Please don't downvote me just because of lack of layout manager, I found it to be what I need for this particular program.
To my issue, I found a similar post on stackoverflow but a solution was never achieved.
I'm adding a dynamic amount of JLabels to my JPanel, I've noticed that when not using a layout manager, the scroller doesn't work.
This is a simplified version of my initialization code.
JPanel mypanel = new JPanel();
mypanel.setLayout(null);
mypanel.setSize(800,450);
mypanel.setForeground(Color.WHITE);
mypanel.setBackground(Color.BLACK);
scrollablePanel = new JScrollPane(mypanel);
scrollablePanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollablePanel.setPreferredSize(new Dimension(800,300));
scrollablePanel.setSize(800,300);
scrollablePanel.setLocation(250,156);
myContainer.add(scrollablePanel);
where myContainer would be the container (also without a layout manager). The JLabels are added later on to the JPanel with:
enter code heremypanel.add(label1);
after some basic settings are set for the labels such as setForeground and setBackground.
Unfortunately when run, the scrollbar appears as if its not required (see image)
http://i.imgur.com/zp0QKGG.png
The table text seen in the image is made up of multiple JLabels.
If it's not possible to resolve the issue without using a Layout Manager I will switch to BoxLayout, I was just hoping there would be a solution.
The problem is JScrollPanel needs the preferred size of the view component to determine when the view exceeds the scroll pane's viewable area.
The preferred size of a component is normally determined via the layout manager. While you can use setPreferredSize, it is typically discouraged and you will simply run into the same problem as the content exceeds what ever value you decide to set.
A better solution would be to use a LayoutManager or compound layout (using multiple layout managers over multiple containers) to achieve the result you desired...or write your own...
RESOLVED
I've looked around for a while now and I can't seem to figure out how to do this.
I have lots of components within my JFrame and I am able to resize my JFrame. When I resize the JFrame I want the internal components to resize along with the JFrame, but instead they stay exactly where they were when the GUI was first run.
How can I fix this problem? Is there a value I'm not setting somewhere or what?
Edit:
Also, I'm not using any layout manager.
getContentPane().setLayout(null);
You state:
Edit: Also, I'm not using any layout manager. getContentPane().setLayout(null);
That's your problem. You should almost never use null layout. It is much easier to use and maintain a gui that uses layout managers in a smart way. Read the layout manager tutorials as they can help.
I am new to Java, started learning swing and have a problem with resizing a JPanel inside a JFrame. I am following this tutorial:
http://vincentramdhanie.blogspot.com/2009/11/cardlayout-with-netbeans.html
because ultimately I am learning each of the different layouts and have come to the CardLayout now. In the above, there is a JPanel being used for a status panel. That is what I want to do as well, but when I drag a JPanel onto my blank JForm it takes up all the space and I don't see any resizing handles for it like I would if I were using a .NET panel. Changing preferredSize in the properties window also does nothing. What am I missing here? I feel like a complete noob for asking such a basic question but I really can't find any way to resize this thing.. :-|
EDIT:
I forgot to mention; I am using NetBeans IDE
You can't resize the JComponent because you've select CardLayout. The CardLayout can holds/manages one or more components that share the same display space.
What you need to read documentation and good tutorials.
I have Java application which adds JTextFields # runtime to JPanel. Basically user clicks a button and new JTextField is added, clicks again added again...
Each new JTextField is directly below the previous one. Obviously I run out of space pretty soon so I'm trying to use JScrollPane and thats where the hell begins, because it just doesnt work no matter what I try.
Right click on JPanel and Enclose in Scroll Pane. Didnt work.
After reading some examples I realized I must have JPanel as an argument for JScrollPane constructor. Which I did via right clicking on ScrollPane and CustomizeCode. Because apparently auto-generated code is protected in NetBeans and I cannot just change all those declarations, etc. manually. Still doesnt work.
I did try to set PreferedSize to null for JPanel and/or JScrollPane, didnt help.
JScrollPane is a child of lets call it TabJPanel (which in turn is a tab of TabbedPane). I tried to mess with their relationships, basically trying every possible way of parentship between JFrame, JPanel(holding textfields), TabJPanel and JScrollPane, but nothing worked.
I also made VerticalScrollBar "always visible" just in a case. So I see the scrollbar, it's just that populating that JPanel with JTextFields does not affect it.
When there are too many JTextFields I they go "below" the bottom border of JPanel and I cannot see them anymore.
Code for adding new JTextFields is like this, in a case it's relevant.
JTextField newField = new JTextField( columns );
Rectangle coordinates = previousTextField.getBounds();
newField.setBounds(coordinates.x , coordinates.y + 50, coordinates.width, coordinates.height);
JPanel.add(newField);
JPanel.revalidate();
JPanel.repaint();
Sorry for a long post I'm just trying to provide as much info as possible, because being newbie I dont know whats exactly relevant and whats not. Thanks in advance :)
As there is another answer now, I'm adding my suggestion too.
This sounds exactly like a problem to use a JTable with a single column. JList is not yet editable (and might never be).
JTable would handle the layout problems for you, and you can easily access the values via the table.
Use your own TableModel (a simple Vector should be sufficient in your case), and add values to it.
An option you have is to utilize a LayoutManager, instead of setting the bounds directly on the components. To test this, a simple single column GridLayout with the alignment set to vertical should prove the concept.
panel.setLayout(new GridLayout(0,1));
zero in the rows param allows for rows to be added to the layout as needed.
I do this way to add a scrollpane, create a panel and fill it with few components, then create a scrollpane in the component you want to add it, cut and paste the panel in which all your details will fall in and resize the scrollpane.Because the components take a larger space than the one visible right click on the scrollpane and select design this container, there you can increase the size of the scrollpane and add as many components as you have.