Как напрямую отобразить динамически добавленный элемент во всплывающем окне, без двойного нажатия?

У меня есть этот 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) {
}
}

Когда я нажимаю на это поле со списком, элемент добавляется, но я должен нажать еще раз, чтобы увидеть всплывающее меню с новыми и оригинальными тремя элементами. Я хотел бы добавить элемент и показать все четыре элемента без двойного щелчка.

ОБНОВЛЕНИЕ: Вот SSCCE. В этом примере всплывающее меню отображается непосредственно, в моей базе кода, когда я впервые щелкаю по списку с добавленным элементом, я не вижу других, мне нужно снова щелкнуть в поле со списком, чтобы увидеть их все.

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 + "'.");
    }

}
}

2 ответа

Я не могу тестировать или предлагать исправления для вашего кода, так как это не SSCCE, поэтому я могу только давать советы на этом этапе.

Вместо PopupMenuListener чтобы ваш комбо обнаружил выбранный элемент в таблице, как это сделать в ActionListener отдельного JButton?

Или, если вы пытаетесь захватить любую ячейку в таблице, в которую нажимает пользователь, вы можете добавить TableColumnModelListener для столбца и ListSelectionListener для ряда, чтобы достичь того же.

  1. в Swing невозможно show() два всплывающих окна одновременно,

  2. JPopupMenu будет (немедленно) hide() по клику на JCombobox эс Arrow Button

  3. это может быть возможно изменить JPopup в JWindow лучше не украшенный JDialog

  4. пример как add / remove / modify JMenuItems до JPopupMenu видно, добавить необходимые изменения внутри mousePressed лучше в mouseReleased перед строкой кода maybeShowPopup(e); выполняется

Другие вопросы по тегам