2

Currently, I have a JList listen to list selection listener.

private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {
    // When the user release the mouse button and completes the selection,
    // getValueIsAdjusting() becomes false        
    if (evt.getValueIsAdjusting()) {
        /*
          In certain situation, I may want to prevent user from selecting other
          than current selection. How can I do so?
        */
    }
}

In certain situation, I may want to prevent user from selecting other than current selection. How can I do so?

It seems too late when I receive ListSelectionEvent. But, if I want to do it before ListSelectionEvent happen, I do not know that user is trying to select other.

Here is one of the senario.

The JList is contains list of project name. So, whenever user select new list item, we need to turn the View, from current project, and display new project. However, current project may be unsaved yet. Hence, if current project unsaved yet, we will ask for user confirmation, "Save Project?" (Yes, No, Cancel) When user select cancel, this means he want to cancel his "select to another project" action. He want to stick with current JList selection. We will pop up the confirmation dialog box in jList1ValueChanged event handle. But when we try to stick with current JList selection, it is already too late.

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875

4 Answers4

3

I've implemented this as follows for the same workflow use-case. While it works sufficiently for me, I do wish there was a simpler and more elegant approach where the selection event could be vetoed before proceeding. If I have time to investigate and figure that out I'll repost, but it might rank as a case where the return on investment isn't worth it (i.e. customizing Swing classes, handling lower level mouse/keyboard events directly, etc). Anyway what I'm doing currently is saving the last good 'validated' selection, and reverting back to it if the user cancels a future selection. It's admittedly not the prettiest solution, but it works:

// save the last good (i.e. validated) selection:
private ProjectClass lastSelectedProj;

// listing of available projects:
private JList list;

// true if current selected project has been modified without saving:
private boolean dirty;

list.addListSelectionListener(new ListSelectionListener() {
    public void valueChanged(ListSelectionEvent evt) {

    if (evt.getValueIsAdjusting()) return;

    // first validate this selection, and give the user a chance to cancel.
    // e.g. if selected project is dirty show save: yes/no/cancel dialog.
    if (dirty) {
        int choice = JOptionPane.showConfirmDialog(this,
            "Save changes?",
            "Unsaved changes",
            JOptionPane.YES_NO_CANCEL_OPTION,
            JOptionPane.WARNING_MESSAGE);

        // if the user cancels the selection event revert to previous selection:
        if (choice == JOptionPane.CANCEL_OPTION) {
            dirty = false; // don't cause yet another prompt when reverting selection
            list.setSelectedValue(lastSelectedProj, true);
            dirty = true;  // restore dirty state. not elegant, but it works.
            return;
        } else {
            // handle YES and NO options
            dirty = false;
        }
    }

    // on a validated selection event:
    lastSelectedProj = list.getSelectedValue();

    // proceed to update views for the newly selected project...
}
}
Chris B.
  • 2,532
  • 1
  • 15
  • 9
0

I think you would need to override the setSelectionInterval(...) method of JList to do nothing under your special situations.

Handling it at the event level is too late as the event has already occured.

camickr
  • 321,443
  • 19
  • 166
  • 288
0

I would suggest that you implement a custom ListSelectionModel.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
0
  table.setSelectionModel(new DefaultListSelectionModel(){

   @Override
   public void setSelectionInterval(int index0, int index1) {

    if (dragState==0 && index0==index1 && isSelectedIndex(index0)) {
     // Deny all clicks that are one row & already selected
     return;
    } else {
     super.setSelectionInterval(index0, index1);
    }
   }

  });
Jimmy
  • 1