Resizing JPopupMenu and avoiding a "flicker" issue - java

I am trying to implement a search results popup list similar to the style found here:
http://www.inquisitorx.com/
(I'm not trying to implement a Google search, I'm just using this as a rough example of the style I'm working on.)
In any event, I am implementing this by using a JList contained within a JPopupMenu which is popped up underneath a JTextField.
When a user enters search terms, the list changes to reflect different matching results. I then call pack on the JPopupMenu to resize it.
This works, however, it creates a slight flicker effect since it is actually hiding the popup and showing a popup. (See the private method getPopup in JPopupMenu where it explicitly does this.)
Is there any way to just get it to just resize itself (aside from using a JWindow)?

to me work :
popup.pack();
popup.validate();
this work in linux with java version "1.6.0_34". I don't know is that work on windows.

The setSize() method didn't work in my case. The popup.pack() approach did work, but also resulted in a flicker. The best solution that I have found was the one found here. In short:
Window window = SwingUtilities.getWindowAncestor(popupMenu);
window.pack();
window.validate();

Have you tried setSize()? It looks like that gets handled in JComponent and might avoid the repaint issues.
I think the issue that getPopup is addressing is what to do when the dimensions of the popup will not fit within the window. When that happens, it drops back from a lightweight component to a heavyweight and that definitely requires a hide and show. So, I think if you can guarantee your popup won't extend beyond the window the setSize might do the trick.

Related

Block Swing pop-up from losing focus and closing

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.

.pack() causes the components to be in the wrong place but works after window resize

I am creating a game in java using Swing.
I am using
mainJFrame.setExtendedState(mainJFrame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
on my JFrame to start it as a maximized window.
After this I am using
mainJFrame.pack();
to be able to get the correct x & y coordinates of components in the GUI. I need those coordinates since i'm painting custom images to the GUI. So far everything is fine.
When a user has passed a level, i rebuild the GUI to updated it to the new level settings and then i call pack() again.
When calling pack() the components are placed in the wrong place, slightly below where they are supposed to be.
However, manually resizing the window causes the components to go to the right place again.
I have tried calling mainJFrame.revalidate() and mainJFrame.repaint() after the pack() but this gives no effect.
If needed I can supply printscreens and code.
Thanks for your time.
Manually resizing the window validates the enclosing container and all of its subcomponents. To avoid the effect you describe, call setVisible() only after you have added components and invoked pack(). More related suggestions may be found here. If the problem persists, please edit your question to include an mcve that exhibits the problem.

Javafx popup won't hide behind other application upon losing focus

So my question, as stated (sort of) in the title, is about the behaviour in some respects of the Javafx (namely 2.2) Popup. Most of the time, you get a popup, and you give it a window to act as it's parent, you give it some scene, and it tends to act relatively independently.
This is all fine, however, in my case, I needed a popup that would anchor itself to a particular stage (window), at a particular location, when an event happened. That popup would then, in turn, disappear when the window disappeared (minimize, off screen, whatever), moved when it would, and in all essence and functionality, be a physical extension of the window, just with a custom shape.
Now of course, there are a lot of nuances with that, and everything for the most part, works great. The only thing I can't seem to figure out is that normally in a platform like Windows 7 64 bit, say. You open two programs, alright. Then if the programs are overlapping a little bit, whichever has focus gets to have the entire program displayed, whereas the other one gives the impression of being 'behind' the other window. (Whether or not windows actually renders application graphics 'behind' a window when another has focus on the same spot, I'm not sure.). Normally, javafx also supports this functionality just fine. But for some reason, The Popup class in javafx (see docs here) doesn't do that. It's always on top of whatever it's displayed with, without exception. For the point of completeness, here's my pretty straightforward popup code (at least the part pertaining to showing it and it's properties):
Popup myPop = new Popup();
//************************Popup Property Setter**************************
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
myPop.setWidth(width);
myPop.setHeight(initialHeight);
myPop.setAutoHide(false);
myPop.setAutoFix(false);
myPop.setHideOnEscape(false);
myPop.setX(xLocation);
myPop.setY(yLocation);
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//**********************end of Popup Properties**************************
myPop.getContent().add(main_anchor);
myPop.show(FileChooserWindow.get_stage());
main anchor has some various components i include inside of the 'myPop' popup, and FileChooserWindow is a non-null parent window that will be open at the time of this method calling without exception.
Here is a screenshot as well of the behaviour I'm referring to. Notice the highlighted text in the pdf, that is where my cursor currently has focus. Also, the window that the popup is anchored to can be seen in the back of the pdf poking out from the left.
Any help you guys can give would be much appreciated. I really hope I don't have to check for active processes and their location relative to the popup, that's getting dangerously close to my knowledge border, and sounds like a total PITA.
So, after toying with this for a few more days, I have a rough workaround, although it is a hack in the full meaning of the term.
Although the popup behaviour is still mystifying me, I can simulate a fix in this behaviour by adding a changeListener to the stage to which it is attached (since I didn't want the popup to close if it's parent window had focus, only if anything BUT the popup and it's parent got focus).
See code as follows:
FileChooserWindow.get_stage().focusedProperty().addListener(new ChangeListener<Boolean>(){
#Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) {
if (!newValue){
if(AutogenPopup.popupReturner().focusedProperty().get()){
AutogenPopup.popupReturner().hide();
}
}else{
if(FileChooserController.refreshAutoPopup && FileChooserController.autoGen_flag){
AutogenPopup.popupReturner().show(FileChooserWindow.get_stage());
}
}
}
});
never mind some of those flags that I'm checking against, they are simply some internal tools to make sure that the popup only appears when the program is in the proper state.
Now, one interesting thing to note. The AutogenPopup.popupReturner().focusedProperty().get()
Seemed to be returning true when the popup's parent window LOST focus. Which is quite counter-intuitive to me, and in my opinion, is even a touch buggy. Now, this does not simulate the behaviour of a modern operating system where a window can slide in and out of focus incrementally, since the popup will just completely disappear upon it's parent window losing focus. But seeing as how my popup just displays additional text entry on the side of the main window, this is an acceptable compromise until I think of a better solution. (Perhaps the better solution is not to use a popup at all, and instead skin a window to act in a popup-y fashion).
Anyway, I hope this helps someone, maybe eventually there will be a more fine-grained way to control this popup functionality.

Should i redraw the GUI after change?

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).

Custom Java Window Title Bar Menu

I'm trying to allow the user to change the title of a window in Java without adding components to the window itself. I'm actually trying this with a JInternalFrame, but figure the solution should be similar for a JFrame. I simply want to add an additional menu item in the context menu that pops up when right clicking on a window title bar. For example, the Set title below:
This example is on Windows XP, but perhaps there's a way to get the window context menu OS independently perhaps similar to the SystemTray.getSystemTray() (but for individual windows within an application). From this I would be able to provide my own ActionListener to popup a dialog for the user to enter a new title.
Is this a much bigger task than I'm guessing it is? Does anyone have solutions they've used before?
Short answer: I don't think this is easy. I'm not 100% sure if it is possible.
First, JFrame and JInternalFrame are actually quite different. JFrame is a top level component whose title bar and such are typically provided by the OS. JInternalFrame's entire content (including title bar) is provided by the Swing LAF.
For a JInternalFrame, the context menu is provided by the LAF, not JInternalFrame itself. You would have to do something with the UIComponent in order to change the context menu. I think you would likely have to provide a custom UI component in order to do this, which is ugly and typically breaks across different LAFs or works but looks terrible at best. See BasicInternalFrameTitlePane, the createSystemMenu method.
I don't think this is possible without digging way too deep into Swing's internal UI system and I wouldn't even consider doing this. Why don't you use the inbuilt JMenuBar of JInternalFrame?
myInternalFrame.setJMenuBar(myMenuBar);

Categories

Resources