打击“输入”时如何采取行动何时开启“取消” JFileChooser中的按钮? [英] How to act upon hitting "Enter" when on "Cancel" button in JFileChooser?

查看:356
本文介绍了打击“输入”时如何采取行动何时开启“取消” JFileChooser中的按钮?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 JFrame 中有 JFileChooser 。我已将 ActionListener 添加到 JFileChooser ,以便点击时取消按钮有效。我也可以选中取消按钮,但是当我按下Enter键时,没有任何反应(即,没有使用事件命令调用 ActionListener JFileChooser.CANCEL_SELECTION )。我必须对 JFileChooser 做什么才能在取消按钮上点击回车键相当于点击取消按钮?

I have a JFileChooser in a JFrame. I've added an ActionListener to the JFileChooser so that the "Cancel" button works when clicked. I can also tab to the "Cancel" button, but when I then hit the "Enter" key, nothing happens (i.e., the ActionListener isn't called with the event command JFileChooser.CANCEL_SELECTION). What must I do with the JFileChooser so that hitting the "Enter" key when on the "Cancel" button is equivalent to clicking on the "Cancel" button?

以下是我所看到的(错误)行为的一个简单示例:

Here's a simple example of the (mis)behavior I'm seeing:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFileChooser;
import javax.swing.JFrame;

public final class TestApp {
    public static void main(final String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    final JFileChooser chooser = new JFileChooser();
                    chooser.addActionListener(new ActionListener() {
                        public void actionPerformed(final ActionEvent e) {
                            System.exit(0);
                        }
                    });
                    final JFrame frame = new JFrame();
                    frame.add(chooser);
                    frame.pack();
                    frame.setVisible(true);
                }
                catch (final Throwable t) {
                    t.printStackTrace();
                }
            }
        });
    }
}

要查看(错误)行为,请执行程序,选项卡取消,然后单击确定键。该程序不会在我的平台上终止 - 虽然我点击取消按钮时会这样做。

To see the (mis)behavior, execute the program, tab to "Cancel", and then hit the "Enter" key. The program doesn't terminate on my platform -- although it does when I click on the "Cancel" button.

扩展 JFileChooser 并覆盖 cancelSelection()也不起作用(显然,在取消时按Enter键时不调用该函数按钮)。

Extending JFileChooser and overriding cancelSelection() also doesn't work (apparently, that function isn't called when the "Enter" key is hit while on the "Cancel" button).

在使用Java 5,6和7的Fedora 10 x86_64系统上发生(误)行为。

The (mis)behavior occurs on my Fedora 10 x86_64 system with Java 5, 6, and 7.

ADDENDUM:以下内容将 KeyEventPostProcessor 添加到当前的 KeyboardFocusManager ,并且似乎按我的意愿执行:

ADDENDUM: The following adds a KeyEventPostProcessor to the current KeyboardFocusManager and appears to do what I want:

import java.awt.Component;
import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;

public final class TestApp {
    public static void main(final String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    final JFileChooser chooser = new JFileChooser();
                    chooser.addActionListener(new ActionListener() {
                        public void actionPerformed(final ActionEvent e) {
                            System.out.println(e.paramString());
                            System.exit(0);
                        }
                    });
                    final KeyboardFocusManager kfm = KeyboardFocusManager
                            .getCurrentKeyboardFocusManager();
                    kfm.addKeyEventPostProcessor(new KeyEventPostProcessor() {
                        @Override
                        public boolean postProcessKeyEvent(final KeyEvent e) {
                            if (e.getID() == KeyEvent.KEY_RELEASED
                                    && e.getKeyCode() == KeyEvent.VK_ENTER) {
                                final Component comp = e.getComponent();
                                if (chooser.isAncestorOf(comp)) {
                                    if (!(comp instanceof JButton)) {
                                        chooser.approveSelection();
                                    }
                                    else {
                                        final JButton button = (JButton) comp;
                                        if ("Cancel".equals(button.getText())) {
                                            chooser.cancelSelection();
                                        }
                                        else {
                                            chooser.approveSelection();
                                        }
                                    }
                                }
                            }
                            return false;
                        }
                    });
                    final JFrame frame = new JFrame();
                    frame.add(chooser);
                    frame.pack();
                    frame.setVisible(true);
                }
                catch (final Throwable t) {
                    t.printStackTrace();
                }
            }
        });
    }
}

然而,这看似很多工作能够区分点击取消按钮上的输入键与其他任何地方的输入键。

It seems like a lot of work, however, just to be able to distinguish between hitting the enter key on the "Cancel" button versus anywhere else.

你觉得它有什么问题吗?

Do you see any problems with it?

发现解决方案:将GUI外观设置为我的系统(Linux)的原生内容,无需任何其他操作即可实现我想要的功能。这就是我所不知道的以及我在寻找的东西。解决方案是具有以下内容

DISCOVERED SOLUTION: Setting the GUI Look and Feel to the native one for my system (Linux) does what I want without the need for anything else. This is what I was ignorant of and what I was looking for. The solution is to have the following

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

作为 main()的第一个可执行语句方法。然后可以免除所有焦点听众,关键事件处理器等。

as the first executable statement of the main() method. One can then dispense with all focus listeners, key event processors, etc.

我已经向最有帮助的受访者颁发了100分。

I've awarded the 100 points to the most helpful respondent.

推荐答案


程序不会在我的平台上终止。

The program doesn't terminate on my platform.

我看到Mac OS X 10.5,Ubuntu 10和Windows 7上的正常操作使用(各种)Java 5和6.我替换了你的 exit()使用 println()查看事件:

I see normal operation on Mac OS X 10.5, Ubuntu 10 and Windows 7 using (variously) Java 5 and 6. I replaced your exit() with println() to see the event:

System.out.println(rootDirChooser.getSelectedFile().getName() + e.paramString());

指定平台和版本可能会有所帮助;如果可能的话,也要验证安装是否正确。

It may help to specify your platform and version; if possible, verify correct installation as well.

我不确定我理解你的目标;但是,作为替代方案,请考虑覆盖 approveSelection()

I'm not sure I understand your goal; but, as an alternative, consider overriding approveSelection():

private static class MyChooser extends JFileChooser {

    @Override
    public void approveSelection() {
        super.approveSelection();
        System.out.println(this.getSelectedFile().getName());
    }
}

附录:


目标是在取消按钮上点击回车键的操作与单击取消按钮相同。

The goal is to have the action of hitting the "Enter" key while on the "Cancel" button be identical to clicking on the "Cancel" button.

密钥绑定 ,您可以更改与 VK_ENTER 相关联的操作。

KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
InputMap map = chooser.getInputMap(JFileChooser.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
map.put(enter, "cancelSelection");

如果您希望仅在取消按钮具有焦点时才进行更改,则需要在 Focus Listener 中进行此操作

If you want the change to occur only while the "Cancel" button has focus, you'll need to do it in a Focus Listener.

附录:


我找到了一个使用的解决方案 KeyboadFocusManager ,相反。您怎么看?

我可以看到专业人士各方面都有所不同,所以我在下面列出了两个方面。使用 KeyboadFocusManager 查找所有按钮,但不提供区别设置,以区分它们; Focus Listener 方法只能看到批准按钮,并且它是特定于UI的。您仍然可以将这些方法结合起来以获得更好的结果第二种意见不会出现问题。

I can see pros & cons each way, so I've outlined both below. Using KeyboadFocusManager finds all buttons, but offers no locale independent way to distinguish among them; the Focus Listener approach can only see the approve button, and it's UI specific. Still, you might combine the approaches for better results. A second opinion wouldn't be out of order.

附录:

我已更新下面的代码无需知道取消按钮的本地化名称并使用键绑定。

I've updated the code below to eliminate the need to know the localized name of the "Cancel" button and use key bindings.

import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.plaf.metal.MetalFileChooserUI;

public final class FileChooserKeys
    implements ActionListener, FocusListener, PropertyChangeListener {

    private final JFileChooser chooser = new JFileChooser();
    private final MyChooserUI myUI = new MyChooserUI(chooser);
    private final KeyStroke enterKey =
        KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);

    private void create() {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        chooser.addActionListener(this);
        myUI.installUI(chooser);
        myUI.getApproveButton(chooser).addFocusListener(this);
        KeyboardFocusManager focusManager =
            KeyboardFocusManager.getCurrentKeyboardFocusManager();
        focusManager.addPropertyChangeListener(this);

        frame.add(chooser);
        frame.pack();
        frame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(e.paramString());
    }

    @Override
    public void focusGained(FocusEvent e) {
        System.out.println("ApproveButton gained focus.");
    }

    @Override
    public void focusLost(FocusEvent e) {
        System.out.println("ApproveButton lost focus.");
    }

    @Override
    public void propertyChange(PropertyChangeEvent e) {
        Object o = e.getNewValue();
        InputMap map = chooser.getInputMap(
            JFileChooser.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        if (o instanceof JButton) {
            if ("focusOwner".equals(e.getPropertyName())) {
                JButton b = (JButton) o;
                String s = b.getText();
                boolean inApproved = b == myUI.getApproveButton(chooser);
                if (!(s == null || "".equals(s) || inApproved)) {
                    map.put(enterKey, "cancelSelection");
                } else {
                    map.put(enterKey, "approveSelection");
                }
            }
        }
    }

    private static class MyChooserUI extends MetalFileChooserUI {

        public MyChooserUI(JFileChooser b) {
            super(b);
        }

        @Override
        protected JButton getApproveButton(JFileChooser fc) {
            return super.getApproveButton(fc);
        }
    }

    public static void main(final String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new FileChooserKeys().create();
            }
        });
    }
}

这篇关于打击“输入”时如何采取行动何时开启“取消” JFileChooser中的按钮?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆