gpt4 book ai didi

java - 全屏Swing组件无法在Mac OS X Mountain Lion上的Java 7上接收键盘输入

转载 作者:行者123 更新时间:2023-12-03 02:37:11 27 4
gpt4 key购买 nike

更新12/21:

7u10是最近发布的。确认:

  • 问题仍然存在
  • 幸运的是,解决方法仍然有效!

  • 更新11/7:

    我们有一个解决方法!

    Leonid Romanov from Oracle on the openjdk.java.net mailing list provided some insight as to what's going on:

    Well, although I'm not 100% sure yet, but it looks like when we enter full screen some other window becomes the first responder, hence the beep. Could you please try the following workaround: after calling setFullScreenWindow() on a frame, call setVisible(false) followed by setVisible(true). This, in theory, should restore the correct first responder.



    似乎有效的代码片段很简单:
    dev.setFullScreenWindow(f);
    f.setVisible(false);
    f.setVisible(true);

    我已经更新了示例代码,可以打开和关闭此修复程序。每次窗口进入全屏模式时都需要它。

    在更复杂的应用程序的更大范围内,我仍然遇到全屏窗口内子组件的键盘焦点问题,单击鼠标会导致我的窗口失去焦点。 (我想它会转到上面引用的不希望有的第一响应者窗口。)当我有更多关于此案例的信息时,我会报告给我-我现在无法在较小的样本中进行复制。

    更新10/31:

    对示例代码的主要更新:
  • 包括在全屏独占模式和Lion风格的全屏模式之间切换
  • 侦听KeyboardFocusManager以显示当前关注的组件
  • 的层次结构
  • 同时使用输入映射和KeyListener来捕获输入的

  • 还与同事进行了一些进一步的挖掘,试图找出问题所在:

    一方面,我们尝试覆盖RT.jar中的某些方法,以查看选择屏幕设备的方式是否存在问题。还尝试了Toolkit.beep()功能的入口点,以查看警报声音是否来自Java端-似乎不是。

    在另一方面,很明显,甚至 native 端也没有收到键盘事件。同事将此归因于7u6中从 AWTViewNSWindow的切换。

    找到了一些现有的Oracle错误,您可以查找 here:
  • 8000276 : [macosx] graphicsDevice.setFullScreenWindow(frame) crashes JVM
  • 8000430 : [macosx] java.awt.FileDialog issues on macosx
  • 7175707 : [macosx] PIT: 8 b43 Not running on AppKit thread issue again


  • 更新10/26:

    感谢以下@maslovalex关于在7u5上运行Applet的评论,我回去仔细研究了与OSX的JDK版本的兼容性:

    含7u4的
  • 10.7.1:全屏工作!
  • 含7u5的
  • 10.7.1:全屏工作!
  • 含7u5的
  • 10.7.5:全屏工作!
  • 带7u6的
  • 10.7.5:全屏中断:(

  • 结合其他地方提到的其他测试,很明显7u6引入了一个问题,该问题仍然存在于7u7和7u9中,并且会影响Lion 10.7和Mountain Lion 10.8。

    7u6是一个重要的里程碑版本,为Mac OS X带来了对JRE和JDK的全面支持,并且包括Java FX作为发行版的一部分。有关更多信息,请参见 Release NotesRoadmap。当支持转移到Java FX时,出现这样的问题并不令人感到意外。

    问题变成:
  • Oracle会在JDK的近期版本中解决此问题吗? (如果您有指向现有错误的链接,请在此处包括它们。)
  • 在此期间可能有解决方法吗?

  • 今天的其他更新:
  • 我将Apple extensions approach to fullscreen mode纳入了探索的替代路径(更新的示例代码有待清理)。好消息:输入有效!坏消息:似乎真的没有任何信息亭/隔离选项。
    我尝试杀死Dock-directly或使用App-据我所知,Dock负责Command-Tab应用程序的切换,任务控制和启动板,却发现它也负责处理全屏应用程序!这样,Java调用将无法运行且永不返回。
    如果有一种方法可以在不影响Dock的全屏处理的情况下到达disable Command-Tab(以及Mission Control,Launchpad和Spaces),那将非常有用。另外,您可以尝试重新映射某些键,例如Command,但是这将影响在程序和系统本身中其他地方使用该修饰符的能力(当您需要Command-C复制某些文本时,这并不是完全理想的)。
  • 我没有KeyListeners的运气(我没有收到任何回调),但是我还有更多选择可以尝试。
  • 根据同事的建议,我通过反射尝试了((sun.lwawt.macosx.LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive()。想法是:
    是带有注释“如果应用程序(其窗口之一)拥有键盘焦点,则返回true”的 native 方法。在过去的几个月中,与焦点逻辑相关的CPlatformWindow.java中添加了对该方法的调用。如果它在测试代码中返回false,则可能是问题的一部分。
    不幸的是,在所有我检查的地方,该方法都返回true。因此,即使根据低级系统,我的窗口也应该具有键盘焦点。
  • 我以前对JAlbum修复的乐观已破灭。开发人员posted a response on their forum解释了他们如何在运行Java 7时简单地删除了对OS X的适当全屏支持。他们在Oracle中有一个bug(我希望得到该bug号)。


  • 更新10/25:

    我现在还在Lion 10.7.4上尝试过Java 7u9,并且看到了完全相同的问题,因此它是JDK而不是特定于OS的。

    核心问题已成为您是否可以嵌入全屏窗口的Swing核心组件,这些组件具有对键盘输入的默认处理( JTextField/JTextArea甚至是可编辑的组合框),并希望它们正常运行(而不必手动重建其基本键绑定(bind)) 。还有一个问题是,其他窗口布局的坚定者是否应该起作用,例如使用制表符进行焦点遍历。

    理想的目标是能够使用带有所有按钮,选项卡,字段等的窗口化Swing应用程序,并以完整的大多数功能在全屏独占/信息亭模式下运行它。 (以前,我已经看到Dialog弹出窗口或ComboBox下拉菜单在OS X的Java 6上无法全屏显示,但是其他组件的表现都不错。)

    我将研究eawt FullScreen功能,如果它们支持信息亭锁定选项(例如消除Command-Tab应用程序切换),这将很有趣。

    原始问题:

    我有一个Swing应用程序,多年来一直通过Java 6在Mac OS X上支持 FullScreen (exclusive)模式。我一直在与最新的Mountain Lion版本(补充版本10.8.2)和Oracle的JDK 7进行兼容性测试,并注意到一个明显的问题,同时在那种模式下:鼠标移动和单击可以正常工作,但是键盘输入没有传递到组件。

    (在下面的测试用例中,我将其范围缩小到在全屏模式下无法键入简单的JTextField。)

    一种症状是每次按键都会导致系统发出蜂鸣声,就像操作系统不允许将键盘事件传递给应用程序一样。

    另外,我的应用程序安装了导出挂钩,而Command-Q组合将触发该挂钩-显然,操作系统正在侦听标准按键组合。

    我已经在具有各种安装方式的三台不同的Mac上分别进行了测试:
  • 在Apple Java 6u35和6u37上:窗口模式和全屏模式都接收输入。
  • 在Oracle Java 7u7和7u9上:全屏显示上述症状时,窗口模式按预期工作。

  • 以前可能已经报告过:
    Java Graphics Full Screen Mode not Registering Keyboard Input
    但是,该问题不是关于Java版本或平台的。

    额外的搜索显示了Lion中引入的一个单独的全屏选项:
    Fullscreen feature for Java Apps on OSX Lion
    我还没有尝试使用这种方法,因为键盘输入似乎是FullScreen Exclusive模式(例如游戏)的目标用例的组成部分。

    JavaDoc中对此模式进行了一些提及,其中输入法可能被禁用。我试图调用建议的 Component.enableInputMethods(false),但似乎叫 have no effect

    我对基于我遇到的Java应用程序发行说明中的​​条目(JAlbum)中的问题有解决方案感到乐观。 stated fix for 10.10.6:“在Mac和Java 7上运行全屏幻灯片放映时,键盘支持不起作用”

    我的测试用例如下。与本期的第二个示例相比,它经过了轻微修改(未修改,也显示了我的问题): How to handle events from keyboard and mouse in full screen exclusive mode in java?
    特别是,它添加了一个按钮来切换全屏。
    import java.lang.reflect.*;
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.beans.*;

    /** @see https://stackoverflow.com/questions/13064607/ */
    public class FullScreenTest extends JPanel {
    private GraphicsDevice dev = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
    private JFrame f = new JFrame("FullScreenTest");

    private static final String EXIT = "Exit";
    private Action exit = new AbstractAction(EXIT) {
    @Override
    public void actionPerformed(ActionEvent e) {
    Object o = dev.getFullScreenWindow();
    if(o != null) {
    dev.setFullScreenWindow(null);
    }
    f.dispatchEvent(new WindowEvent(f, WindowEvent.WINDOW_CLOSING));
    }
    };
    private JButton exitBTN = new JButton(exit);

    private JTextField jtf = new JTextField("Uneditable in FullScreen with Java7u6+ on Mac OS X 10.7.3+");

    private JLabel keystrokeLabel = new JLabel("(Last Modifier+Key Pressed in JTextField)");

    private JLabel jtfFocusLabel = new JLabel("(JTextField Focus State)");

    private JLabel focusLabel = new JLabel("(Focused Component Hierarchy)");

    private JCheckBox useOSXFullScreenCB = new JCheckBox("Use Lion-Style FullScreen Mode");

    private JCheckBox useWorkaroundCB = new JCheckBox("Use Visibility Workaround to Restore 1st Responder Window");

    private static final String TOGGLE = "Toggle FullScreen (Command-T or Enter)";
    private Action toggle = new AbstractAction(TOGGLE) {
    @Override
    public void actionPerformed(ActionEvent e) {
    Object o = dev.getFullScreenWindow();
    if(o == null) {
    f.pack();

    /**
    * !! Neither of these calls seem to have any later effect.
    * One exception: I have a report of a
    * Mini going into an unrecoverable black screen without setVisible(true);
    * May be only a Java 6 compatibility issue. !!
    */
    //f.setVisible(true);
    //f.setVisible(false);

    if(!useOSXFullScreenCB.isSelected()) {
    // No keyboard input after this call unless workaround is used
    dev.setFullScreenWindow(f);

    /**
    * Workaround provided by Leonid Romanov at Oracle.
    */
    if(useWorkaroundCB.isSelected()) {
    f.setVisible(false);
    f.setVisible(true);
    //Not necessary to invoke later...
    /*SwingUtilities.invokeLater(new Runnable() {
    public void run() {
    f.setVisible(false);
    f.setVisible(true);
    }
    });*/
    }
    }
    else {
    toggleOSXFullscreen(f);
    }
    }
    else {
    dev.setFullScreenWindow(null);
    f.pack();
    f.setVisible(true);
    }

    isAppActive();
    }
    };
    private JButton toggleBTN = new JButton(toggle);

    public FullScreenTest() {
    // -- Layout --
    this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

    exitBTN.setAlignmentX(JComponent.CENTER_ALIGNMENT);
    exitBTN.setMaximumSize(new Dimension(Short.MAX_VALUE, 50));
    this.add(exitBTN);

    jtf.setAlignmentX(JComponent.CENTER_ALIGNMENT);
    jtf.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
    this.add(jtf);

    keystrokeLabel.setAlignmentX(JComponent.CENTER_ALIGNMENT);
    keystrokeLabel.setMaximumSize(new Dimension(Short.MAX_VALUE, 50));
    keystrokeLabel.setHorizontalAlignment(SwingConstants.CENTER);
    keystrokeLabel.setForeground(Color.DARK_GRAY);
    this.add(keystrokeLabel);

    jtfFocusLabel.setAlignmentX(JComponent.CENTER_ALIGNMENT);
    jtfFocusLabel.setMaximumSize(new Dimension(Short.MAX_VALUE, 50));
    jtfFocusLabel.setHorizontalAlignment(SwingConstants.CENTER);
    jtfFocusLabel.setForeground(Color.DARK_GRAY);
    this.add(jtfFocusLabel);

    focusLabel.setAlignmentX(JComponent.CENTER_ALIGNMENT);
    focusLabel.setMaximumSize(new Dimension(Short.MAX_VALUE, 50));
    focusLabel.setHorizontalAlignment(SwingConstants.CENTER);
    focusLabel.setForeground(Color.DARK_GRAY);
    this.add(focusLabel);

    useOSXFullScreenCB.setAlignmentX(JComponent.CENTER_ALIGNMENT);
    useOSXFullScreenCB.setMaximumSize(new Dimension(Short.MAX_VALUE, 50));
    useOSXFullScreenCB.setHorizontalAlignment(SwingConstants.CENTER);
    this.add(useOSXFullScreenCB);

    useWorkaroundCB.setAlignmentX(JComponent.CENTER_ALIGNMENT);
    useWorkaroundCB.setMaximumSize(new Dimension(Short.MAX_VALUE, 50));
    useWorkaroundCB.setHorizontalAlignment(SwingConstants.CENTER);
    this.add(useWorkaroundCB);

    toggleBTN.setAlignmentX(JComponent.CENTER_ALIGNMENT);
    toggleBTN.setMaximumSize(new Dimension(Short.MAX_VALUE, 50));
    this.add(toggleBTN);

    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setResizable(false);
    f.setUndecorated(true);
    f.add(this);
    f.pack();

    enableOSXFullscreen(f);

    // -- Listeners --

    // Default BTN set to see how input maps respond in fullscreen
    f.getRootPane().setDefaultButton(toggleBTN);

    // Explicit input map test with Command-T toggle action from anywhere in the window
    this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
    KeyStroke.getKeyStroke(KeyEvent.VK_T, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
    toggle.getValue(Action.NAME));
    this.getActionMap().put(toggle.getValue(Action.NAME), toggle);

    // KeyListener test
    jtf.addKeyListener(new KeyAdapter() {
    public void keyPressed(KeyEvent e) {
    String ktext = "KeyPressed: "+e.getKeyModifiersText(e.getModifiers()) + "_"+ e.getKeyText(e.getKeyCode());
    keystrokeLabel.setText(ktext);
    System.out.println(ktext);
    }
    });

    // FocusListener test
    jtf.addFocusListener(new FocusListener() {
    public void focusGained(FocusEvent fe) {
    focused(fe);
    }
    public void focusLost(FocusEvent fe) {
    focused(fe);
    }
    private void focused(FocusEvent fe) {
    boolean allGood = jtf.hasFocus() && jtf.isEditable() && jtf.isEnabled();
    jtfFocusLabel.setText("JTextField has focus (and is enabled/editable): " + allGood);
    isAppActive();
    }
    });

    // Keyboard Focus Manager
    KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
    focusManager.addPropertyChangeListener(new PropertyChangeListener() {
    public void propertyChange(PropertyChangeEvent e) {
    if (!("focusOwner".equals(e.getPropertyName()))) return;
    Component comp = (Component)e.getNewValue();
    if(comp == null) {
    focusLabel.setText("(No Component Focused)");
    return;
    }
    String label = comp.getClass().getName();
    while(true) {
    comp = comp.getParent();
    if(comp == null) break;
    label = comp.getClass().getSimpleName() + " -> " + label;
    }
    focusLabel.setText("Focus Hierarchy: " + label);
    isAppActive();
    }
    });
    }

    /**
    * Hint that this Window can enter fullscreen. Only need to call this once per Window.
    * @param window
    */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static void enableOSXFullscreen(Window window) {
    try {
    Class util = Class.forName("com.apple.eawt.FullScreenUtilities");
    Class params[] = new Class[]{Window.class, Boolean.TYPE};
    Method method = util.getMethod("setWindowCanFullScreen", params);
    method.invoke(util, window, true);
    } catch (ClassNotFoundException e1) {
    } catch (Exception e) {
    System.out.println("Failed to enable Mac Fullscreen: "+e);
    }
    }

    /**
    * Toggle OSX fullscreen Window state. Must call enableOSXFullscreen first.
    * Reflection version of: com.apple.eawt.Application.getApplication().requestToggleFullScreen(f);
    * @param window
    */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static void toggleOSXFullscreen(Window window) {
    try {
    Class appClass = Class.forName("com.apple.eawt.Application");

    Method method = appClass.getMethod("getApplication");
    Object appInstance = method.invoke(appClass);

    Class params[] = new Class[]{Window.class};
    method = appClass.getMethod("requestToggleFullScreen", params);
    method.invoke(appInstance, window);
    } catch (ClassNotFoundException e1) {
    } catch (Exception e) {
    System.out.println("Failed to toggle Mac Fullscreen: "+e);
    }
    }

    /**
    * Quick check of the low-level window focus state based on Apple's Javadoc:
    * "Returns true if the application (one of its windows) owns keyboard focus."
    */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static void isAppActive() {
    try {
    Class util = Class.forName("sun.lwawt.macosx.LWCToolkit");
    Method method = util.getMethod("isApplicationActive");
    Object obj = method.invoke(Toolkit.getDefaultToolkit());
    System.out.println("AppActive: "+obj);
    } catch (ClassNotFoundException e1) {
    } catch (Exception e) {
    System.out.println("Failed to check App: "+e);
    }
    }

    public static void main(String[] args) {
    System.out.println("Java Version: " + System.getProperty("java.version"));
    System.out.println("OS Version: " + System.getProperty("os.version"));

    SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
    FullScreenTest fst = new FullScreenTest();
    if(!fst.dev.isFullScreenSupported()) {
    System.out.println("FullScreen not supported on this graphics device. Exiting.");
    System.exit(0);
    }
    fst.toggle.actionPerformed(null);
    }
    });
    }
    }

    最佳答案

    这是因为添加了另一个组件的组件现在失去了焦点,可以通过以下任一方法解决此问题:

  • 在您添加了requestFocus()
  • 的组件实例上调用 KeyBinding
    要么
  • 或者将JComponent.WHEN_IN_FOCUSED_WINDOWKeyBinding一起使用:
    component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0),
    "doSomething");
    component.getActionMap().put("doSomething",
    anAction);

  • 引用:
  • How to Use Key Bindings
  • 关于java - 全屏Swing组件无法在Mac OS X Mountain Lion上的Java 7上接收键盘输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13064607/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com