Search code examples
javaswingfocuschromium-embedded

JTextField in JFrame uneditable when using JCEF in JInternalFrame until JFrame loses focus


I have started implementing JCEF in a project of mine, and I am initializing the embedded browser in a JInternalFrame inside of a JFrame, alongside a series of form fields on a JPanel next to the JInternalFrame. The browser component doesn't fully initialize until the JFrame actually becomes visible, and I'm finding that my JTextFields are uneditable unless the JFrame loses and regains focus.

Any idea of what could be happening and how to fix it? This only happens when using a JInternalFrame with the JCEF component...

It also happens every time I call loadURL to load a new page in the browser: the JTextFields become uneditable again, until I lose/gain focus in the JFrame.


UPDATE: I have found a hack which allows the JTextFields to become editable again, but I wouldn't call it a solution because it is not very elegant. I added a load handler to the CefClient instance ( client.addLoadHandler(new CefLoadHandlerAdapter()) ) with an @Ovveride on the onLoadingStateChange method, which in turn gives access to the current browser component. From there I can detect when loading in the browser is complete, and use SwingUtilities to get the Window that the browser component is in. Then I setVisible(false) and setVisible(true) on that Window. I say it's not a solution because every time the browser is done loading the Window disappears and reappears. Even though the JTextFields are editable again, it is quite ugly to see the window flashing. I've tried all kinds of revalidate() and repaint() methods to no avail, unless I didn't call them right...

client.addLoadHandler(new CefLoadHandlerAdapter() {
    @Override
    public void onLoadingStateChange(CefBrowser browser, boolean isLoading,
                                boolean canGoBack, boolean canGoForward) {
      if (!isLoading) {
            //browser_ready = true;
            System.out.println("Browser has finished loading!");
            SwingUtilities.windowForComponent( browser.getUIComponent() ).setVisible(false);
            SwingUtilities.windowForComponent( browser.getUIComponent() ).setVisible(true);
      }
    }
});

If anyone can suggest a better solution, please do!


Solution

  • I figured out the problem by studying the sample JCEF application a little better. I need to implement a FocusHandler in order to release the embedded browser's hold on keyboard input:

    private boolean browserFocus_ = true;
    ---
    jTextField1.addFocusListener(new FocusAdapter() {
        @Override
        public void focusGained(FocusEvent e) {
          if (!browserFocus_) return;
          browserFocus_ = false;
          KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
          jTextField1.requestFocus();
        }
    });