UI glitches / flickering when changing components

Having problems with building or using the JCEF Java binding? Ask your questions here.

UI glitches / flickering when changing components

Postby novus » Mon Jul 25, 2022 4:38 am

Whenever I try to replace my browser-component with a different ui component (or vice versa), I get strange ui glitches.

Two things seem to happen:
1) The space where the browser is located gets black for one or two frames whenever hiding/showing.
2) The leftmost space of the frame shows some light flickering as well (white-ish), whenever showing the browser again.

Here's a small recording and my example code:
https://i.imgur.com/jywVxra.gif
(not perfectly visible in the gif - probably because of framerate issues - but you can at least get an impression)


Code: Select all
import me.friwi.jcefmaven.CefAppBuilder;
import org.cef.CefSettings;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class Main extends JFrame {

    private final JPanel cefPanel;
    private final JLabel replacementLabel;

    public Main() throws HeadlessException {
        setLayout();
        setBackground(Color.white);
        cefPanel = createCefPanel();
        replacementLabel = new JLabel("Hi!");
        addComp(cefPanel, 0);
        addRefreshButton();

        setSize(new Dimension(600, 600));
        setLocationRelativeTo(null);
        setVisible(true);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }

    private void setLayout() {
        var contentPane = getContentPane();
        contentPane.setLayout(new GridBagLayout());
        ((GridBagLayout) contentPane.getLayout()).columnWidths = new int[] {400, 100, 200, 0};
        ((GridBagLayout) contentPane.getLayout()).rowHeights = new int[] {0, 0};
        ((GridBagLayout) contentPane.getLayout()).columnWeights = new double[] {0.0, 1.0, 0.0, 1.0E-4};
        ((GridBagLayout) contentPane.getLayout()).rowWeights = new double[] {1.0, 1.0E-4};
    }

    private void addRefreshButton() {
        var refresh = new JButton();
        refresh.addActionListener(new ActionListener() {
            private boolean cef;

            @Override
            public void actionPerformed(ActionEvent l) {
                if (cef) {
                    getContentPane().remove(replacementLabel);
                    addComp(cefPanel, 0);
                } else {
                    getContentPane().remove(cefPanel);
                    addComp(replacementLabel, 0);
                }
                revalidate();
                repaint();
                cef = !cef;
            }
        });
        refresh.setText("Switch View");
        addComp(refresh, 1);
    }

    private void addComp(Component comp, int gridy) {
        getContentPane().add(comp, new GridBagConstraints(1, gridy, 1, 1, 0.0, 0.0,
                GridBagConstraints.CENTER, GridBagConstraints.BOTH,
                new Insets(0, 0, 0, 0), 0, 0));
    }

    private JPanel createCefPanel() {
        var comp = new BasicCefComponent();
        var jPanel = new JPanel();
        jPanel.setLayout(new BorderLayout());
        jPanel.add(comp, BorderLayout.CENTER);
        return jPanel;
    }

    public static void main(String[] args) throws Exception {
        setupJcef();
        new Main();
    }

    private static void setupJcef() throws Exception {
        var builder = new CefAppBuilder();
        builder.getCefSettings().windowless_rendering_enabled = false;
        builder.getCefSettings().log_severity = CefSettings.LogSeverity.LOGSEVERITY_ERROR;
        builder.build();  // builds a singleton instance accessible via CefApp.getInstance()
    }
}


Code: Select all
import org.cef.CefApp;
import org.cef.browser.CefBrowser;
import org.cef.handler.CefFocusHandlerAdapter;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

public class BasicCefComponent extends JPanel {

    private static final List<CefBrowser> browsers = new ArrayList<>();
    protected CefBrowser browser;

    public BasicCefComponent() {
        setLayout(new BorderLayout(0, 0));
        setBackground(Color.white);
        setOpaque(true);
        refresh();
    }

    public void refresh() {
        var url = "https://www.google.com";
        if (browser == null) {
            var cefClient = CefApp.getInstance().createClient();
            cefClient.addFocusHandler(new CefFocusHandlerAdapter() {
                @Override
                public boolean onSetFocus(final CefBrowser browser, FocusSource focusSource) {
                    if(browser == null)return false;
                    for(CefBrowser bindBrowser : browsers) {
                        if(bindBrowser.getUIComponent().hasFocus()) {
                            return false;
                        }
                    }
                    return true;
                }
            });
            browser = cefClient.createBrowser(url, false, false);
            add(browser.getUIComponent(), BorderLayout.CENTER);
            browsers.add(browser);
        } else {
            browser.loadURL(url);
        }
        browser.getUIComponent().setVisible(true);
    }
}
novus
Newbie
 
Posts: 1
Joined: Fri Jul 22, 2022 4:45 am

Re: UI glitches / flickering when changing components

Postby jdekeij » Thu Sep 08, 2022 5:02 am

To reduce the black screen, you can keep the parent window invisible and make the browser window and parent window visible on the OnLoadEnd() call.

Jasper
jdekeij
Techie
 
Posts: 11
Joined: Mon Jun 22, 2020 8:21 am


Return to JCEF Forum

Who is online

Users browsing this forum: No registered users and 154 guests