How to disable the default context menu on a text field
Asked Answered
D

3

6

By default the JavaFX TextField has a built in ContextMenu with 'undo', 'copy', 'cut' etc. options. The ComboBox also has the same ContextMenu when it is set as editable (the ComboBox is actually part of the editor which is a TextField).

I want to replace this ContextMenu with a custom one but I'm having a problem with disabling the default one.

I have tried consuming the ContextMenu and mouse click events but ComboBox and ComboBox.getEditor() both have a null ContextMenu.

Am I missing something?

Divergent answered 26/11, 2012 at 10:17 Comment(0)
B
2

As you have already stated, a call to GetContextMenu() returns null (which is the big clue the default one is an implementation detail) and if you add an additional ContextMenu it appears over the default one.

Trying to replace the context menu with the following code:

ContextMenu cm = new ContextMenu();
cm.getItems().add(new MenuItem("Test"));

textbox.setContextMenu(cm);

Produces the following result.

enter image description here

Overriding the mouse clicked event isn't going to work either because you will still need to access the default Context menu via some property which doesn't seem to be possible.

I've also checked the CSS reference to see if the ContextMenu was target-able via one of the controls sub-structures but again this returned no results.

Based on this information it looks as though the default ContextMenu is an implementation detail of the TextField control (or maybe it's parent classTextInputControl) and can't currently be changed.

Update

I contacted Jonathan Giles (the tech lead at Oracle in the JavaFX UI controls team) who told me to file a bug report.

I searched the bug database and have found some existing reports (RT-23213 & RT-24823) so it appears this is a known issue. As of today the issue is still open and is considered a medium priority but apparently it will be fixed for FX 8.0.

From the bug report comments:

The default context menu is created by the control's skin, which is currently not public API. We need to decide if and when the context menu should be accessible through the public API, but it will probably need to wait for the broader work to make skins more public.

Brenan answered 26/11, 2012 at 23:21 Comment(5)
yep, looks like there is nothing we can do with it.Divergent
At least until the next release.Brenan
'14 and bug is still not fixedCinchona
Looks like it is still broken in 8u45.Sedgewinn
In the case of wanting to completely disable the context menu, I've had success with setting the context menu to a new, empty ContextMenu: field.setContextMenu(new ContextMenu());Pimbley
A
7

I have found a way to disable the default popup menu. Then you can add your own, without getting the double menu effect.

ComboBox<String> cb_ = new ComboBox<>();
final EventDispatcher initial = cb_.getEditor().getEventDispatcher();
cb_.getEditor().setEventDispatcher(new EventDispatcher()
{
    @Override
    public Event dispatchEvent(Event event, EventDispatchChain tail)
    {
        if (event instanceof MouseEvent)
        {
            //shot in the dark guess for OSX, might not work
            MouseEvent mouseEvent = (MouseEvent)event;
            if (mouseEvent.getButton() == MouseButton.SECONDARY || 
                    (mouseEvent.getButton() == MouseButton.PRIMARY && mouseEvent.isControlDown()))  
            {
                event.consume();
            }
        }
        return initial.dispatchEvent(event, tail);
    }
});

Note - I'm not adding my own menu via the menus on the combobox, I'm not sure if that will work (it might).

If you wrap the combobox in an Hbox, and add a menu to the hbox - I know that will work.

HBox hbox = new HBox();
ContextMenu contextMenu = new ContextMenu();
....
hbox.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>()
{
    @Override
    public void handle(ContextMenuEvent event)
    {
        contextMenu.show(hbox, event.getScreenX(), event.getScreenY());
    }
});
Atomy answered 13/3, 2013 at 5:49 Comment(1)
Did not work for me, not on a TextField at least. You can add this code, but also be aware that the event fires multiple times (I would guess on mouse pressed, mouse released and what have you). Either way, the context menu still popped up.Animism
B
2

As you have already stated, a call to GetContextMenu() returns null (which is the big clue the default one is an implementation detail) and if you add an additional ContextMenu it appears over the default one.

Trying to replace the context menu with the following code:

ContextMenu cm = new ContextMenu();
cm.getItems().add(new MenuItem("Test"));

textbox.setContextMenu(cm);

Produces the following result.

enter image description here

Overriding the mouse clicked event isn't going to work either because you will still need to access the default Context menu via some property which doesn't seem to be possible.

I've also checked the CSS reference to see if the ContextMenu was target-able via one of the controls sub-structures but again this returned no results.

Based on this information it looks as though the default ContextMenu is an implementation detail of the TextField control (or maybe it's parent classTextInputControl) and can't currently be changed.

Update

I contacted Jonathan Giles (the tech lead at Oracle in the JavaFX UI controls team) who told me to file a bug report.

I searched the bug database and have found some existing reports (RT-23213 & RT-24823) so it appears this is a known issue. As of today the issue is still open and is considered a medium priority but apparently it will be fixed for FX 8.0.

From the bug report comments:

The default context menu is created by the control's skin, which is currently not public API. We need to decide if and when the context menu should be accessible through the public API, but it will probably need to wait for the broader work to make skins more public.

Brenan answered 26/11, 2012 at 23:21 Comment(5)
yep, looks like there is nothing we can do with it.Divergent
At least until the next release.Brenan
'14 and bug is still not fixedCinchona
Looks like it is still broken in 8u45.Sedgewinn
In the case of wanting to completely disable the context menu, I've had success with setting the context menu to a new, empty ContextMenu: field.setContextMenu(new ContextMenu());Pimbley
L
0

i hope it would help, i had the same problem with editText built in context menu and this worked for me..

EditText et; ImageView iv;

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    et=(EditText) findViewById(R.id.et1);
    iv=(ImageView) findViewById(R.id.iv1);

    registerForContextMenu(et);
    registerForContextMenu(iv);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) 
{
    menu.clear();
    if(v==et)
        getMenuInflater().inflate(R.menu.editmemu, menu);
    if(v==iv)
        getMenuInflater().inflate(R.menu.imagemenu, menu);super.onCreateContextMenu(menu, v, menuInfo);
}
Landman answered 8/2, 2015 at 18:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.