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.
Related
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.
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.
I've spent many fruitless hours trying to create what I consider to be a very simple GUI. One thing that makes it simple is that I don't even expect it to be resizeable. I want it to display just the way I've laid it out. Simple as that.
There's a JFrame containing two Jpanels of equal width, one above the other. I've got the JPanels behaving themselves finally, and I can slide them around without their enclosed components mysteriously shifting.
But I can't for the life of me get the JFrame to nicely enclose the JPanels. I'm attaching a screen shot showing the layout and the inspector, and another showing how it previews
(Notice that it's chopping off the bottom edge.)
Is there any way to work in a "WYSIWYG mode" in the GUI builder? I don't care about (in fact, I dread) resizeability, at all at this point. I would have thought Absolute Layout would be the right choice for this, but there's still something wrong. (I need an elementary solution, folks -- please don't suggest GridBagLayout!! ;)
EDIT: By restoring some defaults, mainly for MaximumSize, to the JFrame, I got rid of the clipping problem. The right edge was still off by one pixel, and I managed to find which of five (five!) width properties was controlling that. (bounds, max size, min size, preferred size, and width - changing min size fixed that.)
I've already found that you can't completely avoid tweaking properties (e.g. to override "snapping" and achieve pixel-precise positioning). I clearly made trouble for myself at some point by playing with some properties I shouldn't have. The question remains: for non-resizable, WYSIWYG GUI design, is Absolute Layout a reliable choice; and, what properties should I avoid editing?
Is the JFrame showing any better when you actually run than preview? I think this is an OS X specific NB behavior. I did not see this in Win32. For now, you may try adding a JLabel ( spaces as the text content) at the bottom to make sure that space is drawn when the actual JFrame runs.
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.
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.