Why do Java swing components show as NOT lightweight even though they should be?

610 views Asked by At

I'm curious... Why does the JComponent.isLightweightComponent(Component c) method return false when passing swing components such as JLabel, JButton, etc.? According to everything that I have read, these components should be lightweight.

Does this indicate that they are in fact heavyweight (definitely shouldn't be)?

Or is the isLightweightComponent() method broken in some way?

Or am I not understanding something about the isLightweightComponent() method?

Try the following code to see what I mean...

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class SwingLightweightTest {

    public static void main(String[] args) {
        // why do swing components show that they not Lightweight?
        // does this mean that they are Heavywight?
        // or is the .isLightweightComponent() method broken?

        JLabel jLabel = new JLabel();
        testLightweight(jLabel);

        JButton jButton = new JButton();
        testLightweight(jButton);

        JPanel jPanel = new JPanel();
        testLightweight(jPanel);
    }

    private static void testLightweight(JComponent comp) {
        String isIsnot;

        isIsnot = JComponent.isLightweightComponent(comp) ? "IS ": "IS NOT ";
        System.out.println(comp.getUIClassID() + " \t" + isIsnot + "a lightweight component");      

    }
}

it returns the following:

LabelUI IS NOT a lightweight component

ButtonUI IS NOT a lightweight component

PanelUI IS NOT a lightweight component

2

There are 2 answers

4
neuronaut On

The method isLightweightComponent is actually not checking to see if the component itself is lightweight, but rather it checks if the component's "peer" is lightweight. (As such, perhaps this method isn't named well?)

Internally the method checks if the component's peer is an instance of LightweightPeer: c.getPeer() instanceof LightweightPeer. And it looks like only NullComponentPeer and NullEmbeddedFramePeer even implement this interface. Also, the JavaDoc for isLightweightComponent has this to say:

Returns true if this component is lightweight, that is, if it doesn't have a native window system peer.

From what I can gather, peers are a sort of behind-the-scenes means of picking up native OS events and routing them to components.

Update

Upon further investigation I have discovered that before a component is made visible it has no peer (c.getPeer() returns null) and thus the check c.getPeer() instanceof LightweightPeer will return false (seemingly indicating that the component is not lightweight which is misleading). Once a component has been made visible it will be assigned a peer (my testing shows that JLabel, for instance, gets a NullComponentPeer instance as its peer) and thus will return correct information from a call to isLightweightComponent.

In summary: isLightweightComponent is checking only if a component's peer is an instance of LightweightPeer, and it returns false (instead of returning null or throwing an exception) when it can't actually determine whether the peer is lightweight or not.

1
mKorbel On

part of methods (about AWT/SWing GUI system properties, Dimension, isXxxXxx, etc) required visible Top Level Container, respectively true from isEventDispatchThread, e.g.

import java.awt.EventQueue;
import javax.swing.*;
import java.awt.event.*;

public class Test {

    private JFrame frame = new JFrame();
    private JPanel panel = new JPanel();
    private JLabel label = new JLabel("JLabel");
    private JButton button = new JButton("JButton");
    private String[] list = {"1", "2", "3", "4",};
    private JComboBox comb = new JComboBox(list);
    final JPopupMenu pop = new JPopupMenu();
    private Boolean bol = false;

    public Test() {
        comb.setLightWeightPopupEnabled(true);
        panel.add(label);
        panel.add(button);
        panel.add(comb);
        //
        System.out.println("before visible, out of EDT ---> "
                + (bol = pop.isLightweight()));
        System.out.println("before visible, out of EDT ---> "
                + (bol = pop.isLightweightComponent(comb)));
        pop.setLightWeightPopupEnabled(true);
        pop.add(comb);
        System.out.println("before visible, out of EDT ---> "
                + (bol = comb.isLightweight()));
        System.out.println("before visible, out of EDT ---> "
                + (bol = JComponent.isLightweightComponent(comb)));
        System.out.println("before visible, out of EDT ---> "
                + (bol = button.isLightweight()));
        System.out.println("before visible, out of EDT ---> "
                + (bol = JComponent.isLightweightComponent(button)));
        System.out.println("before visible, out of EDT ---> "
                + (bol = label.isLightweight()));
        System.out.println("before visible, out of EDT ---> "
                + (bol = JComponent.isLightweightComponent(label)));
        //
        frame.add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 400);
        frame.setVisible(true);
        frame.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                System.out.println("mousePressed");
                pop.show(e.getComponent(), e.getX(), e.getY());
                bol = false;
                System.out.println("JComponents are visible, on EDT ---> "
                        + (bol = pop.isLightweight()));
                System.out.println("JComponents are visible, on EDT ---> "
                        + (bol = pop.isLightweightComponent(comb)));
                System.out.println("JComponents are visible, on EDT ---> "
                        + (bol = comb.isLightweight()));
                System.out.println("JComponents are visible, on EDT ---> "
                        + (bol = JComponent.isLightweightComponent(comb)));
                System.out.println("JComponents are visible, on EDT ---> "
                        + (bol = button.isLightweight()));
                System.out.println("JComponents are visible, on EDT ---> "
                        + (bol = JComponent.isLightweightComponent(button)));
                System.out.println("JComponents are visible, on EDT ---> "
                        + (bol = label.isLightweight()));
                System.out.println("JComponents are visible, on EDT ---> "
                        + (bol = JComponent.isLightweightComponent(label)));
            }
        });
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Test();
            }
        });
    }
}

with output

run:
before visible, out of EDT ---> false
before visible, out of EDT ---> false
before visible, out of EDT ---> false
before visible, out of EDT ---> false
before visible, out of EDT ---> false
before visible, out of EDT ---> false
before visible, out of EDT ---> false
before visible, out of EDT ---> false
mousePressed
JComponents are visible, on EDT ---> true
JComponents are visible, on EDT ---> true
JComponents are visible, on EDT ---> true
JComponents are visible, on EDT ---> true
JComponents are visible, on EDT ---> true
JComponents are visible, on EDT ---> true
JComponents are visible, on EDT ---> true
JComponents are visible, on EDT ---> true
BUILD SUCCESSFUL (total time: 7 seconds)