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.
Related
I'm developing a plugin for IntelliJ IDEA, which obviously uses Swing.
For a feature I have introduced I'd like to stop a JPopupMenu which uses JCheckBoxMenuItems from losing focus and closing.
You can see it in action.
I've debugged the code, but I couldn't figure out how to do it, also being I'm not that into Swing.
Could you maybe point me to useful listeners/blocks of code/ways to prevent this?
If you want to see code, the IntelliJ classes are
ActionPopupMenuImpl.MyMenu
ActionMenuItem
Edit: a better way need to be found as the uiRefreshed event isn't always called at the right time.
Just coordinate your code in a good way ;)
The Swing mechanism in IDEA is too complicated, and maybe it's better to not touch it. Just know that the mouse events are handled by a special listener and then redirected to Component(s).
That said, having an hold on the menu ActionButton. You can listen for the Lookup's uiRefreshed event and programmatically:
myMenuButton.click()
That's all.
You need to call it after the UI has been refreshed because the LookupUi might have changed in dimension or location.
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).
When creating an MDI Swing GUI, I have a number of JInternalFrames that are added to a JDesktopPane in a JFrame. I make these internal frames invisible by adding setVisible(false) in the constructor, after the initComponents method (as the GUI builder automatically sets these frames visible in this method).
At runtime, the user can choose to open and close the JInternalFrames by invoking listeners that call setVisible(true) and setVisible(false), depending on the current state of the frames. I like how the previous position and state of an internal frame remains intact using this design. However, something tells me this must be terribly wrong, even though I haven't seen any drawbacks yet.
So, my question is: is this poor design?
In the context of a Multiple Document Interface (MDI), this approach is quite reasonable. In addition, you can use the JInternalFrame method setSelected() to highlight a particular frame. To ease navigation, this and other methods can be used in Action, as shown here.
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 am interested in creating a new widget similar to the JSlider widget, but with a "ghost" (translucent) knob displaying the previous slider position, as well as adding a trails-like animation to the real knob's movement.
I am a bit confused on the proper way of extending a Java Swing widget to add new functionality.
As I see it I have a few options:
1) Extend JSlider, place all my new model information here, and overwrite paint to first draw the JSlider, and than to overlay my desired additions. The problem with this solution is I would need to use trial and error to get the marks in the correct position (as I won't have access to full geometrical information) which will could make it not work in all situations.
2) Extend various classes of the Slider widget (JSlider, SliderUI, BasicSliderUI, MetalSliderUI, BoundedRangeModel, DefaultBoundedRangeModel). The advantage I see here is maintaining the proper model-view-controller architecture. However, this will require overloading various functions within the classes. I believe the result would seem very hacked together.
3) Copying all of the Slider widget's code, and modifying to create my new widget. This would be similar to options (2), but may be a bit simpler to modify code then to extend functions (which will be basically copying/modifying code anyways).
4) Re-create the slider widget from scratch with my desired functionality. After looking at the existing Swing Slider widget's code, this is not a trivial task.
Am I missing some more elegant method of creating a new widget that borrows functionality from an existing one?
Thank you for your insight.
I would choose 2) with some changes
Create WrapperSliderUI class which delegates all the methods calls to the delegate UI. And override just paint method.
SetUI of your JSlider should wrap original UI in the WrapperSliderUI
public void setUI(SliderUI ui) {
super.setUI(new WrapperSliderUI(ui));
}
The in the paint you will check original UI class and adapt your painting accordingly.