A better swing gui design? - java

I am working on a project for an online class I made the mistake of taking this summer and I need to build a gui to show how the huffman code algorithm works. The algorithm part is easy, its not very complicated. However im unsure what the best way to draw the tree(forrest) at each step. It would have to start out as just n nodes (with chars in them) on the screen and then you would press a "next" button and it would pick the two lowest nodes weighted (based on character frequency) characters and make them children of a new node (with just a weight - no char) and then update the screen/panel.
I have made swing gui before, my skills are nothing special but I know my way around. However im stuck on this implementation. I have a couple hundred lines of code written right now, but it doesnt work and I think its bad anyway, so I want to "start over" and plan it out better. So Id just like some advice on the data structure to keep track of the nodes and how to draw them on the screen.
I was using an ArrayList of JPanels as nodes and trying to draw them to a null layout. Im sure this is awful and id like to know a better way. Possibly GridBagLayout?
NOTE: don't say JTree.

A good option is to just use a library for drawing trees/graphs. I've had good success with Visual Library in the past.
Another possibility is Prefuse

Instead of wrestling with the different Swing layouts you could just do custom 2D drawing. See for a simple enter link description hereexample here on how to get started.

Use an image of a tree (only one instance) and an array or other data structure to contain the "data" that the algorithm uses. Think about how you can use the data to determine where the image should be painted. Use the repaint() after the algorithm runs.
[Next] --> Algorithm runs --> Update using repaint();
So you have a single frame, a single panel and a single BufferedImage object.
The trick will come in when you have to get slightly mathematical to know at what co-ordinates a node should be painted.
The layout of your components are insignificant, as you're not adding any components to the container, just painting image data onto it.

We all had that what you have once ;-)
First of all, never use Null layout because then you make sizes static and your application will not work on other resolutions like desired.
Best layoutmanager to use: GridBagLayout !
Why ? very flexible and you can get all components exactly on the place you want, discarding the resolution. Its harder to set up but better result eventually.

Related

Positioning a label in Java Swing

I have gone through lots of tutorials which teach about layouts in Java Swing, but they don't seem to suffice my need. I am creating a solar system GUI using Java Swing, and i want to place the planets in the GUI according to the values i fetch from my micro controller, which are usually float point values. I cannot use the Grid Bag Layout, as to position a label i have to specify grid x and grid y, which cannot be the case since I receive float point values from the micro controller. The best resource i found is to use absolute layout where i can specify the position of the planet by giving mere X and Y Co-ordinates, which will be fetched from the micro controller. The problem I am facing now is that the absolute layout does not have auto re-size feature.
What would be the best possible option to adopt the auto re-size feature in absolute layout?
Swing tutorials were not generally meant for situations like this -- they were meant for people who want to write more normal GUI applications, using buttons, drop-down boxes, check boxes, radio buttons, menus, and have layout that follows currently accepted practices in terms of positioning those on the screens. If any of that applies to the part of your program that is not displaying planets, I encourage you to use what they have to say about it.
But you want to place things according to calculations of your own. I recommend doing that in a panel, calculating the size and position of your objects according to the size of the panel at the point of drawing. When the panel resizes, you will need to trap the event that says it is resizing and redraw. You will need to deal with your own minimums and maximums, etc.
I don't recommend the custom layout manager suggested elsewhere for a couple of reasons. Firstly, it won't save you any work at all -- you are still going to have to write the code that determines positions of things, if you just then draw your own graphic instead of attempting to position a UI element, I think it will actually be less work. And that's the second reason -- layout managers' purpose is to position UI elements within the panel, and the pieces of your solar system don't really have any need to be UI elements, just graphics on the screen.
Good luck.

How to know length and width to set?

Just began GUI programming a few days ago and I am wondering how I know what dimensions to give my window and the objects inside of it. I know in my head what I want them to look like but I am just not sure how to know the measurements. Any tips?
Modern UI programming does not normally involve setting exact measurements of components in a window. You need to read a basic tutorial on Java Layout Managers; the basic idea is that you use the layout manager to arrange things so that they are lined up the way you want and stretch the way you want when the window's size is changed by the user. You put the components in the places that achieves the overall topological shape that you want, and you don't set a specific size.
Good luck.

Arranging images according to background in Java

I'm trying to develop a Java program that does the following:
uses a background picture of a network diagram of clients
positions an image of a bandwidth graph to respective client
refreshes the image of graph every 5 seconds which it fetches from another program that constantly produces snapshots of bandwidth
Now, I can set the background picture and I'm pretty confident that I will be able to refresh the images by using a timer. What I am trying to plan out is how I am going to position these images to the respective clients which is displayed in the background picture. I did some research and it appears that I have several options but I want to make sure I am choosing the right one before I run into problems further down the line.
It seems to me that using a GridBagLayout would be the choice for me, however I would like a second opinion for a more experienced population. If using a GridBagLayout is the correct choice, could you recommend any good tutorials that would help me understand this Layout Manager? Please keep in mind that I have limited experience with Java, especially with GUI oriented Java.
EDIT: If I am not explaining the concept well enough please let me know.
check this out-
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
GridLayout is likely to meet your needs and it is easy to use - the assumption I make is that image of bandwidth graph is the same/fixed ...
Look for an example here
http://www.roseindia.net/tutorialsearch/?t=java+gridlayout+color
Try Google the keyword "GridLayout" - there are plenty of hits ...
If you want to do advanced layouts, you should take a look at MigLayout.
It's an extremely flexible layout manager that can pretty much act as a replacement for any/all of the existing Swing layout managers. It's worth using if you want to do difficult / complex layouts.
It feels more like a HTML table layout tool, enabling multi-column spans etc. and arbitrary scaling rules.
The "Quick Start Guide" is very good with lots of examples - I'd suggest taking a look at that if you want to evaluate MigLayout for your project.
If the 'bandwidth graph' image(s) is on top of the BG image, look to OverlayLayout
A layout manager to arrange components over the top of each other. ..
OTOH I would not use a layout strategy for this, instead..
Create a BufferedImage the size of the BG.
Paint the BG to the image.
Display the image in a label.
When it comes time to paint the graphs, get a Graphics instance for the image in the label, and paint them to that. If the graphs are always the same size and shape and do not have transparency, you can simply paint them. Otherwise, draw the BG first.

How to wrap a Component to several lines

I have a large component (say width=4000px, height=200px) and would like to be able to see it entirely even on a small screen.
I don't see any easy way to do a wrapping component, my idea is the following :
given a factor (for example 4), the component would be of size 1000x800, by wrapping the child to 4 lines. The size requests would be translated in reverse to reshape the child, and so on. On painting, the component would call the paint(Graphics) of the child 4 times with a correct Graphics argument that would map the wrapped space to the child's space.
However, I can't see how to handle all the events : should I set eventlisteners for every children-generated event (PropertyChange) and for every parent-generated event (Mouse, Key, Resize, ....) ? This seems quite a lot of mapping, and I'd be happy to ear of an easier way of doing that...
I haven't looked too much at the JViewport implementation, but maybe this could help me don't you think?
thanks for your suggestions!
Frederic.
Edited to answer some of the comments that suggest to redesign the component :
Allow me to disagree here : making a component is one job, showing it is another. If I want to show it with scroll bars, I use a Scroll-Pane, whereas if I want to show it split in 4 lines, I want to use a similar solution.
I am the designer of the component in question (and had sharp words with myself, as suggested, but it lead me nowhere :-) ). I actually added "line-wrapping code" in it but it appears (really quickly!) that adding point space conversion, painting management in the codes of the component itself makes it really really messy, which is the reason why I imagine that a specialized component is a really a better solution.
Furthermore, making a custom component lets me reuse it far more easily as a "wrapper" for any other component.
Imagine if you had to recreate a JScollPane-like functionality every-time you use a JScollPane, dealing with scroll position, buffered painting and everything inside your own components : hopefully you don't have to!
You're approaching this the wrong way. It's the contents of the component, not the component itself you should be thinking about. If you want it to be 1000x800, make it that size. If the component has content - e.g. text or other components - calculate their positions appropriately. (You probably won't be able to use the standard layouts, and may end up writing your own). You'll probablky need to recalculate the layout if the component's width changes.
Don't call paint 4 times. If you've calculated the layout of the component, it's children or text, correctly then paint should just work.
In response to the comment: wrapping a histogram, in the sense of inserting arbitrary line breaks, is not likely to be useful. With graphical components the 'breaker' won't know exactly where to insert the breaks; you will also lose any information attached to the Y axis. Much better solutions would be to simply shrink the histogram in the horizontal direction until it fits the screen width, or to draw four histograms one under the other, duplicating the Y axis information for each. Alternatively allow horizontal scrolling over the whole histogram; or change the axes so the histogram is drawn horizontally. If none of the above work, perhaps because you have many hundreds of histogram bars, maybe a more interactive approach where you amalgamate some of your histogram bars together to give an overview, and allow the user to 'drill down' into the plot to get at the more detailed information.
If the issue is that you can't modify the original component, and it draws a fixed size image, then your best bet may be to call 'paint(Graphics)' on it four times with appropriate transforms and clipRects on the Graphics to draw the four parts 'stacked'. But frankly you may be as well off throwing away the original component. Histograms are not that hard to draw, and there are plenty of free plotting packages to help you. And be very rude to the designer of the original component if you meet them.
You don't mention scrolling. Put it on it's own pane and then put that pane into a scrolling panel.

scroll bar problems in java Layered Panes

I've been trying to build this small java app. I find it very difficult to design UI in java, tasks that seem very simple become complicated and all these strange misbehaviors occur. In my app I've created a JLayeredPane which contains two layers. One on top on the other, They both contain scrollbars.
Here's an explanation of the two layers:
Layer 1:
A very big image inside something similar to a scrollpane. The image is scrollable.
Layer 2:
A graphics2d object, this object draws an image. Once the image reaches a certain length, the layer gets a scrollpane that advances with the drawing with time.
I'd like to connect both layers. I want layer two to update the scrollbar on layer 1. Meaning that once it reaches a certain length, both scrollbars will advance together. When I try doing that, the two scroll bars really do advance, but ( ! ) this strange flickering occurs. I don't understand what is the reason for the flickering. Is there any other way to implement this in a simple manner? I must have the second layer on top of the first one (drawing on top of image)
since I cannot open a special post for thanking the wonderful people of this forum, I'll do it here. Thank you, you are great help. I hope this problem is solvable as well.
It sounds like you're repainting the entire component in some costly way each time - you could try to paint to a BufferedImage to save the image rather than re-generate it each time. Or you could try to mess around with how repaints are handled. I'd suggest this article and this page on Sun's website - both discuss performant painting practices.
Without seeing your code it's quite hard to guess where is the problem. Probably you're getting more paint() events than you really need.
Also you can try JXLayer (http://weblogs.java.net/blog/alexfromsun/archive/2008/06/the_new_jxlayer.html) to show your graphics2d layer.

Categories