participate


Swing - Adding a JButton inside a JTable cell rendering wrong after click
This question is answered.

<<   Back to Forum  |   Give us Feedback
10 Duke Stars rewarded for this thread
This topic has 15 replies on 2 pages.    1 | 2 | Next »
josevnz
Posts:36
Registered: 4/5/09
Adding a JButton inside a JTable cell rendering wrong after click   
Apr 5, 2009 9:25 AM
 
 
Hello to all,

I know this question has been answered one way or the other on this forum but none of the answers really gave me what I need. Also I checked the documentation on the Swing tutorial and looks like I'm still missing something.

Basically my problem is that the JButton doesn't get rendered properly after I add it to a table that has a custom table model; I managed to reproduce the issue with a toy application so please bear with me while a publish only the related pieces (by the way I'm running this on OSX):

My custom table model holds a place for the JButton which is shared by all the rows (common functionality is there is not really storing anything):

import java.util.Date;
import java.util.List;
import java.util.Vector;
 
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
 
/**
 * Table model for the GUI application
 *
 */
final public class DataTableModel extends AbstractTableModel {
 
	private static final long serialVersionUID = 769042563295665904L;
 
	/**
	 * Table description
	 */
	public static enum TableHeader {
		
		Date(Date.class), 
		Counter(Integer.class), 
		Name(String.class),
		Details(JButton.class);
		
		Class<?> currClass;
		private TableHeader(Class <?>currClass) {
			this.currClass = currClass;
		}
		public Class <?>getCurrClass() {
			return currClass;
		}
	}
 
	private List<DataElement> data;
	private JButton button;
 
	/**
	 * Parametric constructor
	 * @param tempList Data list
	 * @param aAction action used to display details
	 */
	public DataTableModel(final Vector<DataElement> tempList, final JButton aButton) {
		if (tempList == null) {
			throw new IllegalArgumentException("Data vector cannot be empty");
		}
		data = tempList;
		button = aButton;
	}
 
	@Override
	public Class<?> getColumnClass(int columnIndex) {
		return TableHeader.values()[columnIndex].getCurrClass();
	}
 
	@Override
	public int getRowCount() {
		return data.size();
	}
 
	@Override
	public Object getValueAt(int rowIndex, int columnIndex) {
		DataElement elem = data.get(rowIndex);
		switch (TableHeader.values()[columnIndex]) {
			case Date: 
				return elem.getDate();
			case Counter: 
				return elem.getCounter();
			case Name: 
				return elem.getName();
			case Details:
				return button;
			default: 
				return null;
		}
	}
 
	@Override
	public int getColumnCount() {
		return TableHeader.values().length;
	}
 
	@Override
	public String getColumnName(int column) {
		return TableHeader.values()[column].name();
	}
 
	@Override
	public boolean isCellEditable(int row, int column) {
		if (column == TableHeader.Details.ordinal()) return true; // Only the JButton cell is editable
		return false;
	}
 
}


So far so good. Then I define a custon cell renderer for any element instance of JButton:
import java.awt.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import javax.swing.JButton;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
 
import  constant DataTableModel.TableHeader;
 
/**
 * Custom cell renderer for the application JTable
 *
 */
class GuiCellRenderer extends DefaultTableCellRenderer  {
 
	private static final long serialVersionUID = 211718743340765799L;
	private SimpleDateFormat dForm;
	public GuiCellRenderer() {
		super();
		dForm = new SimpleDateFormat("hh:mm:ss a");
	}
 
	@Override
	public Component getTableCellRendererComponent(JTable table, Object val, boolean select, boolean focus, int row, int col) {
		
		super.getTableCellRendererComponent(table, val, select, focus, row, col); // Make sure gets called
 
		if (val == null) {
			return this;
		}
 
		if (val instanceof JButton) {
 
			JButton butn = (JButton) val;
			String name = (String) table.getValueAt(row, table.convertColumnIndexToView(TableHeader.Name.ordinal()));
			butn.setText(name);
			butn.setActionCommand(name);
 
			return butn;
 
		} else {
 
			switch (DataTableModel.TableHeader.values()[table.convertColumnIndexToModel(col)]) {
			case Date:
				setText(dForm.format((Date)val));
				break;
			case Counter:
				Integer iVal = (Integer) val;
				setText(iVal.toString());
				break;
			case Name:
				setText((String) val);
				break;
			default:
				setText(val.toString());
				break;
			}
 
			return this;
		}
 
	}
} //end class


The button gets rendered properly, but when you click on it it doesn't react so you either forward events or you create a custom cell editor and assign it to the JButton class types on the table. I first tried adding a MouseEvent listener and then converting the event using SwingUtilities.convertMouseEvent on my button but the click effect didn't worked out so I ended using the custom editor below:
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellEditor;
 
public final class GuiCellEditor extends  AbstractCellEditor implements TableCellEditor, ActionListener {
 
 
	private static final long serialVersionUID = 9L;
	private JButton button;
	
	public GuiCellEditor(final JButton aButton) {
		button = aButton;
	}
 
	@Override
	public void actionPerformed(ActionEvent e) {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				fireEditingStopped();
			}
		});
		
	}
 
	@Override
	public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
		int btnCol = table.convertColumnIndexToView(column);
		if (DataTableModel.TableHeader.Details.ordinal() == btnCol) {
			button = (JButton) table.getValueAt(row, column);
			//button.setBorderPainted(false);
			return button;
		}
		return null;
	}
 
	@Override
	public Object getCellEditorValue() {
		return button;
	}
	
}


Then finally I add them on my table code as follows:
ShowDetailsAction detailsAct = new ShowDetailsAction();
		JButton detailsBtn = new JButton();
		detailsBtn.setAction(detailsAct);
		model = new DataTableModel(dataModel, detailsBtn);		
		table = new JTable();
		table.setModel(model);
						
		/**
		 * Custom cell rendering
		 */
		TableCellRenderer render = new GuiCellRenderer();
		table.setDefaultRenderer(Date.class, render);
		table.setDefaultRenderer(Double.class, render);
		table.setDefaultRenderer(Long.class, render);
		table.setDefaultRenderer(Integer.class, render);
		table.setDefaultRenderer(String.class, render);
		table.setDefaultRenderer(JButton.class, render);
		table.setDefaultEditor(JButton.class, new GuiCellEditor(detailsBtn));


So here are the issues:
1) The click works and my action gets called. But the cell that holds the button goes completely blank with is annoying
2) The selected color of the cell works on all the other cells but not on the one that has the JButton. The selected row looks weird.

Sorry for the long post, I tried to be as specific as possible. I wonder if someone else already went through this and is willing to share some advise on how to implement this correctly.

Thanks in advance,

Jose.
 
camickr
Posts:33,025
Registered: 27/02/98
Re: Adding a JButton inside a JTable cell rendering wrong after click      
Apr 5, 2009 4:56 PM (reply 1 of 15)  (In reply to original post )
Helpful
 
This posting shows my attempt at using a button in a table:

http://forums.sun.com/thread.jspa?threadID=680674
 
josevnz
Posts:36
Registered: 4/5/09
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 5, 2009 6:28 PM (reply 2 of 15)  (In reply to #1 )
 
 
Hello camickr,

Thanks for your time. Yes, I saw your post before but none of your suggestion help with the rendering issue. If you try my code (I can post more or even send you the whole toy application) you will see that what I do is not very different to what you describe on your post.

The example showed on the Swing tutorial shows a similar glitch, except once you set the value the cell gets rendered properly.
 
camickr
Posts:33,025
Registered: 27/02/98
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 5, 2009 6:32 PM (reply 3 of 15)  (In reply to #2 )
 
 
I can post more or even send you the whole toy application

No we don't want to see the entire application.

If you need further help then you need to create a Short, Self Contained, Compilable and Executable, Example Program (SSCCE), that demonstrates the incorrect behaviour.
 
josevnz
Posts:36
Registered: 4/5/09
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 6, 2009 3:32 AM (reply 4 of 15)  (In reply to #3 )
 
 
I cannot post the code (I rewrote the program with only the bare minimum to show the problem), it seems than the forum has a hard limit:

"Sorry, maximum allowed length for message exceeded. Maximum allowed is 7500 only."

I removed all non essentials, any ideas how to post the code on the forum?

Edited by: josevnz on Apr 6, 2009 3:31 AM
 
josevnz
Posts:36
Registered: 4/5/09
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 6, 2009 3:37 AM (reply 5 of 15)  (In reply to #4 )
 
 
Here is the self contained app :)
import java.util.Date;
import java.util.Random;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.AbstractAction;
import javax.swing.AbstractCellEditor;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.table.TableCellEditor;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.text.SimpleDateFormat;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
public class GuiWithProblems extends JFrame {
	private static final long serialVersionUID = 1L;
	private DataTableModel model;
 
	public enum TableHeader {
		Date(Date.class), Counter(Integer.class), Name(String.class),Details(JButton.class);
		Class<?> currClass;
		private TableHeader(Class <?>currClass) {this.currClass = currClass;}
		public Class <?>getCurrClass() {return currClass;}
	}
	
	@SuppressWarnings("unchecked")
	public GuiWithProblems() {
		super("Simple GUI with JTable");
		setPreferredSize(new Dimension(600, 500));
		setLayout(new BorderLayout());
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		
		@SuppressWarnings("unused")
		Vector<?> data = new Vector();
		
		ShowDetailsAction detailsAct = new ShowDetailsAction(this);
		JButton detailsBtn = new JButton();
		detailsBtn.setAction(detailsAct);
		
		model = new DataTableModel(detailsBtn);		
		JTable table = new JTable();
		table.setModel(model);
		
		// Table selection settings
		table.setColumnSelectionAllowed(false);
		table.setRowSelectionAllowed(true);
 
		TableCellRenderer render = new GuiCellRenderer();
		table.setDefaultRenderer(Date.class, render);
		table.setDefaultRenderer(Double.class, render);
		table.setDefaultRenderer(Long.class, render);
		table.setDefaultRenderer(Integer.class, render);
		table.setDefaultRenderer(String.class, render);
		table.setDefaultRenderer(JButton.class, render);
		table.setDefaultEditor(JButton.class, new GuiCellEditor(detailsBtn));		
 
		getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
		
	}
	
	@SuppressWarnings("unchecked")
	private void addData() {
		Random random = new Random(new Date().getTime());
		for (int i = 0; i < 20; i++) {
			Vector data = new Vector();
			data.add(TableHeader.Date.ordinal(), new Date());
			data.add(TableHeader.Counter.ordinal(), i);
			data.add(TableHeader.Name.ordinal(), random.nextInt() + "");
			model.add(data);	
		}
	}
	
	 final void showGui() {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {	pack();	setVisible(true);}
		});
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		final GuiWithProblems instance = new GuiWithProblems();
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				instance.showGui();
				instance.addData();
			}
		});
 
	}
 
	public class DataTableModel extends AbstractTableModel {
		private static final long serialVersionUID = 769042563295665904L;
		@SuppressWarnings("unchecked")
		private Vector data;
		private JButton button;
 
		@SuppressWarnings("unchecked")
		public DataTableModel(final JButton aButton) {
			data = new Vector();
			button = aButton;
		}
 
		@Override
		public Class<?> getColumnClass(int columnIndex) {return TableHeader.values()[columnIndex].getCurrClass();}
 
		@Override
		public int getRowCount() {return data.size();}
 
		@SuppressWarnings("unchecked")
		@Override
		public Object getValueAt(int rowIndex, int columnIndex) {
			Vector elem = (Vector) data.get(rowIndex);
			switch (TableHeader.values()[columnIndex]) {
			case Date: 
				return elem.get(TableHeader.Date.ordinal());
			case Counter: 
				return elem.get(TableHeader.Counter.ordinal());
			case Name: 
				return elem.get(TableHeader.Name.ordinal());
			case Details:
				return button;
			default: 
				return null;
			}
		}
 
		@Override
		public int getColumnCount() {return TableHeader.values().length;}
 
		@Override
		public String getColumnName(int column) {return TableHeader.values()[column].name();}
 
		@Override
		public boolean isCellEditable(int row, int column) {if (column == TableHeader.Details.ordinal()) return true;return false;		}
 
		public void add(final Object elem) {
			SwingUtilities.invokeLater(new Runnable() {
				@SuppressWarnings("unchecked")
				public void run() {
					data.add(elem);
					int rows = getRowCount() - 1;
					fireTableRowsInserted(rows, rows);
				} 
			});
		}
	}
 
	class GuiCellRenderer extends DefaultTableCellRenderer  {
		private static final long serialVersionUID = 211718743340765799L;
		private SimpleDateFormat dForm;
		public GuiCellRenderer() {
			super();
			dForm = new SimpleDateFormat("hh:mm:ss a");
		}
 
		@Override
		public Component getTableCellRendererComponent(JTable table, Object val, boolean select, boolean focus, int row, int col) {
			super.getTableCellRendererComponent(table, val, select, focus, row, col); // Make sure gets called
 
			if (val == null) {
				return this;
			}
 
			if (val instanceof JButton) {
				JButton butn = (JButton) val;
				String name = (String) table.getValueAt(row, table.convertColumnIndexToView(TableHeader.Name.ordinal()));
				butn.setText(name);
				butn.setActionCommand(name);
				return butn;
			} else {
				switch (TableHeader.values()[table.convertColumnIndexToModel(col)]) {
				case Date:
					setText(dForm.format((Date)val));
					break;
				case Counter:
					Integer iVal = (Integer) val;
					setText(iVal.toString());
					break;
				case Name:
					setText((String) val);
					break;
				default:
					setText(val.toString());
					break;
				}
				return this;
			}
		}
	}
 
	public final class GuiCellEditor extends  AbstractCellEditor implements TableCellEditor, ActionListener {
		private static final long serialVersionUID = 9L;
		private JButton button;
		
		public GuiCellEditor(final JButton aButton) {
			button = aButton;
		}
 
		@Override
		public void actionPerformed(ActionEvent e) {
			SwingUtilities.invokeLater(new Runnable() {
				@Override
				public void run() {
					fireEditingStopped();
				}
			});
			
		}
 
		@Override
		public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
			int btnCol = table.convertColumnIndexToView(column);
			if (TableHeader.Details.ordinal() == btnCol) {
				button = (JButton) table.getValueAt(row, column);
				//button.setBorderPainted(false);
				return button;
			}
			return null;
		}
 
		@Override
		public Object getCellEditorValue() {return button;	}
		
	}
	
	class ShowDetailsAction extends AbstractAction {
		private static final long serialVersionUID = 1L;
		private JFrame frame;
		public ShowDetailsAction(final JFrame aFrame) {
			frame = aFrame;
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			SwingUtilities.invokeLater(new Runnable() {
				@Override
				public void run() {
					JOptionPane.showMessageDialog(frame, "Not much to show", "About", JOptionPane.INFORMATION_MESSAGE, null);
				}
			});
		}
	}
}


Edited by: josevnz on Apr 6, 2009 3:36 AM
 
JayDS
Posts:1,242
Registered: 10/23/98
Re: Adding a JButton inside a JTable cell rendering wrong after click      
Apr 6, 2009 5:25 AM (reply 6 of 15)  (In reply to #5 )
Helpful
 
The problem seems to be that you are trying to have the button be the value for the model,
rather than simply having the button render the value in the model. Basically, the check for
val instanceof JButton is false.

If you look at the link camickr provided, what he's doing there is having the button text set
to the value in the table and returning that text as the value. You have a mash of trying to
inject the button in the model and that's what is causing the problem.
 
T.B.M
Posts:1,056
Registered: 10/10/08
Re: Adding a JButton inside a JTable cell rendering wrong after click      
Apr 6, 2009 5:42 AM (reply 7 of 15)  (In reply to #6 )
 
 
You have a mash of trying to inject the button in the model and that's what is causing the problem.
Yes, and I want to point to the fact that you are using just one instance of JButton to act as model, renderer and editor simultaneously for all the rows !!

I suggest you relook at camickr's code which is short and easy to understand.

@camickr:
Thanks for the link to the code, that really helped me....

Thanks!
 
josevnz
Posts:36
Registered: 4/5/09
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 6, 2009 8:36 PM (reply 8 of 15)  (In reply to #7 )
 
 
T.B.M, thanks for your time and help so far.

camickr is using one button. There is no problem with that, as the renderer and editor get called exactly once per cell, right?

That is exactly what camickr wrote on the example code:

//  Create button column
        ButtonColumn buttonColumn = new ButtonColumn(table, 4); // Only one ButtonColum renderer / editor, created on the constructor of the main class


And then the renderer /editor uses one single button as well (check the constructor of ButtonColum):

JButton editButton;
        String text;
 
        public ButtonColumn(JTable table, int column)
        {
            super();
            this.table = table;
            renderButton = new JButton();
 
            editButton = new JButton();
            editButton.setFocusPainted( false );
            editButton.addActionListener( this );


Finally, his code (http://forums.sun.com/thread.jspa?threadID=680674) also shows the same issue; I made a small video and posted it on YouTube that shows the problem on OSX (please excuse the background sounds, I think the TV was playing Medium while I was recording :)):

http://www.youtube.com/watch?v=xucEZSl5coc

And my code (with the same issue).

http://www.youtube.com/watch?v=UmDwF2D3avc

I admit than adding the Button to the model was a bad design idea, since then I fixed the model and created a separated renderer (I'll post the new code shortly).
 
josevnz
Posts:36
Registered: 4/5/09
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 6, 2009 8:39 PM (reply 9 of 15)  (In reply to #6 )
 
 
JayDS, thanks for trying to answer my question,

Yes, adding the Button to the model was a bad idea and I removed it from my test code. Still, I managed to reproduce the bug on camicker code as you can see here:

http://www.youtube.com/watch?v=xucEZSl5coc
 
josevnz
Posts:36
Registered: 4/5/09
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 6, 2009 8:40 PM (reply 10 of 15)  (In reply to #1 )
 
 
Camickr, thanks for sharing your code!. Yes, I looked at your example early on but I think it has the same problem (please check the video links I posted below).

Do you see this issue on Windows or Linux as well? (I haven't got the time to try it on a different platform).
 
josevnz
Posts:36
Registered: 4/5/09
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 8, 2009 7:08 PM (reply 11 of 15)  (In reply to #10 )
 
 
Slightly different version: No button on model, separate renderer for button. Still same issue :)
import java.util.Date;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.text.SimpleDateFormat;
import java.awt.event.*;
 
public class GuiWithProblems extends JFrame {
	private static final long serialVersionUID = 1L;
	private DataTableModel model;
 
	public enum TableHeader {
		Date(Date.class), Counter(Integer.class), Name(String.class);
		Class<?> currClass;
		private TableHeader(Class <?>currClass) {this.currClass = currClass;}
		public Class <?>getCurrClass() {return currClass;}
	}
 
	@SuppressWarnings("unchecked")
	public GuiWithProblems() {
		super("Simple GUI with JTable");
		setPreferredSize(new Dimension(600, 500));
		setLayout(new BorderLayout());
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		@SuppressWarnings("unused")
		Vector<?> data = new Vector();
		model = new DataTableModel();		
		JTable table = new JTable();
		table.setModel(model);
		table.setColumnSelectionAllowed(false);
		table.setRowSelectionAllowed(true);
		TableCellRenderer render = new GuiCellRenderer();
		TableColumn col = table.getColumnModel().getColumn(TableHeader.Name.ordinal());
		JButton editorBtn = new JButton();
		col.setCellEditor(new GuiCellEditor(table));
		col.setCellRenderer(new NameBtnCellRenderer(editorBtn));
		table.setDefaultRenderer(Date.class, render);
		table.setDefaultRenderer(Double.class, render);
		table.setDefaultRenderer(Long.class, render);
		table.setDefaultRenderer(Integer.class, render);
		table.setDefaultRenderer(String.class, render);
		getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
	}
 
	@SuppressWarnings("unchecked")
	private void addData() {
		Random random = new Random(new Date().getTime());
		for (int i = 0; i < 20; i++) {
			Vector data = new Vector(); data.add(TableHeader.Date.ordinal(), new Date()); data.add(TableHeader.Counter.ordinal(), i);
			data.add(TableHeader.Name.ordinal(), random.nextInt() + ""); model.add(data);	
		}
	}
 
	final void showGui() {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {	pack();	setVisible(true);}
		});
	}
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		final GuiWithProblems instance = new GuiWithProblems();
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				instance.showGui(); 	instance.addData();
			}
		});
 
	}
 
	public class DataTableModel extends AbstractTableModel {
		private static final long serialVersionUID = 769042563295665904L;
		@SuppressWarnings("unchecked")
		private Vector data;
 
		@SuppressWarnings("unchecked")
		public DataTableModel() {data = new Vector();}
 
		@Override
		public Class<?> getColumnClass(int columnIndex) {return TableHeader.values()[columnIndex].getCurrClass();}
 
		@Override
		public int getRowCount() {return data.size();}
 
		@SuppressWarnings("unchecked")
		@Override
		public Object getValueAt(int rowIndex, int columnIndex) {
			Vector elem = (Vector) data.get(rowIndex);
			switch (TableHeader.values()[columnIndex]) {
			case Date: 	return elem.get(TableHeader.Date.ordinal());
			case Counter: 	return elem.get(TableHeader.Counter.ordinal());
			case Name:	return elem.get(TableHeader.Name.ordinal());
			default: 	return null;
			}
		}
 
		@Override
		public int getColumnCount() {return TableHeader.values().length;}
 
		@Override
		public String getColumnName(int column) {return TableHeader.values()[column].name();}
 
		@Override
		public boolean isCellEditable(int row, int column) {
			if (column == TableHeader.Name.ordinal()) return true;	return false;
		}
 
		public void add(final Object elem) {
			SwingUtilities.invokeLater(new Runnable() {
				@SuppressWarnings("unchecked")
				public void run() {
					data.add(elem); int rows = getRowCount() - 1; fireTableRowsInserted(rows, rows);
				} 
			});
		}
	}
	// General editor
	class GuiCellRenderer extends DefaultTableCellRenderer  {
		private static final long serialVersionUID = 211718743340765799L;
		private SimpleDateFormat dForm;
		public GuiCellRenderer() {
			super();	dForm = new SimpleDateFormat("hh:mm:ss a");
		}
 
		@Override
		public Component getTableCellRendererComponent(JTable table, Object val, boolean select, boolean focus, int row, int col) {
			super.getTableCellRendererComponent(table, val, select, focus, row, col); // Make sure gets called
			switch (TableHeader.values()[table.convertColumnIndexToModel(col)]) {
			case Date:	setText(dForm.format((Date)val));	break;
			case Counter:	Integer iVal = (Integer) val; setText(iVal.toString()); 	break;
			case Name:	setText((String) val); break;
			default:		setText(val.toString()); break;
			}
			return this;
		}
	}
	// Renderer used only for the name, renders column as button
	class NameBtnCellRenderer extends DefaultTableCellRenderer  {
		private static final long serialVersionUID = 2L;
		private JButton btn;
		public NameBtnCellRenderer(final JButton aBtn) {
			super();
			btn = aBtn;
			btn.setFocusPainted(false);
		}
 
		@Override
		public Component getTableCellRendererComponent(JTable table, Object val, boolean select, boolean focus, int row, int col) {
			super.getTableCellRendererComponent(table, val, select, focus, row, col);
            if (focus)  {
            	btn.setForeground(table.getForeground());
            	btn.setBackground(UIManager.getColor("Button.background"));
            }  else if (select) {
            	btn.setForeground(table.getSelectionForeground());
            	btn.setBackground(table.getSelectionBackground());
            } else {
            	btn.setForeground(table.getForeground());
            	btn.setBackground(UIManager.getColor("Button.background"));
            }
 
            btn.setText( (val == null) ? "" : val.toString() );
            return btn;
		}
	}
 
	// Cell editor for the name (button)
	public final class GuiCellEditor extends  AbstractCellEditor implements TableCellEditor, ActionListener {
		private static final long serialVersionUID = 9L;
		private JButton btn;
		private Component comp;
		public GuiCellEditor(final JButton aBtn, final Component aComp) {
			btn = new JButton();
			btn.addActionListener(this);
			comp = aComp;
		}
 
		@Override
		public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
			String val = table.getValueAt(row, column) == null? "": table.getValueAt(row, column).toString();
			btn.setText(val);
			return btn;
		}
		
		@Override
		public Object getCellEditorValue() { return btn.getText(); }
		
		@Override		
		public void actionPerformed(ActionEvent e) {
			SwingUtilities.invokeLater(new Runnable() {
				@Override
				public void run() {
					SwingUtilities.invokeLater(new Runnable() {
						@Override
						public void run() {
							fireEditingStopped();
							JOptionPane.showMessageDialog(comp, String.format("Not much to show, %s", btn.getText()), "About", JOptionPane.INFORMATION_MESSAGE, null);
						}
					});
 
				}
			});
		}
	}
}


Edited by: josevnz on Apr 6, 2009 8:48 PM

Edited by: josevnz on Apr 7, 2009 3:15 PM

Edited by: josevnz on Apr 8, 2009 7:07 PM
 
camickr
Posts:33,025
Registered: 27/02/98
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 6, 2009 8:50 PM (reply 12 of 15)  (In reply to #10 )
 
 
Do you see this issue on Windows

I use Windows and no I don't see the issue. I wouldn't post or recommend the code if I did ;-)

I don't know anything about OSX. A simple renderer should not cause a problem. The complicated part of the code was trying to get it to respond to a mouse event. I see no reason why the button should turn white just because the row is selected.

Did you try to debug the code at all? Does the logic go through the "isSelected" part of the renderer. Do the two Colors happen to be White?
 
josevnz
Posts:36
Registered: 4/5/09
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 7, 2009 3:15 PM (reply 13 of 15)  (In reply to #12 )
 
 
Looks like is an OSX specific issue; I ran my code on Linux (Redhat Enteprise Server 4) and it works. I will run it through Eclipse on the MAC and I will post my findings here.

Thanks for your suggestions, will try them while I run this through the debugger.
 
josevnz
Posts:36
Registered: 4/5/09
Re: Adding a JButton inside a JTable cell rendering wrong after click   
Apr 8, 2009 7:11 PM (reply 14 of 15)  (In reply to #13 )
 
 
Not much luck while trying to figure out why it looks bad in OSX. It works fine on Linux and Windows, go figure.

Thanks for all who answered, I transferred the duke starts to all of you.

Jose.
 
This topic has 15 replies on 2 pages.    1 | 2 | Next »
Back to Forum
 
Read the Developer Forums Code of Conduct

Click to email this message Email this Topic

Edit this Topic
  
 
 
Forums Statistics
    Users Online : 28
  • Guests : 129

About Sun forums
  • Oracle Forums is a large collection of user generated discussions. It is here to help you ask questions, find answers, and participate in discussions.

    Check out our guide on Getting started with Oracle Forums for a full walkthrough of how to best leverage the benefits of this community.

Powered by Jive Forums