Inicio > java, kodegeek, programación > Agregando un botón a la celda de una tabla usando Swing

Agregando un botón a la celda de una tabla usando Swing

Jueves, 9 de Abril de 2009

Parece trivial (y una vez que se resuelven todos los pormenores lo es), Sin embargo un problema de “rendering” me quebró la cabeza por dos buenos días, hasta que al fin (y con la ayuda de buenos desarrolladores en Internet) le logré dar la vuelta.

A la final el código quedó asi:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
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.table.TableColumn;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.AbstractCellEditor;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
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);
		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; // ENABLE THE EDITOR JUST FOR THE NAME
			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 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);
						}
					});
 
				}
			});
		}
	}
 
}

Les dejó el código para que lo disfruten, aún tiene un bug en OSX (Linux y Windows no tienen el problema). Espero sus comentarios como siempre :)

Veneblogs: , , ,

Blogalaxia: , , ,

To2blogs: , , ,

Technorati: , , ,

Del.icio.us: , , ,

java, kodegeek, programación , , ,

  1. Sin comentarios aún.
  1. Jueves, 9 de Abril de 2009 a las 03:00 | #1