如何禁用文本字段的默认上下文菜单

6
默认情况下,JavaFX的TextField带有内置的ContextMenu,其中包括“撤销”、“复制”、“剪切”等选项。当将ComboBox设置为可编辑时(实际上ComboBoxTextField的一部分),它也具有相同的ContextMenu
我想用自定义的ContextMenu替换默认的ContextMenu,但我在禁用默认ContextMenu方面遇到了问题。
我尝试消耗ContextMenu和鼠标单击事件,但是ComboBoxComboBox.getEditor()都具有空的ContextMenu
我是否漏掉了什么?
3个回答

7
我找到了一种方法来禁用默认的弹出菜单。这样,您就可以添加自己的菜单,而不会出现双重菜单效果。
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);
    }
});

注意 - 我不是通过组合框上的菜单添加我的自定义菜单,我不确定那样做是否有效(可能有效)。

如果您将组合框包装在Hbox中,并向Hbox添加菜单 - 我知道那样会有效。

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());
    }
});

对我来说没有用,至少不适用于TextField。你可以添加这段代码,但也要注意事件会多次触发(我猜测是在鼠标按下、释放等操作时)。无论如何,上下文菜单仍然会弹出。 - RDM

2
正如您已经说明的那样,调用GetContextMenu()返回null(这是默认上下文菜单是实现细节的重要线索),如果您添加其他ContextMenu,它将出现在默认上下文菜单之上。
尝试使用以下代码替换上下文菜单:
ContextMenu cm = new ContextMenu();
cm.getItems().add(new MenuItem("Test"));

textbox.setContextMenu(cm);

产生以下结果。 enter image description here 重写鼠标点击事件也不起作用,因为您仍然需要通过某个属性访问默认上下文菜单,这似乎是不可能的。
我还检查了CSS参考,以查看ContextMenu是否可以通过其中一个控件子结构进行定位,但同样没有返回结果。
基于这些信息,看起来默认的ContextMenu是TextField控件(或者可能是其父类TextInputControl)的实现细节,目前无法更改。
更新
我联系了Jonathan Giles(JavaFX UI控件团队的技术负责人),他告诉我要提交错误报告。
我搜索了错误数据库,并找到了一些现有的报告(RT-23213和RT-24823),因此这似乎是一个已知问题。截至今天,该问题仍然未解决,被认为是中等优先级,但显然将在FX 8.0中修复。
从错误报告注释中:
默认上下文菜单是由控件的皮肤创建的,它目前不是公共API。我们需要决定何时以及何时通过公共API访问上下文菜单,但它可能需要等待使皮肤更加公开的广泛工作。

是的,看起来我们对此无能为力。 - Chechulin
至少在下一个版本发布之前。 - Benjamin Gale
14而且错误仍未修复。 - ITurchenko
看起来在8u45版本中仍然存在问题。 - davidrmcharles
1
如果想要完全禁用上下文菜单,可以将上下文菜单设置为空的新ContextMenu来实现:field.setContextMenu(new ContextMenu()); - pulse0ne

0

希望能对你有所帮助,我曾经遇到过内置上下文菜单的EditText问题,这个方法对我很有效。

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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接