简体   繁体   中英

Java Swing Threading Problem

so here's the problem. I have a JDialog box that consists of 3 combo boxes, a text field, a few buttons and a JTable. The JTable information is filtered based on the text field and combo boxes, so for instance it starts with all of the data and gets shrunk down to only the data that starts with any string value the user decides.

What's happening though is that while the values filter correctly, if I click in the JTable (in the white space, where there are no rows) then the rows that were deleted show up, like they were invisible until I clicked on them. I've tried almost everything: I've tried re-creating the table every time filter is clicked (bad hack that didn't even work), I've called all of the repaint, revalidate, firechanged methods, I rewrote the dialog from scratch to make sure I didn't do any stupid mistakes (if I made one I didn't find it at least), and I've tried putting them on separate threads. The only fix I haven't tried is using a swing worker, but that's because my filtering was a little too complicated for me to figure out what goes where and how to extend the swing worker correctly. The GUI is generated by netbeans (bleh), and has worked in my other dozen or so JDialogs just fine (perfectly in fact). Here's the method that doest the filtering, if any of you can help it would be greatly appreciated.

 private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

        nameFilter = "task1";
        javax.swing.table.DefaultTableModel dm = (javax.swing.table.DefaultTableModel)jTable1.getModel();


       tempParameters = parameters;
       String currentString;
       int rowNumber = 0;
       while (dm.getRowCount()>rowNumber){
           currentString = (String)(jTable1.getValueAt(rowNumber,1));
           if(!nameFilter.equalsIgnoreCase(currentString.substring(0,nameFilter.length()))){
               dm.removeRow(rowNumber);
               parameters--;
           }
           else rowNumber++;
       }
       parameters = numOfRows;
}

Update, I also implemented the filter from the comment below, and while it filtered out the correct data, it had the exact same problem. In the future I will probably use this filter feature though, so thanks.

Another update, the code is still failing even after removing everything but this chunk, and all (at least I believe..) I am doing here is doing a simple remove row call. Hope this helps a bit.

Have you tried creating a new Model every time you want to filter, instead of clearing it by deleting rows? Create new model, copy relevant rows to new Model, set new Model in table. Really shouldn't be necessary, but it might be a quick fix.

Also, I really have to wonder why you're calling toLowerCase on two strings when you're using equalsIgnoreCase to compare them.

So long as this method is called from the EDT I don't think there would be a threading problem. Try using

SwingUtilties.isEventDispatchThread()

to make sure.

If you look at the API for DefaultTableModel, updates are being sent to your JTable which will repaint itself, so I don't think that is the problem.

I would guess that it is a logic problem. If you can extract the logic into separate methods it will be easier to test and verify whether it is updating the model as you expect.

Couple of observations:

  • If the filter happens to be larger than the string content of the row, it'll throw in the substring call
  • Calling the dm.removerow is generating a bunch of tablerowsdeleted events.
  • You're asking for a rowcount from the model, yet are getting the value through the table (a little inconsistent, if the model gets wrapped around another model you might be acting upon different rows), so instead of jtable1.getvalueat, use the dm.getvalueat.

    I think what might be happening is that as the events get fired I see there are repaint and revalidate events fired in the JTable, these can be trampling over each other as they get enqueued in the EDT.

    What I would suggest is to create a new datamodel, add the rows that you want to keep, and then reassign it to your jTable1.setModel(newDm);

    Also to watch for is if someone else is modifying the model while you're in your eventlistener.

    Hope this helps

  • The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

     
    粤ICP备18138465号  © 2020-2024 STACKOOM.COM