Is there a way to control menu popup position in JavaFX 8? - java

I am working on custom styling for my application. My current problem stems from the fact that designers specified entirely different styles for menu bar and menu items. I implemented the button style, but menu popup now slightly overlays the button itself (including button label), which is ugly.
Is there some way to control menu popup position relatively to menu bar button? Where is the code that actually positions those popups? I searched through JavaFX source, but javafx.scene.control.Menu class does not handle anything related to context menus - seems that menu logic happens in some entirely different place.

I believe the popups from the menu is done with ContextMenu (the same as right clicking menu). You will also be able to change the location using CSS. You can also use ScenicView and SceneBuilder to extensively debug your GUI and find the appropriate CSS paths (if you are not already doing so).
The relevant css classes can be found here How can I style a JavaFX menu and its items in CSS? and padding and margin can be used to move the context menu.
Check out the default CSS style called Modena. Line 1166 is where the menu stuff starts.
Hope this helps.
UPDATE:
Here is my test:
As it turns out, the context menu pops up at the bottom of the menu button. As far as I know there is no way to MOVE the actual node via CSS.
This means, as it overlaps for you, the menu button is not as big as your menubar, if you make it as big as your menubar (as I did in the picture) it will appear perfectly under the menubar.
As you can see, instead of using padding on the menubar, I use it on the menu buttons. This will automatically resize the menubar and cause the contextmenu to pop up perfectly in place.
I have also removed the color to show you that it is fully transparent if you remove the color.
As you can see here:
-fx-effect: null; also removes the default shadow effect. If you want more extensive control over this, you will need to implement your own menu buttons and your own context menu. Only then, you will have full control.

The actual code for showing the popup is located in MenuButtonSkinBase:
private void show() {
if (!popup.isShowing()) {
popup.show(getSkinnable(), getSkinnable().getPopupSide(), 0, 0);
}
}
Two last parameters to popup.show are X and Y offset of popup. Unfortunately, method is marked as private for some reason, so it is not possible to simply create a subclass of MenuButtonSkin and override that method.
One possible solution is to copy-paste code from MenuButtonSkinBase and MenuButtonSkin into your own file (about 300 lines of code) and tweak the method there. After that, you will be able to do:
menuButton.setSkin(new TweakedMenuButtonSkin(menuButton));

You dont need to copy the whole skin. If you extend the skin you can change this fairly easily (even though the method is private). Just copy paste the following.... (change the position to whatever you want in the "show" method)
#Override
protected void handleControlPropertyChanged(String p) {
if ("SHOWING".equals(p)) {
if (getSkinnable().isShowing()) {
show();
} else {
super.handleControlPropertyChanged(p);
}
} else {
super.handleControlPropertyChanged(p);
}
}
private void show() {
if (!popup.isShowing()) {
popup.show(getSkinnable(), getSkinnable().getPopupSide(), 100, 100);
}
}

Related

JavaFX Color Picker Custom Color In Table Cell

I'm currently using JavaFX ColorPicker to select colors in my application. The ones outside the TableView work as expected, but I've run into an issue with the ones contained in the TableView.
I'm currently using the solution found at Michael Simons's site to implement custom controls in a TableCell. It works fine... until you open the Custom Color dialog of the Color Picker. At this point, any interaction with the custom color dialog box closes and commits the edit, meaning you're unable to, as an example, key in an RGB code for specific color usage.
How do I keep this open until the custom color value is committed from this dialog?
Found a solution; hopefully it can help someone else searching:
The original solution used a change listener to commit the edited table cell:
this.colorPicker.valueProperty().addListener((observable, oldValue, newValue) -> {
if(isEditing()) {
commitEdit(newValue);
}
});
However, the ColorPicker custom color window continuously updates the value as you drag the sliders or target around. As a result, the first time you'd click, the listener would fire and you'd end up out of the dialog.
Changing this to an event listener against the isHiding event fixes this problem. The ColorPicker hides when you select a preset color or when you click [Save] or [Use] in the custom color window. Replace the above snippet with this, and you're good to go!
this.colorPicker.setOnHiding(event -> {
if (isEditing()) {
commitEdit(this.colorPicker.getValue());
}
});

How do I remove the shadow border around a JavaFX ContextMenu?

I've been working on a Button extending class that when left-clicked on displays a stay-open popup menu (ContextMenu object) on a configurable side/corner of the button. The constructor takes an enumerated value like NORTH_LEFT that indicates the side of the button where it gets shown and which edges on both the button and popup are aligned. In other words the 2 should always show in an L shape combo, not a T shape.
So when I want to do something like EAST_BOTTOM where the bottom edges of both button and popup should align, I figured something like this would work:
PopupMenu.show(this, Side.RIGHT, 0, this.getHeight() - PopupMenu.getHeight());
But what I get is a Popup that appears much higher up then it should. That's because the PopupMenu.getHeight() call is returning a larger value then expected. I suspect because it is including the large shadow border in its dimensions. I've noticed that this semi-visible border also extends over my button a bit and prevents mouse clicks from registering on the edge of the button near the menu. So I have multiple reasons to want a border of 0 width.
I assume there is a way to do it via CSS. I've tried setting -fx-background-insets and -fx-padding to 0 but neither seems to make a difference. Any other suggestions?
The solution is to add -fx-effect: null; to your CSS for the ContextMenu. This removes the dropshadow effect that is the modena.css default for ContextMenus. Once I did that I was able to correctly place my menu wherever I needed it to go.
Credit for this working answer goes to José Pereda - we worked it out in the comments above.

How to add custom menu action and titlebar icon to JFrame

I have a custom JFrame. On the title bar I have an icon in the top left, a title, and then the standard minimize, maximize, and close buttons on the right.
When I click the icon in the title bar I get the standard options: Restore, Move, Size, Minimize, Maximize, Close.
How can I add my own menu option here? I'd like to add and "Always On Top" option here.
Additionally I'd like to add a button next to the max,min,close buttons on the title bar to allow uses to toggle the "Always On Top" state of the JFrame.
You could create your own customized Components. To do that, create a new class which extends JMenuBar for example and override the methods which fit your needs. Very often, for example, one wants to override paintComponent(Graphics).
That is not what you want, 'though. Customizing the JMenuBar wont work as you expect it to. The "JMenuBar" is another bar below the title bar. I am Mac user, but as far as my knowledge goes, it is not possible to customize the title bar, because that isn't handled by the JVM. The only thing that is modifiable without using native code is the Icon in the top left.
For further information on that, look at this question and the best answer there. This will help you a lot.
Your problem (adding a button at the top for toggling the alwaysOnTop status) is best solved by creating normal instances of a JMenuBar, a JMenu and a JMenuItem.
To then add that MenuBar to your Frame, use JFrame.setJMenuBar(JMenuBar). See also How to use Menus.
I hope this helps!

Java Open a JFrame relative to the position of a button (menu like behaviour)

I am trying to implement expand functionality like in below example, however instead of a menu I am using a JFrame which contains more sophisticated GUI elements.
The problem I run into is that if I move the parent window which contains the button below which the frame should appear, I can not adjust my custom JFrame to open each time relative to the position of that button
initially I simply used
myCustomFrame.setLocation(myButton.getX(), (myButton.getY() + 73));
but this obviously doesn't work if I change move the parent window
After that I tried
myCustomFrame.setLocationRelativeTo(myButton);
but in this case it appears at the top of the button... I adjust the position for a particular case, but this is not a solution.
So I am trying to get the same behavior as menus have, such that the position of the JFrame is automatically adjusted.
Does anyone have any suggestions?
Have you considered using myButton.getLocationOnScreen()? That way no matter where you move the jFrame containing the button you will always get the Point of your button measured from the top left corner of the screen.
You could alter your original method something like this:
myCustomFrame.setLocation(myButton.getLocationOnScreen().x, (myButton.getLocationOnScreen().y + 73));

How to remove GWT menubar on Screen click?

I am a beginner using GWT. I have a menubar which pops-up on a Label click. I need to remove it when the user clicks anywhere on screen except the Label which caused it to display (Legal) I tried various methods like hooking up this event on
RootPanel.get().addDomHandler(clickDetectHandler, ClickEvent.getType());
public void onClick(ClickEvent event) {
Object source = event.getSource();
if (!(source instanceof MenuBar))
panel.remove(menu);
I even tried using the MouseOutEvent but it doesn't detect click. I am able to remove it on a click back to the legal label. But I need it to be removed on detecting a click on the screen. Please advise.
GWT has a panel called PopupPanel which automatically handles exactly the behaviour that you want.
Quoting from the javadoc:
"PopupPanel's constructor takes 'auto-hide' as its boolean parameter.
If this is set, the panel closes itself automatically when the user clicks outside of it."
Is it possible to have the pop-up menu display inside of a PopupPanel?
http://google-web-toolkit.googlecode.com/svn/javadoc/2.5/com/google/gwt/user/client/ui/PopupPanel.html
Have a look at this GWT sample. This seems to have the behaviour you describe. It comes with source code.
Alternatively you can try handling the blur event on the menu widget.

Categories