invokeLater strange call, after other methods

59 Views Asked by At

I am developing a library program and when I make a given successive actions, I get an unexpected row added to my books' JTable.

The actions are this:

  • launching of the program
  • add a filter based on the commentaries (I have many filters, which are classes inheriting from RowFilter, they are all associated to the RowSorter of the JTable. This part of the program works fine). In the initial state, there are 2 book in the JTable, which are "le livre de la jungle" and "Eloge des mathématiques". After the use of the filter, there only remains one, "Eloge des mathématiques". The other is not displayed but is still in the model.
  • select in the JTable the remaining book("le livre de la jungle"). With the debugger, I saw that during the actions triggered by this click, a book with an empty title and author is created. It is not visible but if I
  • deactivate all the filters, There are now 3 books in the JTable. (2 previous one plus the "ghost" with dummy values.) The dummy values come from a method, saveChanges(), which saves the current fields.

Here is a picture of the program, with the ribbon(north), the fields(center), and the JTable(bottom).

here

you can see the additional row, unexpected.

Now, let's see some code:

When I click on the JTable's row, I trigger this method:

table.getSelectionModel().addListSelectionListener(e -> {

      if (!e.getValueIsAdjusting()) {
        if (table.getSelectedRow() > -1) {

          Book book = ((TableATM) table.getModel()).getBook(table
                  .convertRowIndexToModel(table.getSelectedRow()));

          getStatesManager().getState().selectBook(book);

        }
      }
    });

This calls selectBook, from the UnboundState class. There are 2 states for the window: BoundState & UnboundState. UnboundState is used when the fields are empty. When the fields contain the datas of a book, (e.g. after a remote search on internet with the ISBN) it is immediately saved and the state becomes bound.

After the search I talked about above, the state remains the same as the initial one, I mean UnboundState : the search only changes the JTable, not the fields.

so, UnboundState's selectBook is triggered :

@Override
  public void selectBook(Book book) {
    statesManager.setBound(book);
  }

the setBound method's purpose is to change the state :

public void setBound(Book book) {
    state = new BoundState(book, this, bookWindow,
            new ChoiceISBNDialog(bookWindow));


  }

here is the constructor called by setBound:

public BoundState(Book book, StatesManager statesManager,
                    BookWindow bookWindow, ChoiceISBNDialog choice) {
    this.statesManager = statesManager;
    this.bookWindow = bookWindow;
    this.choice = choice;

    SwingUtilities.invokeLater(() -> {
      statesManager.enableFields(true);
      if (statesManager.getState().getName().equals("BOUND"))
        saveChanges();
      statesManager.displayBook(book);
      statesManager.setCaretsToZero();
      bookWindow.ribbon.btn_revertChanges.setEnabled(false);
      bookWindow.ribbon.btn_storeInTable.setEnabled(false);
    });
  }

The important thing is that th emethod saveChanges() should not be called, because the current state when the invokeLater is called is "UNBOUND".

But when I debug the program, I get this: the methods are ran, following the odrer I gave to you, except that the debugger don't go into the invokeLater, it continues, and the methods finish, the last one is the JTable listener. but I put a breakpoint in the saveChanges() method, and I see that the saveChanges() method is triggered AFTER the end of the JTable's listener. This is an effect of the invokeLater I presume. But at the time, the state became "BOUND" and the saveChanges method think that the book actually in the fields is new and tries to save it.

How could I make it work? I tried a call to invokeAndWait but it freezes the program (it is definitely stopped, even after 1 minute or more).

0

There are 0 best solutions below