I have code with null panel:
JPanel thePanel = new JPanel();
thePanel.setLayout(null);
I used setBounds(x, y, width, heigth), for example here:
label2.setBounds(150, 220, 459, 311);
I read that this is not a good practice, can you tell me why?
Is it only because when you want to add something between one component and another you have to set them positions again and again or is it something else?
There are multiple problems with absolute positioning:
Different screen sizes and resolutions, what looks great on your machine would come out differently on another screen with a different resolution.
In the same vein, what happens when a user resizes the screen because they want to run your application side by side with some other application (to copy paste or whatever)
Different locales and font sizes, what happens to your labels when you use another locale, or another font, or change the font size.
There's probably more reasons, but using a layout manager makes sure that content is redistributed when windows are resized, or when content of a container changes, ...
Using absolute positioning is probably the easiest way in the beginning, but it pays to get to know the different layout managers and how they operate. It will save you from a lot of headaches due to, for example, changing requirements.
Related
So, I'm trying to design my first GUI app, and i'm stuck on putting elements exactly where I want them. I'm not trying to let anyone do my job for me, but some starters would be great.
For example:
The basic answer is, you don't. Pixel perfect positioning is an illusion in modern user interfaces. Why? Because no two platforms are equal (unless they are exact copies). Each computer will have different requirements when it comes to how information is rendered on the screen, most notably, fonts.
Font metrics will change between platforms, meaning that the way a font is rendered on your screen won't be the same as it is rendered on someone elses. This causes no end of issues not only of an individual component, but how the surrounding components should react.
The best choice is to use layout managers, which provide "guides" on how components should be laid out and how they effect surrounding components.
Based on your example above, I would suggest you would actually need (at least) three layout managers.
At the base, you would use a BorderLayout, this would separate the form from the buttons.
You would need a fields panel and a buttons panel.
The fields panel would contain the actual fields and probably use a GridBagLayout. The buttons panel would contain the buttons and probably use a FlowLayout
The form panel would be added to the CENTER position of the base panel and the buttons to the SOUTH position.
Take a look at Laying Out Components Within a Container for more details
What you want to look at is various layouts in Java (Given that you are asking a basic question I am assuming you are using Swing).
See this link for more info: http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
It will show you the various layouts available in Java and how to use them. You will need to use different Components along with different layouts to render your GUI exactly the way you want it.
I have a very simple game I'm creating as a novice project. It's based on an online card game called "Castlewars". There are two players, each with a tower which is affected by cards they and their opponent play. At the moment I have the basic framework of collections and classes I need to make the game operate at a very simple level, but I'm having problems displaying these effects to the user. I have the following code, which should update, amongst other things, two jLabels on a jFrame GUI (constructed in NetBeans 7.4) which represent the player's towers:
private void adjustScreen(){
System.out.println (Integer.toString(jLabel1.getSize().height));
jLabel1.setSize(100, (playerRed.getTower().currentHeight() * 2));
System.out.println(Integer.toString(playerRed.getTower().currentHeight() * 2));
System.out.println (Integer.toString(jLabel1.getSize().height));
jLabel2.setSize(100, (playerBlue.getTower().currentHeight() * 2));
jLabel5.setText(Integer.toString(playerBlue.getTower().currentHeight()));
jLabel6.setText(Integer.toString(playerBlue.getGold()));
jLabel9.setText(Integer.toString(playerRed.getTower().currentHeight()));
jLabel10.setText(Integer.toString(playerRed.getGold()));
if (TurnBlue){
jPanel21.setBackground(inPlay);
jPanel10.setBackground(outPlay);
}else{
jPanel10.setBackground(inPlay);
jPanel21.setBackground(outPlay);
}
}
When I run it, i get the following output:
(Initial label height) - 200
(adjusted Tower().height) - 100
(adjusted label height) - 100
Which suggests that what I'm trying to do is working on some level, but the actual labels visually stay the same size.
At start (the initiation of the game should have set the labels to half their visible size):
After a couple of plays - the Blue's new tower height is shown in the top left
I've played around with enabling and disabling the resize property, both on the label and on the frame, and I did once manage to get it to resize, but it then shifted the other components of the frame in an unfortunate way. As you can see, the "Cards" at the bottom do seem to resize themselves, although I am not explicitly instructing them to do this (maybe an effect of the text length in the "Cards"?) What am I doing wrong?
After re-reading the question I realized the answer is not really an answer to the question but more of a list of suggestions. Rather than deleting it, I'll leave it up in case someone can gain something from it :-)
"What am I doing wrong?"
Welcome to the world of "Why I should use Layout Managers"
There's an ocean of problems that may arise from null layouts and trying to set size and location to everything. Swing was made to be used with Layout Managers.
Some layout managers will respect preferred sizes and some wont.
Use the correct layout manager and make use of nested JPanel with different layout managers to get your desired result
Make use of EmptyBorder and vgap and hgap for empty space.
Don't set size or location to anything. Let the layout managers take care of that for you.
Go over Laying out Components withing a Container to learn the different layout managers.
EDIT
If you're using Netbeans GUI BUilder take a look at this answer for some help with how to use different layout managers using the design tool.
I am using the NetBeans Designer to create a JFrame. Also it is worth mentioning I am fairly new to Java so I might not understand some things / do things correctly. The frame has about 100 panels, more buttons than I would even think about counting, about ~40 tables, basically most swing components the NetBeans designer provides are being used within the frame. Also for the main frame I am using Null Layout (in order to have a background image inside a JLabel). I know it is not recommended but it doesn't affect the general layout of things as I'm using panels/LayeredPane/TabbedPane for everything, each with it's own design (most of them on Free Design with no Layout specified - that's how I started, didn't know about Layouts and it would take ages now to rearange everything after using Grid Bag Layout for example).
Now getting to my problem, I need to be able to resize the frame and make it resize all components contained. I have to carry a presentation tomorrow of it and I just noticed it doesn't fit on smaller displays (and resizing it doesn't do it properly, it just hides components). I do not care much if it's just an improvisation / not the best approach to the problem as after the 15 min presentation I will probably never open it again.
Thanks.
I would try to go through all the components tree and try to set them smaller font and reduce all their bounds to some static %.
In other words for each component multiply x,y,widht,height to e.g. 0.75 and call setFont() passing derived font of 25% smaller.
I'm using Java Swing and I want to it to set its JFrame size and the size of inner components size based on Screen resolution. I also want it to be compatible on any device like Tablet, laptop. Any easy solution for this?
I also want it to be compatible on any device like Tablet,laptop.Any
easy solution for this.
Put JScrollPane to JFrame, then put JPanel nested all JComponents to JScrollPane, then all JComponents are accesible for non-standard screens e.g net_books, crazy tablets with two or more Native OS (most of screen in Native OS there is scrolled by default)
I'm using Java Swing and I want to it to set its JFrame size and the
size of inner components size based on Screen resolution.
This is a job for LayoutManager
for really better look is not possible without manage with Font size, basically there are a few screen ratios (4:3, 16:9 ...) with a corresponding pixels (screen) resolutions, rest of then to leave for JScrollPane
there is not universal advice, everything depends of your GUI, how JComponents are laid, number of JComponents, its Rectangle on the screen
about the arts, make it look nice and good concept, (then nothing complicated)
Is there a simply layout manager I can use in a JPanel to create something akin to a bar chart? FlowLayout almost meets this need. The added component orientation needs to be left to right (default for FlowLayout), but they need to "rest" on the bottom of the panel with excess space at the top (not available in FlowLayout). Also, the components will all the be the same height and width.
Thanks.
A BoxLayout will do the trick as demonstrated in this posting
If you are going to do something like a bar chart, you might want to consider not using Components at all. Just have a single JComponent that overrides (IIRC) paintComponent. It'll be easier to do the calculations in a manner appropriate to a bar chart rather than trying to use an inappropriate layout manager abstraction.
FWIW, I default to GridBagLayout, even if a simpler layout manager will do, on this basis that the code can be more consistent.
You can do exactly what you want in GridBagLayout. Yes, I know everyone hates GBL; yes, I know I'll get down-voted. But it really is not difficult to understand and you can use it for almost any layout goal.
The trick to get a component to "stick" to the bottom is to use the anchor and fill properties of the GridBagConstraints object properly (i.e. SOUTH and NONE)
A BoxLayout might work for you. It lets you layout components left-to-right or top-to-bottom, with the tightly coupled Box class to force spacing constraints.
I actually prefer the FormLayout, since it is very flexible but you have to write a lot of code though. And in the beginning its a little bit confusing with its percentage and pixel parameters.
But you can for example tell a control that it is 5 pixels left of another control (thats the main part...it layouts controls in relation to neighbors), then it takes 100% of the lasting space availabel including a border space of 5 pixels (you need to use -5 then).
I think it looks somewhat similar to this
FormData data = new FormData();
data.left = new FormAttachement(neighborControl, 5);
data.right = new FormAttachement(100, -5);
...
button.setLayoutData(data);
This example is for JFace, but there are Swing implementations as well.
I will look up my old code later this day to check if the code I wrote is right :)
HereĀ“s a additional link