Javafx: setting a Tab mnemonics - tabs

Quick question: Is it possible to set a mnemonic for a JavaFX Tab?
I can only seem to be able to set them for such controls as buttons, and menu items.

Okay, this is an interesting question! You are right, you can not set the mnemonic directly on a Tab. But you can add a component as a Tabs graphic that supports the mnemonic feature:
private class MTab extends Tab
{
public MTab(String pText)
{
super();
Button fakeLabel = new Button(pText);
fakeLabel.setMnemonicParsing(true);
fakeLabel.getStyleClass().clear();
setGraphic(fakeLabel);
fakeLabel.setOnAction(ev -> {
if (getTabPane() != null) {
getTabPane().getSelectionModel().select(this);
}
});
}
}
Using this tab:
TabPane tabs = new TabPane();
tabs.getTabs().add(new MTab("_this is a test"));
tabs.getTabs().add(new MTab("t_his is a test"));
tabs.getTabs().add(new MTab("th_is is a test"));
Will make your tabs switchable via shortcuts.

Related

Make JavaFX Button visually appear to be clicked on right click

I converted some old Java Swing code to JavaFX. The JavaFX code had explicit doClick() for the right mouse button calls:
myButton.addMouseListener(new MouseAdapter() {
#Override
public final void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
// ...
}
else if (SwingUtilities.isRightMouseButton(e)) {
// ...
myButton.doClick();
}
}
});
Left clicks make the button visually appear to be clicked in Java Swing. However right clicks do not visually do this without adding myButton.doClick()
I am seeing the same visual behavior in JavaFX and I want right clicks to visually make the button look clicked. Below is my JavaFX code:
myButton.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(final MouseEvent event) {
if (event.getButton() == MouseButton.PRIMARY) {
// ...
}
else if (event.getButton() == MouseButton.SECONDARY) {
// ...
}
}
});
What do I have to add to make right clicks visually click myButton?
That visual appearance of button click is usually referred as "armed" pseudo state. So you can turn on/off the armed pseudo state of the button when doing right button pressed&released.
Something like..
myButton.setOnMousePressed(e->{
if(e.getButton()== MouseButton.SECONDARY){
myButton.pseudoClassStateChanged(PseudoClass.getPseudoClass("armed"), true);
}
});
myButton.setOnMouseReleased(e->{
if(e.getButton()== MouseButton.SECONDARY){
myButton.pseudoClassStateChanged(PseudoClass.getPseudoClass("armed"), false);
}
});
Updating the :armed pseudo class is not enough if you want the Button's action to be fired by a right click. You actually need to arm the Button. In other words, you need to make the armed property change to true. Also, updating the armed property will update the pseudo class for you.
As the armed property is read-only, you can't set it directly; you need to call arm() and disarm(). You may also need to manually call fire() (expanded on below). Here's an example:
Button button = new Button("Click Me!");
button.setOnAction(event -> System.out.println("Button clicked!"));
button.setOnMousePressed(event -> {
if (event.getButton() == MouseButton.SECONDARY) {
button.arm();
}
});
button.setOnMouseReleased(event -> {
if (button.isArmed()) {
button.disarm();
button.fire();
}
});
However, you don't appear to need the onMouseReleased handler at all—at least in JavaFX 11 and 12, using the default Button's skin/behavior. The Button's behavior class will fire the action if said Button is armed at the time the mouse is released (and no keys are down). Note that the default behavior class does a more complex check regarding which MouseButton was used (i.e. it does more then just check event.getButton() == MouseButton.PRIMARY). You can see the implementation for yourself here.
All that said, if you only want the visuals to change then you should use the approach shown in Sai's answer.

How can I make the AppBar on Windows phone disappears/appear programmatically?

On Windows phone, I can declare App bar in my page like this:
<Page.BottomAppBar>
<CommandBar>
..
</CommandBar>
</Page.BottomAppBar>
My question is how can I programmatically make that app bar disappear and reappear?
Thank you.
Hence IsOpen property opens/closes the AppBar (shows/hides secondary menu and labels), to hide completely the AppBar, I'm just seting BottomAppBar property to null just after remembering the old bar in variable. Then when I want to return my AppBar, I use that variable, sample code:
CommandBar previousBar;
private void HideBar()
{
previousBar = BottomAppBar as CommandBar;
BottomAppBar = null;
}
private void ShowBar()
{
BottomAppBar = previousBar;
}
You can open and close the app bar programmatically by setting the IsOpen property. You can respond to the app bar being opened or closed by handling the Opened and Closed events.
if (this.BottomAppBar != null)
{
this.BottomAppBar.IsOpen = true;
}

How to create customize title bar with close button on jFrame?

I want to create a customised title bar for my JFrame. I can remove the default title bar with
JFrame.setUndecorated(true)
Now i need to create a customised title bar for my JFrame with a close button?
Without having done that ever, I think I would go this way:
Indeed set the JFrame to undecorated
Extend JRootPane to add an additional field titleBar
Create a TitleBar component holding the title, the close button, etc...
Set a new LayoutManager on that JRootPane (have a look at JRootPane.RootLayout) and layout the components in the appropriate order (first the title bar, then below the menubar, then below the content pane)
Set an instance of that extends RootPane on your JFrame
There are maybe better ways.
I'm not quite sure of how you want to customize the close button, but maybe this can point you in the right direction: How can I customize the title bar on JFrame?
EDIT: Here's an updated working link to a forum about customizing his GUI and one user posted code on his creation of a simple GUI: Here
It looks like you can just modify his removeComponents method and create an addComponents method to fit your needs.
The Code According to the Above Link :
(Edited for Java 8)
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
class Testing {
public void buildGUI() throws UnsupportedLookAndFeelException {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame f = new JFrame();
f.setResizable(false);
removeMinMaxClose(f);
JPanel p = new JPanel(new GridBagLayout());
JButton btn = new JButton("Exit");
p.add(btn, new GridBagConstraints());
f.getContentPane().add(p);
f.setSize(400, 300);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
btn.addActionListener((ActionEvent ae) -> {
System.exit(0);
});
}
public void removeMinMaxClose(Component comp) {
if (comp instanceof AbstractButton) {
comp.getParent().remove(comp);
}
if (comp instanceof Container) {
Component[] comps = ((Container) comp).getComponents();
for (int x = 0, y = comps.length; x < y; x++) {
removeMinMaxClose(comps[x]);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
new Testing().buildGUI();
} catch (UnsupportedLookAndFeelException ex) {
Logger.getLogger(Testing.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
}
may Work Fine but what if user also Want to set a L&F
such as nimbus
There are really three ways to approach this:
Set the frame to undecorated and implement everything, which includes control buttons, snapping, resizing and moving.
Get the root pane of the JFrame and directly edit that pane. You will need to add the control buttons and the snapping behaviour.
Use JNI to get the window's handle at the creation of a JFrame to get the control of it's attributes. This is better explained in this post. I have also built a little project which is basically an extension of the JFrame class that handles everything that needs to be dealt with... This last approach does not break native functions like snapping and resizing. But you do need to create the control buttons again since you have a new title bar if you want to build it from scratch.

How to add a JPopupMenu to a JMenuBar?

I have an application with a popup menu. I'd like to use the popup in the usual way (i.e., it should appear when the user right-clicks anywhere in the window), but I'd also like to attach it to the main MenuBar at the top of the window. I'm not sure how to do this.
I'd thought it would as simple as calling
myJMenuBar.add(myPopupMenu)
but this doesn't work.
JMenuBar.add() wants a JMenu parameter, not a JPopupMenu.
Does anyone have any suggestions?
Instead of trying to reuse the JPopupMenu object, the best approach would be to encapsulate the actions that the menus perform, and reuse those. The popup would trigger those actions, as would the menu items.
From the Action JavaDoc:
In addition to the actionPerformed method defined by the ActionListener interface, this interface allows the application to define, in a single place:
One or more text strings that describe the function. These strings can be used, for example, to display the flyover text for a button or to set the text in a menu item.
One or more icons that depict the function. These icons can be used for the images in a menu control, or for composite entries in a more sophisticated user interface.
The enabled/disabled state of the functionality. Instead of having to separately disable the menu item and the toolbar button, the application can disable the function that implements this interface. All components which are registered as listeners for the state change then know to disable event generation for that item and to modify the display accordingly.
and
JPopupMenu, JToolBar and JMenu all provide convenience methods for creating a component and setting the Action on the corresponding component. Refer to each of these classes for more information.
I had the same issue. A right-mouse-click as well as a top menu with exactly the same (complicated) set of menu items. The 'Action' class is something to consider if you are talking about enablement choices, but it's not dealing with visibility and in my case there was also a dynamic list of entries based on a current selection that I wanted to reuse.
So I ended up implementing a 'Bridge' design pattern (I think) for the methods I actually use (add() and addSeparator()):
public static class MenuBridge
{
private JPopupMenu popupMenu;
private JMenu menu;
public MenuBridge(JPopupMenu popupMenu)
{
this.popupMenu = popupMenu;
}
public MenuBridge(JMenu menu)
{
this.menu = menu;
}
public void addSeparator()
{
if(popupMenu!=null) popupMenu.addSeparator();
else menu.addSeparator();
}
public void add(JMenuItem item)
{
if(popupMenu!=null) popupMenu.add(item);
else menu.add(item);
}
}
So then I can write a reusable method that computes the menu items and synchronize my right mouse click with the top-level menu:
public void addTaskMenuItems(DefaultMenu menu, List<MDProcTask> taskList)
{
...
menu.add()/menu.addSeparator()
...
}
addTaskMenuItems(new DefaultMenu(popupMenu),taskList);
...
taskMenu.addMenuListener( new MenuListener() {
public void menuCanceled(MenuEvent menuevent)
{
}
public void menuDeselected(MenuEvent menuevent)
{
}
public void menuSelected(MenuEvent menuevent)
{
taskMenu.removeAll();
addTaskMenuItems( new DefaultMenu(taskMenu),getSelectedTasks());
taskMenu.revalidate();
}});

How to prevent JPopUpMenu disappearing when checking checkboxes in it?

I want to use JCheckBoxMenuItems in a JPopupMenu. It works, but the problem is that the popup menu disappears when a checkbox item has been checked or unchecked. So if one wants to check/uncheck several items, the popup needs to be launched repeatedly, which is irritating.
Curiously, if I use just plain JCheckBox items in the menu (instead of JCheckBoxMenuItems), the behavior is just as it should be: the popup stays there and the checkboxes can be checked/unchecked. Once done, the popup can be closed just by clicking outside it.
How do I make the popup to behave like that when the items there are JCheckBoxMenuItems? I would prefer using JCheckBoxMenuItems because of their looks.
Well, found working answer from http://forums.sun.com/thread.jspa?threadID=5432911. Basically, create a custom UI:
public class StayOpenCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI {
#Override
protected void doClick(MenuSelectionManager msm) {
menuItem.doClick(0);
}
public static ComponentUI createUI(JComponent c) {
return new StayOpenCheckBoxMenuItemUI();
}
}
And set it in the JCheckBoxMenuItem:
myJCheckBoxMenuItem.setUI(new StayOpenCheckBoxMenuItemUI());
Don't know if this is the most elegant possible solution, but works perfectly.
I ran into an issue with the nice Joonas Pulakka's answer because the "UIManager lookandFeel" was ignored.
I found the nice trick below on http://tips4java.wordpress.com/2010/09/12/keeping-menus-open/
The point is to reopen immediatly the menu after it has been closed, it's invisible and keep the application look and feel and behavior.
public class StayOpenCBItem extends JCheckBoxMenuItem {
private static MenuElement[] path;
{
getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (getModel().isArmed() && isShowing()) {
path = MenuSelectionManager.defaultManager().getSelectedPath();
}
}
});
}
public StayOpenCBItem(String text) {
super(text);
}
#Override
public void doClick(int pressTime) {
super.doClick(pressTime);
MenuSelectionManager.defaultManager().setSelectedPath(path);
}
}
I found a much easier solution for this problem
JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem("sample");
menuItem.putClientProperty("CheckBoxMenuItem.doNotCloseOnMouseClick", Boolean.TRUE);
I found this solution while reading the code from
BasicMenuItemUI.doNotCloseOnMouseClick()