Swing: What is a good way to implement fully-scalable components? - java

I am creating an application which has a scrollable and scalable (zoomable) view. Inside this view I want to place other components (most of them customized JPanels and JInternalFrames).
Things such as fonts and borders, and sub-elements such as buttons don't need to be scalable. Only dimensions and position of container components should be.
What do you think, what is a good way to implement scalable components?
EDIT: I'm talking about resizing the entire layout including all
components. Please think of something such as a visual UML editor with zoom functionality.
My alternatives are:
Create a custom layout manager;
Create custom resizeable sub-components;
Create a custom container which would take care of resizing its sub-components;
Do something else?
Possible problems:
Boilerplate code;
Necessity to provide access to additional custom properties of components;
Not straightforward (inconsistent) representation of components in code.
Something else?

This is why layout managers exist: they tell contained components where and how large they should be.
Since you're talking about a UML editor, are you using contained Swing components to represent the various objects in the diagram (eg, a component for a class)? If yes, then you've got a lot of work ahead of you (although it's not necessarily a bad approach). I'd recommend creating a constraints object that identifies the object's location on a "unit space," then multiplying by the current size.

I've done that by creating a custom layout manager. Every component (or rather component class) on the frame has a marker whether or not it shall be resized when the container is resized (e.g. tables are resized, buttons are not). Those which are not resized are moved when the container is resized.
This is used to make resizeable forms without any manual setup, i.e. forms are defined by just specifying x/y/length/width for each component (no further alignment info).

If I look at this problem as visual UML editor then I had to think about single "canvas" component drawing each element as graphical object with base aspect ration and zooming in/out. I can't see reason for list of components aligned within parent container.

I started a similar solution that works fine without touching the original layout.
It's as easy as this:
// Install scalable layout and CTRL+/CTRL- keys for scaling operations
ScalableLayoutUtils.installScalableLayoutAndKeys(new DefaultScalableLayoutRegistry(), frame, 0.1);
It's still under work but It will be soon available as part of the next "utils4swing" version.

Related

Layout Manger to Freely place your objects

I am a self-taught java developer and I use IntelliJ IDEA for Java. Recently I saw a video on youtube in which the guy was using NetBeans and in his JFrame form, he was able to freely place his objects like JButton, JTextFeild, JLabel, etc. I am not able to figure out how to do that. In IntelliJ IDEA I found several layout managers such as Border, Card, Grid, Bag, etc. but none of them gave the desired result. can somebody please tell me how can I get a layout manager in which I can freely place all my objects and also freely resize them without any restrictions? Thank you in advance for any help.
In swing every component extends Container. That means that every component can have nested components (they all have add(Component) method). However, not all of them support the layout-ing of nested components.
What I want to say is, that you can add a component to a JButton, but a JButton is not capable of showing its nested components.
So, in order to have nesting, we use the components - containers that support the orientation of their nested components.
These components are all windows (JFrame, JDialog, etc...) and JPanels. There some others that support layout-ing a specific type of nested components. For example a JMenu is capable of showing JMenuItems properly.
Now, these "top-level"/empty containers are using Layout Managers in order to align-show their nested components. Based on the container's layout manager, the components are shown.
This is why you can't "freely" place the components into a JFrame. Because its Layout Manager is taking care of the components will be placed. So, what you are looking for, is to change its LayoutManager (use setLayout method) to one that allows you to freely place the components.
Guess what? There is no such layout manager. Simply because, it would have nothing to do/calculate since you are taking care the layout of the components. So, in order to achieve the "free" component layout, you must use jframe.setLayout(null);. In order to layout the components after it, you will have to use componentInsideJFrame.setBounds(...) and give it constant coordinates /dimension.
This is bad practice. A very bad one when it comes to UI. Giving a component static coordinates and dimension is bad. There are some questions you have to ask yourself.
What if user resizes the window? If the window is 301x301, the center of it, is at (150,150). So you place a component at (150,150). Ok it works. Now user resizes the window and makes it 501x501. The center is now standing at (250,250). But the component is staying at (150,150). There is the solution of setResizable(false), to this kind of problems, but how often have you used "uncapable of resizing" applications? What if user wants to resize it?
I hope you get it and understood what I am trying to say.
By using layout managers, you are solving this kind of problems easily, since the layout manager will take care of the resize and calculate the new center.
Yes. I know it feels weird, but all these youtube tutorials are not teaching you the correct way to make Swing GUIs. (This is a conversation for another day, I guess)
I truly suggest you read the tutorials of Swing documentation in order to get some ideas of how layout managers work. You will really benefit from those.
Finally, I suggest you to leave outside the whole "gui-builder-tool" thing. They seem to help you building your GUI, but they are adding so much additional/useless code and most of the times they are "bad UI creation" prone. Try to code the GUI by yourself.
At first, this sounds a bit harsh, but you can always run your application and see the result of the GUI. After some mistakes, you will finally be able to imagine the GUI result by only seeing the container.setLayout(..) and container.add(...) lines.

Adding more than one JPanel in a single JFrame

I have created a JFrame - now I want to add the 4 JPanel in that frame at a particular location. How can set the location of panels in the frame?
Use (possibly nested1) layouts for the logic. See Laying Out Components Within a Container for details. They can:
Include default spacing in the constructor (often)
Calculate how big the GUI needs to be in order to display the components (in whatever PLAF, on whatever system the app. is deployed).
Extra spacing can be organized by adding an EmtpyBorder to child components.
See the nested layout example
Placing components in a container is quite a complicated subject in Swing. Instead of defining the exact places for your components, you would normally use a layout manager that arranges them in a certain way.
Here is the tutorial you should read to get a (visual) clue about the different layout managers: A Visual Guide to Layout Managers
However, the standard layout managers of Swing can be cumbersome for more complex layouts. Either, you could use nested layouts to get the desired result, or you could use a very powerful third-party library: JGoodies Forms. The downside is of course that you have to learn yet another library. Therefore, I would only recommend it for a bigger project.
For me it is good way to set GridbagLayout for the container of the frame. There are several visual swing GUI editors available to do this easily. You can use NetBeans GUI editor or GWT Designer (https://developers.google.com/web-toolkit/tools/gwtdesigner/) for complex GUI designing tasks
If its 4 locations, you can use BorderLayout,by default its the CENTRE, but it also have EAST, WEST , NORTH, SOUTH locations for the placement of the components. You can also use setLocation to put the panels in the appropriate locations, if a layout isn't used.
Its even better to use GroupLayout developed my NetBeans team in 2005, use Windows Builder Pro, now provided by google for free.
set the layout of the Frame to be null via setLayout(null)
create 4 JPanel and set their location using setLocation method
add these panels using JFrame's add method

Resize gui elements by dragging the corners

I have a swing project and noticed that the elements inside the JFrame is statically located inside the JFrame and I do not have the option of resizing the elements as I want to.
My gui app inside the designer window looks like the following:
I want to resize the button (E.g.) by dragging the corners of the button, but I am not allowed to?
As you can see on the following picture, the dragging is not allowed per pixel, but only per section in the JFrame:
How can I disable the static placement of the elements/Enable the self-dragging of elements inside the designer window?
Most likely you will need to disable the LayoutManager. On Netbeans, Setting this to null would provide you full control over the location and dimension of the child elements, so I am assuming that something similar should work here (although you seem to be using Eclipse, if that is the case, please state what plugin you are using).
It is to be noticed however that usually you want to have a layout manager taking care of how your components are rendered. I would recommend you take a look here for some more information on layout managers prior to removing them completely.
Setting size and position of components in a GUI should be left to the JRE at run-time, using:
The preferred size of the component (with current content, in the current PLAF).
The borders/padding/insets set to the component.
The layout used.
The component spacing defined in the layout constructors.
The layout constraints used when adding components to the layout (especially important to e.g. BorderLayout and the much maligned GridBagLayout, as well as many 3rd party layouts).
Generally, complex effects are created by using a nested layout.

purpose of JPanel?

This write up on JPanel seems to focus on this container as a means of setting a background color. Oracle on how to use JPanel Should I infer that if I am happy with the default grey background in ubuntu/gnome/Java programs, there is no need to use this object? Is there an object-oriented programming reason to use this object?
JPanels are a way to create a logical "division" of space if that makes any sense. For example, if you think about HTML, you could just put elements one after another on the page (how some old HTML pages look in fact) but it's much more aesthetically pleasing to use a container like a table, or some CSS styled DIV tags to create divisions on the page, and place elements relative to one another in a much more defined manner.
JPanels fill this function in Swing, where each JPanel has a Layout Manager that defines how it's inner elements are laid out. It's not unusual to nest JPanels, for example, using a JPanel with a border layout for the menus/status bar, etc, a JPanel at the center of that with further elements, and then additional JPanels inside of that central "content panel" area that further divides the space, for example, creating an input form on one part of the central panel.
In this sense, JPanels are quite comparable to how Tables and Divs are used in HTML, and you should think of them in a similar manner when creating your layout. The most important thing about JPanels is their ability to dynamically resize, pushing the contained components around. If you just used, say, one JPanel and absolutely positioned everything, then you'd lose the main appeal of Swing, and this container methodology.
It's quite possible you perceived the authors angle to be one slanted towards color and drawing, but I think if you give the blog a second read you will find that he was indeed trying to be more expansive than that. JPanel's can and are used as content panes for a variety of other widgets in a typical Swing application.
Also I'm not sure why you reference Ubuntu/Gnome, as the L&F of a platform is quite divorced from the utility of JPanel.

Why is it frowned upon to use a null layout in Swing?

Recently, I started creating a program for the company I work for. Just as background info, I'm still a student and a beginner programmer, so my solution is probably not recommended and I didn't know how to do it otherwise, but it works and I'm not going to be judged for it because it's a student job totally unrelated to programming.
The thing about the program is, it's going to be run on multiple different computer with different screen sizes and resolutions (800x600 and up). To make sure it takes as much of the screen as possible without losing any part of the program, I set the layout to null and hard-coded everything using relative values.
The program is kiosk-style and I first get the screen size values and go from there (for example, off the top of my head, the left-side menu takes an eighth of the screen, the top bar 2%, etc.). I also use font metrics to make sure the components are sized correctly and that everything gets displayed nicely.
My question is: why is it so frowned upon to make the layout null instead of using the layout managers? (I was told on some forums that this is a horrible way of doing things) I know how the layout manager works and know how to use the different layouts, but for the requirements of this program (multiple different resolutions, custom button shapes and placements, text changing on the components when you change language, etc.), I couldn't see myself using the layout managers to do it all.
How do you more experienced programmers use the layout managers in a situation like this? And what do you do when you want a button to be somewhere specific and other components somewhere else specific that don't really match any of the predefined layouts?
If you layer the layout managers correctly the screen will re-flow to different sizes for you, the idea is to use a single set of layout managers on ALL screen sizes.
If you use null you will have to do each screen size yourself. Not only that but if the app can be windowed you have to support every possible size they might scroll to.
That's kind of difficult to do, but the layout mangers are designed to do just that.
There are some common tricks. BorderLayout is a great layout to start with. Sometimes you might use it at multiple levels--often with just 2 or 3 components in it. That's because it's really good at giving all but one area the minimum required area and giving everything else to the CENTER.
FlowLayout can be useful but it's tricky if your components are different sizes.
I wouldn't try GridBagLayout unless you are planning to write code to feed your layout manager (an excellent solution at that!).
I also wouldn't use GUI builders, they don't know the overall way you want to reflow your layout.
In a nutshell: because all the work that you explain above is done (or at least: should be done) by the layout manager.
More often than not, when a null layout is used, it also implies that all positions and sizes are hardcoded to a single value, so no flexibility at all is given. This means that changes in window size, language, font size, display density or any other related parameter have no effect on the layout and you get the usual ugly effects: empty parts of the window; tiny, unresizable lists; buttons with their labels cut off; ...
It sounds like the work you do should really be done by the Layout Manager. Either find one that does that (my personal suggestion would be MiGLayout, which does a lot and is easy to use) or write your own.
You are practically using a layout - your own, with all your sophisticated calculations of positions.
You can move these logic to a custom layout manager class to pacify the critics.
hmmm trick should be by mixing LayoutMangers and by usage of numbers of nested JPanels that each could have diferrent Layout or not, really depends of number of JComponents, that allows you to create GUI that looks like as layed by using AbsoluteLayout but with same look/output to the GUI for every screen resolutions and ratio (4:3, 16:9, 16:10)

Categories