|
Replies:
23
-
Last Post:
Aug 25, 2009 1:22 AM
by: java_ghost
|
Threads:
[
Previous
|
Next
]
|
|
|
|
|
|
|
Re: JTable
Posted:
Apr 29, 2008 12:28 PM
in response to: sfshaza
|
|
|
Every time I look at a code base involving tables I see someone trying to do the following:
1. Add and remove columns from the table. 2. Color/Highlight an entire row based on the the contents of one column. 3. Row Labels. 4. Use a checkbox for selection of rows. 5. Multi-Line Headers 6. Multi-Line Rows 7. Grouped/Custom Headers
1. Is all about columns and column models. It seems like something one could write a tutorial for without much problem.
2. Is all about renderers. There is already some renderer tutorial information. Maybe this could be added renderer section.
3. There are some examples of row labels on the net. I'm not sure what the correct approach actually should be.
4. I'm not sure this is a good idea. I think the desire stems from the fact that control+clicking is not oblivious to all users as a mechanism for multi-selection.
5. I've seen this question asked a lot. Again there are a few differing approaches on the web and I'm not sure what the "correct" answer is.
6. Another renderer example. Would not be too hard to implement.
7. This seems really advanced, and yet I've seen it asked for time and time again.
Some of these are API issues, but as with the original SwingWorker and TableSorter, they might need to be explained in the tutorial first before making it into the JDK. Collin
|
|
|
|
|
|
|
|
Re: JTable
Posted:
May 1, 2008 12:45 PM
in response to: aberrant
|
|
|
That's a great list, Collin! Maybe after JavaOne we can ask one of the Swing engineers to address #3, #5 and #7. We could use a lot more table examples in the tutorial. (Of course there's always the problem that whenever you add a lot more examples, you're adding a lot more work to maintain and update them.)
If anyone has good examples (table or otherwise), please feel free to post them on our wiki and link to them from here.
Sharon
|
|
|
|
|
|
|
|
Re: JTable
Posted:
May 1, 2008 12:52 PM
in response to: sfshaza
|
|
|
I'll make #1 my next project. I hope to have something soon.
|
|
|
|
|
|
|
|
Re: #2 JTableColorEntireRowDemo
Posted:
May 19, 2008 9:47 AM
in response to: aberrant
|
|
|
It seems you could do this much easier by just overriding the prepareRenderer(renderer, row, column) method and possibly the prepareEditor(editor, row, column) method. Cast the renderer to the type that it is (or just JTextComponent or something) and set it's background to some color. You can use the row/column numbers to go into the model and ask for the value, being sure to translate the column/row(in java 6.0+) numbers using the convert[Row/Column]IndexTo[Model/View](int [col/row]Number). Wouldn't this be easier?
|
|
|
|
|
|
|
|
Re: #2 JTableColorEntireRowDemo
Posted:
May 19, 2008 10:39 AM
in response to: jnthodge
|
|
|
I investigated your ideas by attempting to color even and odd rows differently in a table. It seems though that modifying the renderer based on the value of a column in prepareRenderer() sets up an infinite loop. Do you have a working example of this technique? (DefaultTableCellRenderer extends JLabel)
Also I'm not sure I see a big difference between.
int colIndex = table.getColumnModel().getColumnIndex(sportColumn);
and
int colIndex = table.convertColumnIndexToView(SPORTS_COLUMN_INDEX);
Both cases involve looping through each column, one just takes the name instead of the index. Is there something I'm missing.
|
|
|
|
|
|
|
|
Re: #2 JTableColorEntireRowDemo
Posted:
May 19, 2008 12:04 PM
in response to: aberrant
|
|
|
Aberrant,
Here is an example that should run on JDK5+. Sorry for the bad indention (is there a code tag or something we can use?)
Cheers,
Jason
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component;
import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.table.TableCellRenderer;
public class RowColoringDemoApp extends JFrame {
private JPanel jContentPane = null; private JScrollPane jScrollPane = null; private JTable jTable = null;
public RowColoringDemoApp() { super(); initialize(); }
private void initialize() { this.setSize(300, 200); this.setContentPane(getJContentPane()); this.setTitle("JFrame"); }
private JPanel getJContentPane() { if (jContentPane == null) { jContentPane = new JPanel(); jContentPane.setLayout(new BorderLayout()); jContentPane.add(getJScrollPane(), BorderLayout.CENTER); } return jContentPane; }
private JScrollPane getJScrollPane() { if (jScrollPane == null) { jScrollPane = new JScrollPane(); jScrollPane.setViewportView(getJTable()); } return jScrollPane; }
private JTable getJTable() { if (jTable == null) { String columnNames[] = { "First", "Last", "Age" }; Object dataValues[][] = { { "Jason", "Hodge", 37 }, { "Aberrant", "Behavior", 35 }, { "Games", "Jostling", 55 } };
// Create a new table instance jTable = new JTable(dataValues, columnNames) { Color red = new Color(255, 150, 150); @Override public Component prepareRenderer(TableCellRenderer renderer, int row, int column) { Component rend = super.prepareRenderer(renderer, row, column); // convertColumnIndexToModel() is needed if using the JTable convenience method for getValueAt() // otherwise, column re-arrangement can break because JTable assumes column 2 to be the View's // column, not the model's column. // In JDK6+, Rows have the same dilemma since sorting was built into the table implementation. Integer age = (Integer) getValueAt(row, this.convertColumnIndexToModel(2)); if (age > 35) { // Detect over the hill programmers  rend.setBackground(red); } else { // NOTE: you have to set the color every time since renderers are re-used if (this.getSelectedRow() == row) { rend.setBackground(this.getSelectionBackground()); } else { rend.setBackground(this.getBackground()); } } return rend; } }; } return jTable; } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new RowColoringDemoApp().setVisible(true); } }); } }
|
|
|
|
|
|
|
|
Re: #2 JTableColorEntireRowDemo
Posted:
May 19, 2008 12:08 PM
in response to: jnthodge
|
|
|
Aberrant,
I forgot to note: In the example above, at runtime, rearrange the Age column to be before the others by dragging the column header and watch the code break. Then, swap out the convertColumnIndexToModel() with convertColumnIndexToView(), and it will fix this bug.
|
|
|
|
|
|
|
|
Re: #2 JTableColorEntireRowDemo
Posted:
May 19, 2008 1:00 PM
in response to: jnthodge
|
|
|
Thanks,
I found my problem that let to the infinite loop, silly mistake. This is a very interesting way of approaching this. I like it because you don't have to make your own renderer. I don't like it because it means you have to inherit from table everyplace you want to use it. Also once you start getting into custom renderers per column you can't use this technique. It IS less code, I can't argue with that.
By the way for the record replacing
Integer age = (Integer) getValueAt(row, this.convertColumnIndexToView(2));
with
Integer age = (Integer) getValueAt(row, this.getColumnModel().getColumnIndex("Age"));
works even if you rearrange the columns in your demo.
Thanks for the feedback. I'll think about it.
I just noticed your data set ... I'm 30 so I guess I'm not over the hill yet 
http://aberrantcode.blogspot.com/
Message was edited by: aberrant
|
|
|
|
|
|
|
|
Re: #2 JTableColorEntireRowDemo
Posted:
May 19, 2008 2:06 PM
in response to: aberrant
|
|
|
Aberrant,
About the lines: Integer age = (Integer) getValueAt(row, this.getColumnModel().getColumnIndex("Age"));
Yes, I agree, your way does not use the convenience method on JTable, so going directly to the column model, yours will always work. I'm kind of a fan of the convenience methods, myself, since I've found little reasons here and there that they eliminate certain inconveniences (such as when you change a model but must also fire a "changed" event to let the JTable view know you did it.)
Also, I have a table with about 4 custom renderers. They all ultimately extend some component that has a background color. Therefore, I used the prepareRenderer() method to color the rows so that I didn't have to code it into each renderer. You might have to type-check and cast here or there, but it cleans up the code in complex situations by putting all the "row coloring" logic in one place. 
Just my 2c.
Jason
|
|
|
|
|
|
|
|
Re: #2 JTableColorEntireRowDemo
Posted:
May 20, 2008 12:07 PM
in response to: jnthodge
|
|
|
Jason you have a very good point. I added http://wiki.java.net/bin/view/Projects/AlternateRowshadingDemo that uses prepareRenderer() for color. I'm still undecided as to if it needs to replace JTableColorEntireRowDemo or just supplement it.
Thanks for your feedback,
Collin
|
|
|
|
|
|
|
|
Row Labels / Frozen Columns
Posted:
May 12, 2008 1:58 PM
in response to: sfshaza
|
|
|
I did some research on the web and built a Row Labels / Frozen Columns demo. I'm not 100% sure this best way to accomplish this effect but it does seem like the most common way to approach it.
http://wiki.java.net/bin/view/Projects/JTableFrozenColumns
It seems to me that this kind of thing begs to be wrapped into a reusable component.
Collin
|
|
|
|
|
|
|
|
Re: Row Labels / Frozen Columns
Posted:
May 13, 2008 2:46 PM
in response to: aberrant
|
|
|
You are so darned prolific, Collin! 
That's a cool demo - it allows you to "freeze" the first table column (in this case) while you horizontally scroll the rest of the columns. I can see lots of applications for this.
For those of you not yet using JDK 6, you can comment out the two lines that invoke "setFillsViewportHeight" and it will work fine. If you wonder why that method is important, see this blog entry: http://blogs.sun.com/thejavatutorials/entry/dropping_data_onto_an_empty
Sharon
|
|
|
|
|
|
|
|
Re: Row Labels / Frozen Columns
Posted:
May 19, 2008 3:05 PM
in response to: aberrant
|
|
|
Does anyone know how to do a multi-row record table like you see in Quicken or QuickBooks? They have things like date, check number, payee, and amount fields on top, and then on the 2nd row per record they have things like category and memo fields.
I need to do something like that where the column headers must align to the top row of each record, and the bottom row is just one long continuous field that spans something like 15 fields. It's a long comments field for a banking app.
Any thoughts? Seen any tutorials like that?
Thanks,
Jason
|
|
|
|
|
|
|
|
Re: Row Labels / Frozen Columns
Posted:
May 19, 2008 3:37 PM
in response to: jnthodge
|
|
|
**************************
After rereading you request I decided that this is not what you are looking for. I ran into the same issue when I needed to do "totals". I know it's possible but not easy.
**********************************
I'm not quite sure this is what you are looking for but you can take a look at this and see if it helps. It's just renderer based on a JPanel and a bunch of JLabels. I cheated some to write it quickly, but I'm sure you can clean it up if the idea is what you are looking for.
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.FlowLayout; import java.util.Date; import java.util.Random;
import javax.swing.BoxLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn;
/** * RowHighlightDemo: * * Demonstrates the use of a TableCellRenderer to color an entire row of a table * based on some property of a single column. * * @author Collin Fagan */ public class RowHighlightDemo extends JPanel {
private static final long serialVersionUID = 1L;
private JTable table = new JTable();
/** * sample data column names */ private String[] columnNames = { "ID", "Info" };
private class QuickInfo { private Date date; private int checkNumber; private String payee; private String category; private String memo;
public QuickInfo(Date date, int checkNumber, String payee, String category, String memo) { super(); this.date = date; this.checkNumber = checkNumber; this.payee = payee; this.category = category; this.memo = memo; } }
private Random rnd = new Random(); /** * sample table data */ private Object[][] data = { { rnd.nextInt(100), new QuickInfo(new Date(rnd.nextLong() % System.currentTimeMillis()), rnd.nextInt(1000), "Jason Hodge", "paycheck", "for services rendered") },
{ rnd.nextInt(1000), new QuickInfo(new Date(rnd.nextLong() % System.currentTimeMillis()), rnd.nextInt(1000), "Jason Hodge", "paycheck", "for services rendered") },
{ rnd.nextInt(1000), new QuickInfo(new Date(rnd.nextLong() % System.currentTimeMillis()), rnd.nextInt(1000), "Jason Hodge", "paycheck", "for services rendered") },
{ rnd.nextInt(1000), new QuickInfo(new Date(rnd.nextLong() % System.currentTimeMillis()), rnd.nextInt(1000), "Jason Hodge", "paycheck", "for services rendered") }, { rnd.nextInt(1000), new QuickInfo(new Date(rnd.nextLong() % System.currentTimeMillis()), rnd.nextInt(1000), "Jason Hodge", "paycheck", "for services rendered") },
};
/** * Constructor builds the demo creating the table and associated renderer. */ public RowHighlightDemo() { DefaultTableModel model = new DefaultTableModel(data, columnNames) { @Override public boolean isCellEditable(int row, int column) {
return false; } };
table.setModel(model);
table.setRowHeight(60);
setLayout(new BorderLayout()); JScrollPane scrollPane = new JScrollPane(table); table.setFillsViewportHeight(true);
QuickInfoRenderer rowRenderer = new QuickInfoRenderer(); TableColumn column = table.getColumnModel().getColumn(1); column.setCellRenderer(rowRenderer);
add(scrollPane, BorderLayout.CENTER); }
private class QuickInfoRenderer extends JPanel implements TableCellRenderer {
private JLabel dateLabel = new JLabel(); private JLabel checkNumberLabel = new JLabel(); private JLabel payeeLabel = new JLabel(); private JLabel categoryLabel = new JLabel(); private JLabel memoLabel = new JLabel();
public QuickInfoRenderer() { setLayout(new FlowLayout(FlowLayout.LEFT)); add(new JLabel("Date:")); add(dateLabel); add(new JLabel("Check Number:")); add(checkNumberLabel); add(new JLabel("Payee:")); add(payeeLabel); add(new JLabel("Category:")); add(categoryLabel); add(new JLabel("Memo:")); add(memoLabel); }
@Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (!isSelected) { setBackground(table.getBackground()); } else { setBackground(table.getSelectionBackground()); }
QuickInfo qi = (QuickInfo) value; dateLabel.setText(qi.date.toString()); checkNumberLabel.setText(String.valueOf(qi.checkNumber)); payeeLabel.setText(qi.payee); categoryLabel.setText(qi.payee); memoLabel.setText(qi.memo); return this; }
}
/** * Start the demo on the Event Dispatch Thread. * * @param args * the command line arguments */ public static void main(String[] args) {
// turn bold fonts off in metal UIManager.put("swing.boldMetal", Boolean.FALSE);
SwingUtilities.invokeLater(new Runnable() { public void run() { JFrame demoFrame = new JFrame(); demoFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); demoFrame.setContentPane(new RowHighlightDemo()); demoFrame.pack(); demoFrame.setVisible(true); } }); } }
Message was edited by: aberrant
|
|
|
|
|
|
|
|
|
|
Re: Row Labels / Frozen Columns
Posted:
Aug 25, 2009 1:22 AM
in response to: aberrant
|
|
|
I just tried your code Mr. Aberrant, about frozen columns. Basically, it has 2 separated table, hasn't it? I try to sort the table, but it seems the two tables not related each other, so just one table that being sort (the one that doesn't have frozen columns). Any idea so the table can be sortable?
|
|
|
|
|
|
|
|
Re: JTable
Posted:
Oct 14, 2008 10:53 AM
in response to: aberrant
|
|
|
Dont know if you are interested but I have pretty much rewritten the DefaultTableModel class to accept row label and override the getColumnType in the AbstractTableListener. All the same constructors (modified for columnTypes) are there and all the power of the Default Table Model
|
|
|
|
|
|
|
|
Remove Selected Rows
Posted:
Jul 23, 2008 12:48 PM
in response to: sfshaza
|
|
|
One example I would love to see is "How to Remove All of the Selected Rows from a JTable". This seems like a simple task, and it turns out to be, but there are some pitfalls people could run into when trying to do this.
The first thing I thought of doing when I went to solve this problem was to get the List of selected indexes, iterate over them, and remove the rows with those indexes from the JTable's TableModel. This seems like it should work, if you iterate over the indexes in a way that ensures that you remove higher indexed rows first (so that removing a row doesn't shift the index of other rows you will remove). Unfortunately this can't be ensured for sortable tables, because one must convert from the "view index" used by JTable to the "model index" used by the table's TableModel. (Also the JTable.getSelectedRows() method documentation doesn't actually guarantee an order for the indexes it returns, it just seems to usually return them in the order of least to greatest).
The result of all of this is that one must determine how many rows are selected, and then use the JTable.getSelectedRow() method to get each row's view index individually, covert the view index to a model index, and remove this row from the model. Woah, seems a little crazy, but it's not:
//setting up the table DefaultTableModel tableModel = new DefaultTableModel(rowCount, columnCount); JTable table = new JTable(tableModel);
...
//removing all selected rows int numSelected = table.getSelectedRowCount(); for (int i=0;i<numSelected;i++) { int viewIndex = table.getSelectedRow(); int modelIndex = table.convertRowIndexToModel(viewIndex); tableModel.removeRow(modelIndex); }
I hope this is constructive information. I'm new to java.net, but I've been using the java tutorial forever, and it's an incredible resource. Please let me know if I should throw together a demo or something for this. Thank you.
Matthew
|
|
|
|
|
|
|
|
Re: Remove Selected Rows
Posted:
Aug 30, 2008 6:20 AM
in response to: mamonahan
|
|
|
You are absolutely correct. This is very good information. Thank you. If you want to put a demo together go right ahead. If not then I'll see if I have time to build one.
Thanks,
Collin
Message was edited by: aberrant
|
|
|
|
|
|
|
|
Tabbing
Posted:
Sep 3, 2008 6:22 AM
in response to: sfshaza
|
|
|
I'd love to see a good tutorial on how to use tab in a table. Preferably it would show how to move only between the editable fields in the table and then how to tab out of the table and on to the next component outside of the table.
When your at it maybe show how to validate when tabbing out of the fields. I'm struggling with this at the moment and find it hard to understand being not very good at swing.
Regards Calle PS If anyone knows of a good tutorial that explains this please tell me
|
|
|
|
|