Hello Java powers that be,

I've implemented a JTable that I can add/delete rows of information to/from, but I can't actually see the changes until I do something stupid like resize the columns. I currently use a "fireTableCellUpdated(row, col);" doo-hicky in my AbstractTableModel(whenever data is changed) that I thought would do the trick, but I guess not.

I'm not so skilled with the Java/GUI programming stuff, so let me know what other information you might need to know to solve this problem.

Unrelated Problem: Does anyone know how to change the color of the numbers on a JSlider? (I've tried setBackground() and setForeground())

peace.

Recommended Answers

All 7 Replies

Right after you add a row or delete it, revalidate the table.

table.revalidate();

call that on the table, NOT the table model.

Also, is it really necessary that you use the abstract table model? I'm using default right now and it's much easier to use. It simply has a method called addRow() and addColumn() that would probably suit your needs and make life easier on you.

YES! Was about to write "Thanks for the reply server_crash, but it didn't seem to work....." when I realized I was calling revalidate(); on the instance of my table-containing panel class, not the actual table.

For some reason it doesn't update on the first addition, but I think that's some weirdness on my end...something that I can fiddle around with.

As far as the question of whether or not I'd be better off just using a default model....well, I don't know. I might be, but I really wouldn't know because I'm just kind of piecing this application together from lots and lots of random Java GUI lessons learned.

Thanks again for the help.

peace.

I did this just the other day! I would suggest using the DefaultTableModel, you'll have an easier time with it.

This was my code:

int c = dtm.getRowCount();
			 for (int i=c-1; i>=0; i--)
			 {
				 dtm.removeRow(i);
				 mortgageTable.revalidate();
			 }

dtm is a DefaultTableModel
mortgageTable is the JTable

Compare your code with mine. It will be somewhat different, but overall it should look similar. Again, I really think you should use the DefaultTableModel instead.

I have a very simple frame that retrieves the list of pdf files in a directory.
Using an extension of a DefaultTableModel, it then loads each filename preceded by a Boolean and followed by a blank string. When I click on an action button "Scan", it loops through the rows from the table model and if it is "checked", it scans the file. Each time it changes pages in the scan, it calls a method "change" in the frame holding the table with the filename as an argument. The method looks up the fileName in the model and does a tablemodel.setValueAt(str, row, 2), where row is the row located, 2 is the location of the column that had an empty string, and str contains "2 or 5" for instance, then "3 of 5", etc. Since I am using setValueAt on a DefaultTableModel and haven't overridden any methods, I expect to see the value in the 3rd column ticking away 2 of 5, 3 of 5, 4 of 5, etc.

After all files have been processed, the last of the values shows up for all rows simultaneously like "3 of 3" and "5 of 5" showing me that I have been setting the values. What's missing is the changing of that cell on the screen in real-time.

I've tried fireTableDataChanged(), revalidate on the table, etc. NOTHING.

     // section where row is found and model is updated.  The msg contains
     //  "3 of 5", "4 of 5", etc.
     int row = ((MyTableModel)aTable.getModel()).findRow(fileName);
     // update the Type info
     // System.out.println("Looking for <"+fileName+"> found row "+row);
     if (row == -1)
        return;
     System.out.println("Updating row " + row + " with " + msg);
     ((DefaultTableModel)aTable.getModel()).setValueAt(msg, row, 2);
     // various attempts to cause table to show the message.
     //aTable.revalidate();
     //((AbstractTableModel)aTable.getModel()).fireTableDataChanged();
     //aTable.updateUI();



  class MyTableModel extends DefaultTableModel
   {
      private int rows = 0;
      public MyTableModel(Vector dataVector, Vector columnNames)
      {
         super(dataVector, columnNames);
         rows = dataVector.size();
      }

      public Class getColumnClass(int c)
      {
         if (c == 0)
            return Boolean.class;
         else
            return super.getColumnClass(c);
      }

      /*
       * Don't need to implement this method unless your table's editable.
       */
      public boolean isCellEditable(int row, int col)
      {
         if (col == 0 || col == 2)
            return true;
         return false;
      }

      public int findRow(String fileName)
      {
         for (int i = 0; i < rows; i++)
         {
            if (fileName.equals((String)getValueAt(i, 1)))
               return i;
         }
         return -1;
      }
   }

I'm showing the loop also just so it can be seen.

        OpenHandler handler = new OpenHandler(getQueriable());
        int rows = ((MyTableModel)aTable.getModel()).getRowCount();
        long start = System.currentTimeMillis();
        for (int i = 0; i < rows; i++)
        {
           boolean val = ((Boolean)aTable.getModel().getValueAt(i, 0)).booleanValue();
           if (!val)
              continue;
           String fileName = (String)aTable.getModel().getValueAt(i, 1);
           String path = aDir.getAbsolutePath() + File.separatorChar + fileName;
           handler.scanPages((Editable)getQueriable().getViewer(), path);
        }
        long stop = System.currentTimeMillis();
        System.out.println("\nTime to scan "+rows+" files is "+(stop - start)/1000+" seconds");

The handler scans the pages and as it does it calls the first piece of code and very clearly prints the message to the console showing the progress, but NOT updating the gui until it's completely done, then it does.
I can find no reason why the JTable should not be showing me the "progress" as I loop through the rows.

Swing is a single-threaded event model. If you are executing the code that updates the table in a button action listener then you are essentially "holding-up" processing other UI events like repaints, table updates, etc.

If you want the table to update over the course of a long running process you will need to perform that processing in a separate thread and push UI updates onto the event dispatch thread.

This tutorial may help: http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html

Great advice! Thanks! I finally understand what's been bothering me in so many cases! Took me about 10 minutes to fix my code so it does precisely what I wanted.

This link on single threaded swing should be advice to all with questions about non-responsiveness of GUI's to update events!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.