Pregunta

I am having problems with a popup menu on a JTable and the fact that this JTable allows for Multiple Interval Selection. I'm going to explain in detail my situation, making it as clear as possible, hopefully.

I have a basic data class, lets call it Item, with a string id (name) and two boolean fields, online and active (with relative getters).
The idea behind the JTable is that, for each item in the dataset, it will show its name in the first colum and its status in the second column, where by 'status' I mean that, it will show "ACTIVE/NOT ACTIVE" if the Item is Online, otherwise it will show "OFFLINE". I have implemented a TableModel that does the job and it works.

I also want, when the user right clicks on a row, a popup to appear (if the selected Item is ONLINE) allowing to Activate/Deactivate the item, depending on its status. This worked perfectly as long as the Selection Model was SINGLE SELECTION, but when I changed it to MULTIPLE INTERVALS SELECTION, I could not make it work properly anymore.

The behaviour that I want is that, on right-click, a popup appears where the click is performed, the row is added to the selection and highlighted and all the previously selected rows stay selected! This I cannot manage to do!

Here is the code I have in the MouseListener:

tblModel.addMouseListener(new MouseAdapter() {
    void showPopup(MouseEvent e){
            int r = tblModel.rowAtPoint(e.getPoint());
            if (r >= 0 && r < tblModel.getRowCount()) {
                    //tblModel.setRowSelectionInterval(r, r);
                } else {
                    tblModel.clearSelection();
                }   
            int[] viewRowIndexes = tblModel.getSelectedRows();          
            int rowViewIndex = tblModel.getSelectedRow();

            if (rowViewIndex < 0)
                return;

            int rowModelIndex = tblModel.convertRowIndexToModel(rowViewIndex);
            if (e.isPopupTrigger() && e.getComponent() instanceof JTable) {
                Action changeActiveAction;
                Action changeInactiveAction;
                List<String> actives = new ArrayList<String>();
                List<String> inactives = new ArrayList<String>();
                DefaultListSelectionModel selectionModel = (DefaultListSelectionModel) tblModel.getSelectionModel();

                for (int viewRowIndex : viewRowIndexes) {
                    int modelRowIndex = tblModel.convertRowIndexToModel(viewRowIndex);
                    if (selectionModel.isSelectedIndex(viewRowIndex)) {
                        boolean online = ((MyTableModel) tblModel.getModel()).isItemOnline(modelRowIndex);
                        if (!online)
                            continue;

                        boolean active = ((MyTableModel) tblModel.getModel()).isItemActive(modelRowIndex);
                        String idItem = (String) ((MyTableModel) tblModel.getModel()).getValueAt(modelRowIndex,0);
                        if (active) {
                            actives.add(idItem);
                        } else {
                            inactives.add(idItem);
                        }
                    }
                }

                if (actives.size() > 0 || inactives.size() > 0) {
                    popup = new JPopupMenu();
                    if (actives.size() > 0) {
                        changeActiveAction = new ChangeAction("Deactivate ACTIVE Items","This will deactivate all the selected ACTIVE items",actives, false);
                        popup.add(new JMenuItem(changeActiveAction));
                    }
                    if (inactives.size() > 0) {
                        changeInactiveAction = new ChangeAction("Activate INACTIVE Items","This will activate all the selected INACTIVE items",inactives, true);
                        popup.add(new JMenuItem(changeInactiveAction));
                    }
                    popup.show(e.getComponent(), e.getX(),e.getY());
                }
            }
    }
    @Override
    public void mousePressed(MouseEvent e) {
        showPopup(e);
    }

    @Override   
    public void mouseReleased(MouseEvent e) {   
        showPopup(e);   
    }
};

The behaviour is functionally correct, but the selection of rows is not working. Having commented the line

//tblModel.setRowSelectionInterval(r, r);

when I right-click on a row, a popup appears, but it ignores the row on which I clicked.

On the other hand, if uncommented, that line will select only the clicked row, losing all the rest of the selection....

I am sorry for the long post, but I didn't know how to explain my problem without giving all the details of my situation.... Hopefully this is a trivial thing and you can tell me how I can fix/change it.

Thank you in advance.

¿Fue útil?

Solución

One part of the answer is:

if (tblModel.isSelectedIndex(r)) {
   tblModel.removeSelectionInterval(r, r);
} else {
   tblModel.addSelectionInterval(r, r);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top