RFR: 4938801: The popup does not go when the component is removed [v6]
Alexey Ivanov
aivanov at openjdk.org
Wed Jul 30 13:01:59 UTC 2025
On Wed, 30 Jul 2025 09:53:13 GMT, Prasanta Sadhukhan <psadhukhan at openjdk.org> wrote:
>>>> You can serialize a lambda expression if its target type and its captured arguments are serializable
>>
>> I think that means `propListener` is NOT going to serialize, because `PropertyChangeListener` isn't `Serializable`. I'm unfamiliar with these details; I found this link helpful: https://www.baeldung.com/java-serialize-lambda
>>
>> Alternatively: if we put `propListener` in BasicPopupMenuUI: then I think serialization will be less of an issue. `JComponent#ui` is transient, so we don't try to serialize it (and all of its other listeners). This way the JPopupMenu will come out on the other side of deserialization using whatever the L&F is in that setup. This feels good-ish to me.
>>
>> (I'm assuming most L&F's extend BasicPopupMenuUI?)
>>
>> This is all just an idea/suggestion; as long as the deserialized JPopupMenu behaves like the original JPopupMenu I think that should be fine.
>
> Yes, it seems deserialized JPopupMenu fails hiding the popup menu owing to `propListener` not getting serialized.
>
> Tried with modified testcase of yours and fixed in latest PR
>
>
> import java.awt.*;
> import java.awt.event.*;
> import javax.swing.*;
> import java.beans.PropertyChangeListener;
> import java.io.*;
>
> public class JPopupMenuSerializationTest {
>
> public static class MyThread implements Runnable {
> static Container box;
> static Component invo;
>
> public MyThread(Container cont, Component comp) {
> this.invo = comp;
> this.box = cont;
> }
>
> public void run() {
> System.out.println("Starting 3 second countdown...");
> try{
> Thread.currentThread().sleep(3000);
> } catch (Exception e) {}
> System.out.println("Removing popup invoker from the container.");
> box.remove(invo);
> box.repaint();
> }
> }
>
> public static void main(String[] args) throws Exception {
> JPopupMenuSerializationTest test = new JPopupMenuSerializationTest();
> test.testSerialization();
> }
>
> public void testSerialization() throws Exception {
> JPopupMenu popupMenu = new JPopupMenu();
> byte[] data = serialize(popupMenu);
> JPopupMenu copy = deserialize(data);
>
> test(copy);
> }
>
> private void test(JPopupMenu jpm) {
> JFrame frame = new JFrame("My frame");
> final Container pane = frame.getContentPane();
> pane.setLayout(new BorderLayout());
> pane.add(new JTextField("", 20), BorderLayout.NORTH);
> JButton btn = new JButton("Exit");
> final Thread[] thr = new Thread[] { null };
> btn.setAction(new AbstractAction() {
> public void actionPerformed(ActionEvent ev) {
> System.exit(0);
> }
> });
> btn.setText("Exit");
> pane.add(btn, BorderLayout.SOUTH);
> final JLabel label = new JLabel("Click here to invoke popup");
> label.addMouseListener(new MouseAdapter() {
> public void mouseReleased(MouseEvent e) {
> jpm.add("One");
> jpm.add("Two");
> jpm.add("Three");
> jpm.show(label,
> label.getLocationOnScreen().x,
> label.getLocationOnScreen().y);
> }
>
> public void mousePressed(MouseEvent e) {
> Thread thr = new Thread(new MyThread(pane, label));
> thr.st...
Do we even care about serialisation as much?
What would be the use case?
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/26407#discussion_r2242601894
More information about the client-libs-dev
mailing list