mrt181
mrt181

Reputation: 5316

How to directly show a dynamically added item in the popup, without doubleclicking?

I have this PopupMenuListener

public class MyPopupMenuListener implements PopupMenuListener {

protected JTable _table;

public MyPopupMenuListener(JTable table) {
    _table = table;
}

@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
    JComboBox comboBox = null;

    comboBox = (JComboBox) e.getSource();
    final int selectedRow = _table.rowAtPoint(comboBox.getLocation());
    final int selectedColumn = _table.columnAtPoint(comboBox.getLocation());

    if (_table.getValueAt(selectedRow, selectedColumn)
            .equals(MyEnum.BOTH.getDescription())) {
        comboBox.getModel().setSelectedItem(MyEnum.BOTH.getDescription());
    }
}

@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}

@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
}

When i click on this combo box the item is added but i have to click again to see the popup menu with the new and the original three items. I would like to add the item and show all four items without double clicking.

UPDATE: Here is a SSCCE. In the example the popupmenu is visible directly, in my code base when I first click the combobox with the added item, I do not see the other ones, I have to click again into the combobox to see all of them.

public class Example extends JFrame {
private JTable _table;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Example frame = new Example();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public Example() {
    setBounds(100, 100, 450, 300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    _table = new JTable();
    _table.setModel(new DefaultTableModel(
        new Object[][] {
            {MyEnum.ONE.getDescription()},
            {MyEnum.ONE.getDescription()},
            {MyEnum.ONE.getDescription()},
        },
        new String[] {
            "Selection"
        }
    ) {
        Class[] columnTypes = new Class[] {
            String.class
        };
        public Class getColumnClass(int columnIndex) {
            return columnTypes[columnIndex];
        }
    });
    getContentPane().add(_table, BorderLayout.CENTER);
    _table.getColumnModel()
            .getColumn(0)
            .setCellEditor(new MyCellEditor(new MySwitchComboBox(new String[] {
                    MyEnum.ONE.getDescription(),
                    MyEnum.TWO.getDescription(),
            }), _table));

}

@SuppressWarnings("serial")
public class MyCellEditor extends DefaultCellEditor {

    private JComboBox _comboBox;

    public MyCellEditor(JComboBox comboBox, JTable table) {
        super(comboBox);
        _comboBox = comboBox;
        _table = table;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table,
                                                 Object value,
                                                 boolean isSelected,
                                                 int row,
                                                 int column) {

        Rectangle r = _table.getCellRect(row, column, true);
        _comboBox.setLocation(new Point(r.x, r.y + r.height));
        return super.getTableCellEditorComponent(table, value, isSelected, row, column);
    }

}

@SuppressWarnings("serial")
public class MySwitchComboBox extends JComboBox {

    public MySwitchComboBox(String[] items) {
        super(items);
        addPopupMenuListener(new PopupMenuListener() {
            private boolean _firedPopupMenuWillBecomeVisible;

            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                JComboBox comboBox = null;

                comboBox = (JComboBox) e.getSource();
                final int selectedRow =
                        _table.rowAtPoint(comboBox.getLocation());
                final int selectedColumn =
                        _table.columnAtPoint(comboBox.getLocation());

                if (_table.getValueAt(selectedRow, selectedColumn)
                        .equals(MyEnum.BOTH.getDescription())) {
                    comboBox.getModel().setSelectedItem(MyEnum.BOTH.getDescription());

                    if (_firedPopupMenuWillBecomeVisible) {
                        _firedpopupMenuWillBecomeVisible = false;
                    } else {
                       _firedPopupMenuWillBecomeVisible = true;
                       comboBox.firePopupMenuWillBecomeVisible();
                    }
                }
            }

            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
            }

            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {
            }
        });

        addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                JComboBox comboBox = null;

                MyEnum selectedConstant = MyEnum.getEnum(e.getItem().toString());
                if (e.getStateChange() == ItemEvent.SELECTED && selectedConstant != MyEnum.BOTH) {
                    comboBox = (JComboBox) e.getSource();
                    final int selectedRow = _table.rowAtPoint(comboBox.getLocation());
                    final int selectedColumn = _table.columnAtPoint(comboBox.getLocation());


                    if (selectedRow != 0) {
                        boolean allEqual = false;
                        boolean allNotEqual = false;
                        for (int i = 0; i < 3; i++) {
                            if (0 == i) {
                                continue;
                            }

                            if (selectedRow == i) {
                                allEqual = true;
                            } else if (selectedConstant == MyEnum.getEnum(_table.getValueAt(i,
                                                                                            selectedColumn)
                                    .toString())) {
                                allEqual = true;
                            } else {
                                allNotEqual = true;
                            }
                        }

                        if (allEqual && !allNotEqual) {
                            setHeaderValue(selectedConstant.getDescription(),
                                           0,
                                           selectedColumn);
                        } else {
                            setHeaderValue(MyEnum.BOTH.getDescription(),
                                           0,
                                           selectedColumn);
                        }
                        // do something
                    } else {
                        for (int i = 0; i < 3; i++) {
                            if (selectedRow != i) {
                                _table.setValueAt(selectedConstant.getDescription(),
                                                  i,
                                                  selectedColumn);
                                // do something
                            }
                        }
                    }
                }
            }

            protected void setHeaderValue(final String value,
                                          final Integer row,
                                          final int column) {
                _table.setValueAt(value, row, column);
            }

        });
    }
}

public enum MyEnum {
    BOTH("both"),
    ONE("one"),
    TWO("two");

    private String _description;

    private MyEnum(String description) {
        _description = description;
    }

    public synchronized final String getDescription() {
        return _description;
    }

    public static MyEnum getEnum(final String description) {
        for (final MyEnum element : MyEnum.values()) {
            if (element.getDescription().equals(description)) {
                return element;
            }
        }

        throw new IllegalArgumentException(
                "No enum in const class " + MyEnum.class.getCanonicalName()
                        + " contains description '" + description + "'.");
    }

}
}

Upvotes: 0

Views: 391

Answers (2)

mKorbel
mKorbel

Reputation: 109815

  1. in Swing isn't possible to show() two popup window in the same time,

  2. JPopupMenu will (immediatelly) hide() by click to JComboboxes Arrow Button

  3. this could be possible to change JPopup to JWindow, better un_decorated JDialog

  4. example how to add/remove/modify the JMenuItems before JPopupMenu is visible, add required changes inside mousePressed, better in mouseReleased, before code line maybeShowPopup(e); is executed

Upvotes: 1

splungebob
splungebob

Reputation: 5415

I can't test or suggest fixes to your code since it's not an SSCCE, so I can only offer advice at this point.

Instead of a PopupMenuListener for your combo to detect the selected item in a table, how about doing it in the ActionListener of a separate JButton?

Or, if you're trying to capture any cell in the table that the user clicks in, you could add a TableColumnModelListener for the column and a ListSelectionListener for the row to achieve the same.

Upvotes: 1

Related Questions