I have built a GUI displaying a matrix. It looks much like in excel where you have labels on the first row and first column. The cells contains either 1 or 0.
There's a JComboBox below the matrix. I can select an item from the JComboBox and click a button "add". This adds an extra row to the matrix with the JComboBox item as its name. My question is how i should handle expanding this.
Is it a good idea to have a method that redraws the whole window? Or should i try and just redraw the part that's been changed?
I thought of having a method like updateWindow() that could be used both for initiating the window and updating it if i make changes.
Is it a good idea to have a method that redraws the whole window? Or should i try and just redraw the part that's been changed?
It depends on what's in your window.
If you're drawing on a JPanel, by overriding the paintComponent method, redraw the entire JPanel. It's not worth the effort to try and redraw a part of a JPanel.
If you have a window made up of many JPanels, you can redraw just the JPanel with the changes.
I thought of having a method like updateWindow() that could be used both for initiating the window and updating it if i make changes.
It's generally a good idea to create methods to perform specific GUI tasks. I'd have separate initializeWindow and updateWindow methods for my own sanity. I usually separate the initialization of my GUI from the update of my GUI.
Read this excellent article, Sudoku Solver Swing GUI, to get an idea of how to put together a Swing GUI.
When you add components to a container, you will be invalidating that container's layout. This will automatically trigger a repaint, so the question becomes moot.
The real question becomes why?
Instead of messing about with labels and fields, you should just simply use a JTable. Check out How to use Tables.
This is optimized for performance, so if you're really concerned, this should provide a better solution, so long as you are firing the correct events to the required changes.
Unless you're finding yourself performance bound, I see no real reason not to redraw the entire window; sure there will be a performance hit but it should be negligible and your source will be simpler and easier to maintain. However, if you're finding yourself pressed for performance, I would suggest looking into implementing a "dirty rectangles" method of redrawing (i.e. your second approach).
Related
I am looking for a reliable way to be informed when the mouse moves and when the component beneath the mouse moves. While the first part can be rather easily implemented by using a MouseMotionListener, I am currently struggling with the second part.
Right now I have these two ideas:
1. Listen for all relevant changes
This one seems to be rather tough, so far I have
ComponentListener: When the component is moved
AncestorListener: When the ancestor is moved
MouseMotionListener: When the mouse is moved
And when a JScrollPane is used:
ChangeListener: When the view changes
Pros
Only triggers event based.
Cons
Breaks when JScrollPanes are used and you are not aware of it.
Additionally for my specific usecase I want to implement this hover behavior for a JEditorPane and the text layout could change. As described in the comments, for example changing text orientation of a text/rtf editor pane by pressing Ctrl + Shift + O.
2. Regularly check position and inform components
Regularly get the mouse position and inform the child component containing this position about it.
Pros
Catches all situations.
Cons
Always triggers, even if no change happened.
Is not immediate.
The component lookup is maybe rather expensive, especially with many nested components; I am currently using Container#findComponentAt but have not done any tests. (But maybe only as expensive as the lookup for MouseMotionListeners.)
Do you have other solution ideas, additions or changes to the ideas above?
I need to refactor my application, since I'm running into rendering issues which are probably a result of not properly using the event dispatch thread. In order to do things right, I try to gather information. I already started this thread, which was about the EDT:
When exactly are components realized in Swing
Now I would like to know more about the best way to nest Panels.
Let's say I have the following structure:
[PanelA [PanelB [PanelC ]]]
What would be more performant (less internal calls to invalidate())
Order 1 (first inner components then outer):
PanelB.add(PanelC);
PanelA.add(PanelB);
Order 2 (first outer components then inner):
PanelA.add(PanelB);
PanelB.add(PanelC);
If someone also has more info/links/hints etc on how to get the most performant UI I would really appreciate that. Most Tutorial just explain the basics.
A related question:
Since all JComponents are Containers, I consider saving some JPanels, by adding components to let's say a JButton. Is this good practice:
JButton b=new JButton();
b.setLayout(new BorderLayout(),BorderLayout.Right);
b.add(new MyComponent());
How can I know which layout a Component uses by default and what could possibly happen, when I change the Component's Layout?
Thanks a lot for your help.
You should not worry about the order of adding the components, the difference will not be noticeable to the user.
You should not worry about the performance of the UI in general. Swing code in itself will be "fast enough". Performance/responsiveness gets interesting only if you are starting long-running non-UI tasks from the UI.
If you add panels to buttons, it will confuse the user. You can check the source code of the components to see their layout managers (but this is very rarely necessary)
I've been staring at Oracle's JLayeredPane tutorials but they are laid out in a manner that is confusing to me and doesn't get at what I am trying to do.
I have an application that up to now has had no concept of layers. Everything is laid out in a single layer, inside a JFrame.
I now want to introduce a component that appears sporadically, as needed, in a certain location, overlaying existing components that stay there normally. Do I have to modify my existing application JFrame so that all its top-level contents (that is, the components that are directly added to the JFrame) are instead added to the JFrame's JLayeredPane?
Or what, exactly?
I'm looking for an easy way to adapt this gui to use layers with the minimum rework of the existing GUI.
Thanks in advance for any help here.
You may want to instead consider drawing your overlay element on the glass pane. That way you can leave the underlying structure completely as-is.
I'm making a Gui for games, and I only want the Gui to redraw a widget when it is necessary. Is there an algorithm to knowing when the widget needs to be invalidated? otherwise it seems very error prone.
Thanks
How does Windows's GUI do it.
Is there an algorithm to knowing when the widget needs to be invalidated?
Generally when you change a property of your widget.
If you look at the standard Swing components they always repaint when methods like setFont(), setBackground(), setText(), setLocation(), setSize() ... are invoked.
I have no idea what your widget does buy you should follow the same concept, that is is you change a property that affects the painted stated of the widget then revalidate() and repaint() it.
it's not really an algorithm at the level of your question.
In the OO world, you will make an object out of the 'widget'
then that 'widget' will be aware of where it is in the world.
then you can check whether any other widget overlaps with it for redraw - or if it has moved etc.
Overview
I'm using a listfield class to display a set of information vertically. Each row of that listfield takes up 2/5th's of the screen height.
As such, when scrolling to the next item (especially when displaying an item partially obscured by the constraints of the screen height), the whole scroll/focus action is very jumpy.
I would like to fix this jumpiness by implementing smooth scrolling between scroll/focus actions. Is this possible with the ListField class?
Example
Below is a screenshot displaying the issue at hand.
(source: perkmobile.com)
Once the user scrolls down to ListFieldTHREE row, this row is "scrolled" into view in a very jumpy manner, no smooth scrolling. I know making the row height smaller will mitigate this issue, but I don't wan to go that way.
Main Question
How do I do smooth scrolling in a ListField?
There isn't an official API way of doing this, as far as I know, but it can probably be fudged through a clever use of NullField(Field.FOCUSABLE), which is how many custom BlackBerry UIs implement forced focus behavior.
One approach would be to derive each "list item" from a class that interlaces focusable NullFields with the visible contents of the list item itself -- this would essentially force the scrolling system to "jump" at smaller intervals rather than the large intervals dictated by the natural divisions between the list items, and would have the side benefit of not modifying the visible positioning of the contents of the list item.
Assuming you want the behavior that the user scrolls down 1 'click' of the trackball, and the next item is then highlighted but instead of an immediate scroll jump you get a smooth scroll to make the new item visible (like in Google's Gmail app for BlackBerry), you'll have to roll your own component.
The basic idea is to subclass VerticalFieldManager, then on a scroll (key off the moveFocus method) you have a separate Thread update a vertical position variable, and invalidate the manager multiple times.
The thread is necessary because if you think about it you're driving an animation off of a user event - the smooth scroll is really an animation on the BlackBerry, as it lasts longer than the event that triggered it.
I've been a bit vague on details, and this isn't a really easy thing to do, so hopefully this helps a bit.
unless you want to override the how the listfield paints or create your own wrapper, you will always have this issue, this is because each line is always visible when scrolling. Try using labelfield instead.