It's a good start but the problem is it will never shrink the cells even if the contents are updated to be much smaller. I've had to deal with precisely this problem only I also had to deal with the row height as well and it had to dynamically change as the user scrolled due to different data being displayed. It took two interfaces and about five classes to solve the problem. Unfortunately that code is proprietary but I can at least describe one fairly robust way of solving it.
The first issue is that there's no easy way to find the preferred width or height of other cells because the table reuses a renderer for painting each cell in a column. Michael gets around this by only changing the width if it needs to be larger. If this suits you then do that, but if it doesn't read on.
One approach is to have the renderer dispatch events whenever it's size changes and include in that even the preferred width, height and the row and column, all of which should be available when getTableCellRendererComponent() is invoked on the renderer. Then create a class to listen for these events and keep track of the preferred width and height of each cell. That class can then either make that information accessible to another class which is responsible for sizing the rows and columns or it can do the sizing itself.
So basically what you would do is create a SizeEvent that contains the width, height, row and column. Then you would define a listener interface that has a sizeChanged(SizeEvent) method for notification using that event. Create another interface that renderer's can implement which defines methods to add and remove listeners. Then either create custom renderers that implement this interface and dispatch the event when getTableCellRendererComponent() is called or create a wrapper/decorator that can wrap an arbitrary renderer to implement the functionality. Finally, create a class that can have these renderer's added to it and will listen for changes in the size.
When a change occurs note the width and height for that column. Then provide a method that can look at that data and find the largest width and height needed for a given cell. Either have that same class update the JTable's row/column size to meet that requirement or have a different class query the aforementioned class to find the information.
In my case I've done both. I have something called a "RendererGroup" that keeps track of the sizes by adding a "GroupableRenderer" which can notify "GroupListener"s of changes by passing a "SizeEvent". The RendererGroup then calculates the height/width for the cell and updates the row and column of the JTable that was passed to it at construction. In another example it's a very specialized JTable that keeps track of the information itself and updates itself as necessary.