JTable Multi ColumnName Rows and Mac
I do the following to get multi rows for a single column name. Example:
Column Name 1 =
Quiz
SessionName
100 points
This code works for Windows but not Mac. The JList appears behind Mac's attemp to make a JTable header. It seems like Mac's component is heavyweight. Anyone know a work around?
TableCellRenderer iconHeaderRenderer = new DefaultTableCellRenderer()
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
if(value.toString().indexOf("\r\n") == -1)
setText((value == null) ? "" : value.toString());
setIcon(null);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setHorizontalTextPosition(JLabel.LEFT);
setHorizontalAlignment(JLabel.CENTER);
return this;
else
JList multiRow = new JList();
multiRow.setOpaque(true);
multiRow.setForeground(UIManager.getColor("TableHeader.foreground"));
multiRow.setBackground(UIManager.getColor("TableHeader.background"));
multiRow.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
multiRow.setCellRenderer(new MyCellRenderer());
String str = (value == null) ? "" : value.toString();
BufferedReader br = new BufferedReader(new StringReader(str));
String line;
Vector v = new Vector();
try
while ((line = br.readLine()) != null)
v.addElement(line);
catch (IOException ex)
ex.printStackTrace();
multiRow.setListData(v);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return multiRow;
};
bump
Similar Messages
-
JTable - Swapping the Rows and Columns
This issue was raised in the Java Programming forum. Received initially as a weird requirement, it now seems that it is more common than you might think. Under it's original title it was "JTable - Limitation or Not?"
I introduced the topic here so that the thread perspective can include more experienced Swing developers.
The JTable in it's default layout is intended to hold database tables with records in rows. But what if you want records in columns?
Some have said why? Just accept the row layout. Others have said use a customised form. Both reasonable views. Despite this, others report that the inherrited power of the JTable is worth leveraging and they have been doing it for years. Albeit with messy code in certain cases.
This is a clear candidate for a popular derived component. If the existing JTable were renamed as a JTableRecordPerRow I am describing a JTableRecordPerColumn. The corresponding Table Model must naturally have a getRowClass method and no getColumnClass method.
Java is good at seperating data from display issues so essentially this is only a display issue. The data representation is unaffected.
While this may be so, the TableModel for a JTable makes the link from the display to the data so it must have knowledge about cell type to trigger the correct cell editor for example.
I think it is fair to say that the standard JTable has not be designed with alternative row/column or column/row displays in mind. Hence a single getColumnClass method. However implementing a Table model which exchanges columns for rows is a good start. This leaves a few loose ends where editting is concerned.
While this may not be an ideal topic for anyone just learning Swing I have been encouraged to consider the general case within the limitations of the cell types normally supported by the default Table model.
I would have a guess that this is an established component in many private Java libraries already.
Views and experience on this topic extremely welcome.It appears to me that while interchanging the rows and columns of a JTable is not trivial it is still worthwhile as a workhorse component.
Perhaps the original design could have allowed for an aternative layout manager of somekind but this could easily have made description of records/rows and fields/columns confusing.
I will probably get this summary wrong but I aill attempt to collate the neatest approach as I see it. Criticisms or shorter steps welcome. My thanks to the original contributors traceable from this thread.
In the descriptions below a distinction is made between the normal internal data model representation of a row, called "mrow", and the displayed form "row".
Only the TableModel need be changed.
1 Use row 0 to show the headers by a)disabling the normal TableHeader renderer b)setting the cell renderer for column 0 to the default renderer used by the TableHeader and c)using the getValueAt method to return mcol header values for the row entries.
2 For other row, col values to getValueAt return the value at mcol, mrow where mcol==row-1 & mrow==col.
3 Create a new getCellClass(col,row) method to return the class where mrow==0 and mcol==row-1. Note that I am only trying to immitate the common use of of a database record per mrow here.
4 Override a)getCellRenderer and b)getCellEditor to use getCellClass
Four steps with seven parts seems worth it to me.
The power of Swing!
Many thanks to all. -
JTable Multi Level Row Headers
Hi All
does any one know what's the better way to create MultiLevel Row Headers in JTable.
for Ex.
|- Hot
|- Drinks--------|
| |- Cold
Food-------|
| |- Soft
| - Fruits-------|
|- Hard
and it goes on....to the n level.
Is there any predefined classes available in Swing for this functionality.
Thanks in Advance
Kiran.Rwhere did you find this ?
http://www2.gol.com/users/tame/swing/examples/JTableExamples1.html
That has some pretty hardcore examples!
-jonathan -
I have a JTable with many rows and X number of cols.
The user selects some rows.
I call getSelectedRows() to find out what rows have been selected.
I do some stuff and sort the rows. This loses the selection and the selected rows can be different numbers now.
How can I re-select the right rows....there is no setRowSelection(Object o).You'll need to figure out how to map from original to new row indices. Then use javax.swing.JTable.addRowSelectionInterval(int, int) to reselect. The Java tutorial provides a class called TableSorter that handles sorting and maintains an index map.
-
Print JTable with Multiple pages and rows
I took the printing example at http://java.sun.com/developer/onlineTraining/Programming/JDCBook/advprint.html#pe and modified it a bit to include the following:
1) To Print Multiple pages
2) To wrap lines that is too long for the column
3) To print with a more proffesional style, so that it doesn't look like a screen capture is printed
4) To align the numbers to the right and center column headings
import javax.swing.*;
import javax.swing.table.*;
import java.awt.print.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.Dimension;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
import java.text.*;
public class Report implements Printable
private final int LEFT_ALIGN = -1;
private final int CENTER_ALIGN = 0;
private final int RIGHT_ALIGN = 1;
private JFrame frame;
private JTable tableView;
private String lastPrintDate;
private Font defaultFont;
private Font headerFont;
private Font footerFont;
private int headerHeight;
private int footerHeight;
private int cellBuffer = 5;
private boolean first_pass;
private ArrayList pages;
public Report()
frame = new JFrame("Sales Report");
frame.addWindowListener(new WindowAdapter()
public void windowClosing(WindowEvent e)
System.exit(0);
final String[] headers =
"ID",
"Description",
"open price",
"latest price",
"End Date",
"Quantity"
int count = 0;
final Object[][] data =
{new Integer(count++), "Box of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of Biros ppppppppppppppp", "1.00", "4.99", new Date(), new Integer(200000)},
{new Integer(count++), "Blue Biro", "0.10", "0.14", new Date(), new Integer(1)},
{new Integer(count++), "legal pad", "1.00", "2.49", new Date(), new Integer(1)},
{new Integer(count++), "tape", "1.00", "1.49", new Date(), new Integer(1)},
{new Integer(count++), "stapler", "4.00", "4.49", new Date(), new Integer(1)},
{new Integer(count++), "Box of Biros", "1.00", "4.99", new Date(), new Integer(2)},
{new Integer(count++), "Blue Biro", "0.10", "0.14", new Date(), new Integer(1)},
{new Integer(count++), "legal pad", "1.00", "2.49", new Date(), new Integer(1)},
{new Integer(count++), "tape", "1.00", "1.49", new Date(), new Integer(1)},
{new Integer(count++), "stapler", "4.00", "4.49", new Date(), new Integer(1)},
{new Integer(count++), "Box of Biros", "1.00", "4.99", new Date(), new Integer(2)},
{new Integer(count++), "Blue Biro", "0.10", "0.14", new Date(), new Integer(1)},
{new Integer(count++), "legal pad", "1.00", "2.49", new Date(), new Integer(1)},
{new Integer(count++), "tape", "1.00", "1.49", new Date(), new Integer(1)},
{new Integer(count++), "stapler", "4.00", "4.49", new Date(), new Integer(1)},
{new Integer(count++), "Box of Biros", "1.00", "4.99", new Date(), new Integer(2)},
{new Integer(count++), "Blue Biro", "0.10", "0.14", new Date(), new Integer(1)},
{new Integer(count++), "legal pad", "1.00", "2.49", new Date(), new Integer(1)},
{new Integer(count++), "tape", "1.00", "1.49", new Date(), new Integer(1)},
{new Integer(count++), "stapler", "4.00", "4.49", new Date(), new Integer(1)},
{new Integer(count++), "Box of Biros", "1.00", "4.99", new Date(), new Integer(2)},
{new Integer(count++), "Blue Biro", "0.10", "0.14", new Date(), new Integer(1)},
{new Integer(count++), "legal pad", "1.00", "2.49", new Date(), new Integer(1)},
{new Integer(count++), "tape", "1.00", "1.49", new Date(), new Integer(1)},
{new Integer(count++), "stapler", "4.00", "4.49", new Date(), new Integer(1)},
{new Integer(count++), "Box of Biros", "1.00", "4.99", new Date(), new Integer(2)},
{new Integer(count++), "Blue Biro", "0.10", "0.14", new Date(), new Integer(1)},
{new Integer(count++), "legal pad", "1.00", "2.49", new Date(), new Integer(1)},
{new Integer(count++), "tape", "1.00", "1.49", new Date(), new Integer(1)},
{new Integer(count++), "stapler", "4.00", "4.49", new Date(), new Integer(1)},
{new Integer(count++), "Box of Biros", "1.00", "4.99", new Date(), new Integer(2)}
TableModel dataModel = new AbstractTableModel()
public int getColumnCount() { return headers.length; }
public int getRowCount() { return data.length;}
public Object getValueAt(int row, int col)
return data[row][col];
public String getColumnName(int column)
return headers[column];
public Class getColumnClass(int col)
return getValueAt(0,col).getClass();
public boolean isCellEditable(int row, int col)
return (col==1);
public void setValueAt(Object aValue, int row, int column)
data[row][column] = aValue;
tableView = new JTable(dataModel);
JScrollPane scrollpane = new JScrollPane(tableView);
scrollpane.setPreferredSize(new Dimension(500, 80));
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(BorderLayout.CENTER,scrollpane);
frame.pack();
JButton printButton= new JButton();
printButton.setText("print me!");
frame.getContentPane().add(BorderLayout.SOUTH,printButton);
// for faster printing turn double buffering off
RepaintManager.currentManager(frame).setDoubleBufferingEnabled(false);
printButton.addActionListener( new ActionListener()
public void actionPerformed(ActionEvent evt)
doPrint();
frame.setVisible(true);
* Reset variables before printing
private void prepareForPrint()
pages = new ArrayList();
first_pass = true;
* Display a print dialog with some hardcoded defaults
* The print fonts are also hardcoded
public void doPrint()
try
String jobName = "Java Report";
defaultFont = new Font("Arial", Font.PLAIN, 8);
footerFont = new Font("Arial", Font.PLAIN, 6);
headerFont = new Font("Arial", Font.BOLD, 10);
PrinterJob prnJob = PrinterJob.getPrinterJob();
prnJob.setPrintable(this);
PrintRequestAttributeSet prnSet = new HashPrintRequestAttributeSet();
prnSet.add(new Copies(1));
prnSet.add(new JobName(jobName, null));
prnSet.add(MediaSizeName.ISO_A4);
PageFormat pf = prnJob.defaultPage();
pf.setOrientation(java.awt.print.PageFormat.PORTRAIT);
prnJob.setJobName(jobName);
PrintService[] services = PrinterJob.lookupPrintServices();
if (services.length > 0)
if (prnJob.printDialog(prnSet))
* Get print date
String dateFormat = "dd/MM/yyyy HH:mm:ss";
DateFormat m_DateFormat = new SimpleDateFormat(dateFormat);
lastPrintDate = m_DateFormat.format(new Date()).toString();
prepareForPrint();
prnJob.print(prnSet);
else
JOptionPane.showMessageDialog(frame, "No Printer was found!!", "Printer Error", JOptionPane.ERROR_MESSAGE);
return;
catch (PrinterException e)
e.printStackTrace();
public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException
* Check if this is the first time the print method is called for this print action.
* It is not guaranteed that the print will be called with synchronous pageIndex'es,
* so we need to calculate the number of pages and which rows appear on which pages.
* Then the correct page will be printed regardless of which pageIndex is sent through.
if (first_pass)
calcPages(g, pageFormat);
first_pass = false;
// Stop printing if the pageIndex is out of range
if (pageIndex >= pages.size())
return NO_SUCH_PAGE;
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.black);
// The footer will be one line at the bottom of the page, cater for this.
g2.setFont(footerFont);
footerHeight = g2.getFontMetrics().getHeight() + g2.getFontMetrics().getDescent();
g2.setFont(defaultFont);
FontMetrics fontMetrics = g2.getFontMetrics();
int fontHeight = fontMetrics.getHeight();
int fontDescent = fontMetrics.getDescent();
double pageHeight = pageFormat.getImageableHeight() + pageFormat.getImageableY();
double pageWidth = pageFormat.getImageableWidth();
double tableWidth = (double) tableView.getColumnModel().getTotalColumnWidth();
// Shrink or expand the table to fit the page width
double scale = pageWidth / (tableWidth+ (cellBuffer * tableView.getColumnCount()));
// Calculate the width in pixels for each column
double[] columnWidths = new double[tableView.getColumnCount()];
for(int i = 0; i < tableView.getColumnCount(); i++)
columnWidths[i] = (double)tableView.getColumnModel().getColumn(i).getWidth() * scale;
// Reset the view to the start of the page
g2.translate(0, 0);
// Draw a rectangle to see the printable area
g2.draw3DRect((int)pageFormat.getImageableX(),
(int)pageFormat.getImageableY(),
(int)pageFormat.getImageableWidth(),
(int)pageFormat.getImageableHeight(),
false);
// Calculate the header height
g2.setFont(headerFont);
fontMetrics = g2.getFontMetrics();
// Print the headers and retreive the starting position for the data
int next_row = printLine(g2, pageFormat, fontMetrics, -1, (int)pageFormat.getImageableY() + fontHeight, columnWidths);
g2.setFont(defaultFont);
fontMetrics = g2.getFontMetrics();
// Start printing the detail
ArrayList page = (ArrayList)pages.get(pageIndex);
int start = ((Integer)page.get(0)).intValue();
int end = ((Integer)page.get(1)).intValue();
for (int i = start; i <= end; i++)
next_row = printLine(g2, pageFormat, fontMetrics, i, next_row, columnWidths);
// Print the footer
g2.setFont(footerFont);
String pageFooter = "Page " + (pageIndex + 1) + " - " + lastPrintDate;
g2.drawString(pageFooter,
(int)pageFormat.getWidth() / 2 - (fontMetrics.stringWidth(pageFooter) / 2),
(int)(pageHeight - fontDescent));
return PAGE_EXISTS;
* We can't guarantee that the same amount of rows will be displayed on each page,
* the row heights are dynamic and may wrap onto 2 or more lines.
* Thus we need to calculate the height of each row and then test how may rows
* fit on a specific page. eg. Page 1 contains rows 1 to 10, Page 2 contains rows 11 to 15 etc.
public void calcPages(Graphics g, PageFormat pageFormat) throws PrinterException
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.black);
// The footer will be one line at the bottom of the page, cater for this.
g2.setFont(footerFont);
footerHeight = g2.getFontMetrics().getHeight() + g2.getFontMetrics().getDescent();
g2.setFont(defaultFont);
FontMetrics fontMetrics = g2.getFontMetrics();
int fontHeight = fontMetrics.getHeight();
int fontDescent = fontMetrics.getDescent();
double pageHeight = pageFormat.getImageableHeight() - fontHeight;
double pageWidth = pageFormat.getImageableWidth();
double tableWidth = (double) tableView.getColumnModel().getTotalColumnWidth();
// Shrink or expand the table to fit the page width
double scale = pageWidth / (tableWidth+ (cellBuffer * tableView.getColumnCount()));
// Calculate the width in pixels for each column
double[] columnWidths = new double[tableView.getColumnCount()];
for(int i = 0; i < tableView.getColumnCount(); i++)
columnWidths[i] = (double)tableView.getColumnModel().getColumn(i).getWidth() * scale;
// Calculate the header height
int maxHeight = 0;
g2.setFont(headerFont);
fontMetrics = g2.getFontMetrics();
for (int j = 0; j < tableView.getColumnCount(); j++)
String value = tableView.getColumnName(j).toString();
int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);
if (numLines > maxHeight)
maxHeight = numLines;
headerHeight = g2.getFontMetrics().getHeight() * maxHeight;
g2.setFont(defaultFont);
fontMetrics = g2.getFontMetrics();
int pageNum = 0;
int bottom_of_page = (int)(pageFormat.getImageableHeight() + pageFormat.getImageableY()) - footerHeight;
int prev_row = 0;
int next_row = (int)pageFormat.getImageableY() + fontHeight + headerHeight;
int i = 0;
ArrayList page = new ArrayList();
page.add(new Integer(0));
for (i = 0; i < tableView.getRowCount(); i++)
maxHeight = 0;
for (int j = 0; j < tableView.getColumnCount(); j++)
String value = tableView.getValueAt(i, j).toString();
int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);
if (numLines > maxHeight)
maxHeight = numLines;
prev_row = next_row;
next_row += (fontHeight * maxHeight);
// If we've reached the bottom of the page then set the current page's end row
if (next_row > bottom_of_page)
page.add(new Integer(i - 1));
pages.add(page);
page = new ArrayList();
page.add(new Integer(i));
pageNum++;
next_row = (int)pageFormat.getImageableY()
+ fontHeight
+ ((int)pageFormat.getHeight() * pageNum)
+ headerHeight;
bottom_of_page = (int)(pageFormat.getImageableHeight()
+ pageFormat.getImageableY())
+ ((int)pageFormat.getHeight() * pageNum)
- footerHeight;
//Include the current row on the next page, because there is no space on this page
i--;
page.add(new Integer(i - 1));
pages.add(page);
* Print the headers or a row from the table to the graphics context
* Return the position of the row following this one
public int printLine(Graphics2D g2,
PageFormat pageFormat,
FontMetrics fontMetrics,
int rowNum,
int next_row,
double[] columnWidths)
throws PrinterException
int lead = 0;
int maxHeight = 0;
for (int j = 0; j < tableView.getColumnCount(); j++)
String value = null;
int align = LEFT_ALIGN;
if (rowNum > -1)
Object obj = tableView.getValueAt(rowNum, j);
if (obj instanceof Number)
align = RIGHT_ALIGN;
value = obj.toString();
else
align = CENTER_ALIGN;
value = tableView.getColumnName(j);
int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);
if (numLines > maxHeight)
maxHeight = numLines;
if (fontMetrics.stringWidth(value) < columnWidths[j])
// Single line
int offset = 0;
// Work out the offset from the start of the column to display alignment correctly
switch (align)
case RIGHT_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value)); break;
case CENTER_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value)) / 2; break;
default: offset = 0; break;
g2.drawString(value,
lead + (int)(pageFormat.getImageableX() + offset),
next_row);
else
for(int a = 0; a < numLines; a++)
//Multi-Line
int x = 0;
int width = 0;
for(x = 0; x < value.length(); x++)
width += fontMetrics.charWidth(value.charAt(x));
if (width > columnWidths[j])
break;
int offset = 0;
// Work out the offset from the start of the column to display alignment correctly
switch (align)
case RIGHT_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value)); break;
case CENTER_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value)) / 2; break;
default: offset = 0; break;
g2.drawString(value.substring(0, x),
lead + (int)(pageFormat.getImageableX() + offset),
next_row + (fontMetrics.getHeight() * a));
value = value.substring(x);
lead += columnWidths[j] + cellBuffer;
// Draw a solid line below the row
g2.draw(new Line2D.Double(pageFormat.getImageableX(),
next_row + (fontMetrics.getHeight() * (maxHeight - 1)) + fontMetrics.getDescent(),
pageFormat.getImageableY() + pageFormat.getImageableWidth(),
next_row + (fontMetrics.getHeight() * (maxHeight - 1)) + fontMetrics.getDescent()));
// Return the position of the row following this one
return next_row + (fontMetrics.getHeight() * maxHeight);
public static void main(String[] args)
new Report();
}Fixed some bugs and added a title. Just pass in a JTable and the class will do the rest.
import javax.swing.*;
import javax.swing.table.*;
import java.awt.print.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
import java.text.*;
import java.math.*;
public class PrintJTable implements Printable
private final int LEFT_ALIGN = -1;
private final int CENTER_ALIGN = 0;
private final int RIGHT_ALIGN = 1;
private JFrame m_parent;
private String m_title;
private JTable tableView;
private String lastPrintDate;
private Font defaultFont;
private Font headerFont;
private Font footerFont;
private int headerHeight;
private int footerHeight;
private int cellBuffer = 5;
private boolean first_pass;
private ArrayList pages;
public PrintJTable(JFrame parent, JTable table)
m_parent = parent;
tableView = table;
doPrint();
public PrintJTable(JFrame parent, String title, JTable table)
m_parent = parent;
m_title = title;
tableView = table;
doPrint();
* Reset variables before printing
private void prepareForPrint()
pages = new ArrayList();
first_pass = true;
* Display a print dialog with some hardcoded defaults
* The print fonts are also hardcoded
public void doPrint()
try
String jobName = "Java Report";
defaultFont = new Font("Arial", Font.PLAIN, 8);
footerFont = new Font("Arial", Font.PLAIN, 6);
headerFont = new Font("Arial", Font.BOLD, 8);
PrinterJob prnJob = PrinterJob.getPrinterJob();
prnJob.setPrintable(this);
PrintRequestAttributeSet prnSet = new HashPrintRequestAttributeSet();
prnSet.add(new Copies(1));
prnSet.add(new JobName(jobName, null));
prnSet.add(MediaSizeName.ISO_A4);
PageFormat pf = prnJob.defaultPage();
pf.setOrientation(java.awt.print.PageFormat.PORTRAIT);
prnJob.setJobName(jobName);
PrintService[] services = PrinterJob.lookupPrintServices();
if (services.length > 0)
if (prnJob.printDialog(prnSet))
* Get print date
String dateFormat = "dd/MM/yyyy HH:mm:ss";
DateFormat m_DateFormat = new SimpleDateFormat(dateFormat);
lastPrintDate = m_DateFormat.format(new Date()).toString();
prepareForPrint();
prnJob.print(prnSet);
else
JOptionPane.showMessageDialog(m_parent, "No Printer was found!!", "Printer Error", JOptionPane.ERROR_MESSAGE);
return;
catch (PrinterException e)
e.printStackTrace();
public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException
* Check if this is the first time the print method is called for this print action.
* It is not guaranteed that the print will be called with synchronous pageIndex'es,
* so we need to calculate the number of pages and which rows appear on which pages.
* Then the correct page will be printed regardless of which pageIndex is sent through.
if (first_pass)
calcPages(g, pageFormat);
first_pass = false;
// Stop printing if the pageIndex is out of range
if (pageIndex >= pages.size())
return NO_SUCH_PAGE;
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.black);
// The footer will be one line at the bottom of the page, cater for this.
g2.setFont(footerFont);
footerHeight = g2.getFontMetrics().getHeight() + g2.getFontMetrics().getDescent();
g2.setFont(defaultFont);
FontMetrics fontMetrics = g2.getFontMetrics();
int fontHeight = fontMetrics.getHeight();
int fontDescent = fontMetrics.getDescent();
double pageHeight = pageFormat.getImageableHeight() + pageFormat.getImageableY();
double pageWidth = pageFormat.getImageableWidth();
double tableWidth = (double) tableView.getColumnModel().getTotalColumnWidth();
// Shrink or expand the table to fit the page width
double scale = (pageWidth - (cellBuffer * tableView.getColumnCount())) / tableWidth;
// Calculate the width in pixels for each column
double[] columnWidths = new double[tableView.getColumnCount()];
double test = 0;
for(int i = 0; i < tableView.getColumnCount(); i++)
columnWidths[i] = (double)Math.floor(tableView.getColumnModel().getColumn(i).getWidth() * scale);
test += columnWidths;
// Reset the view to the start of the page
g2.translate(0, 0);
// Draw a rectangle to see the printable area
g2.draw3DRect((int)pageFormat.getImageableX(),
(int)pageFormat.getImageableY(),
(int)pageFormat.getImageableWidth(),
(int)pageFormat.getImageableHeight(),
false);
// Calculate the header height
g2.setFont(headerFont);
fontMetrics = g2.getFontMetrics();
// Print the headers and retreive the starting position for the data
int next_row = (int)pageFormat.getImageableY() + fontMetrics.getHeight();
if ((m_title != null) && (!m_title.equalsIgnoreCase("")))
g2.drawString(m_title,
(int)(pageFormat.getImageableX()),
next_row);
Color current_color = g2.getColor();
g2.setColor(Color.lightGray);
int y = next_row + fontMetrics.getDescent();
g2.draw(new Line2D.Double(pageFormat.getImageableX(),
y,
(pageFormat.getImageableY() + pageFormat.getImageableWidth()),
y));
g2.setColor(current_color);
next_row += fontMetrics.getHeight();
next_row = printLine(g2, pageFormat, fontMetrics, -1, next_row, columnWidths);
g2.setFont(defaultFont);
fontMetrics = g2.getFontMetrics();
// Start printing the detail
ArrayList page = (ArrayList)pages.get(pageIndex);
int start = ((Integer)page.get(0)).intValue();
int end = ((Integer)page.get(1)).intValue();
for (int i = start; i <= end; i++)
next_row = printLine(g2, pageFormat, fontMetrics, i, next_row, columnWidths);
// Print the footer
g2.setFont(footerFont);
String pageFooter = "Page " + (pageIndex + 1) + " - " + lastPrintDate;
g2.drawString(pageFooter,
(int)pageFormat.getWidth() / 2 - (fontMetrics.stringWidth(pageFooter) / 2),
(int)(pageHeight - fontDescent));
return PAGE_EXISTS;
* We can't guarantee that the same amount of rows will be displayed on each page,
* the row heights are dynamic and may wrap onto 2 or more lines.
* Thus we need to calculate the height of each row and then test how may rows
* fit on a specific page. eg. Page 1 contains rows 1 to 10, Page 2 contains rows 11 to 15 etc.
public void calcPages(Graphics g, PageFormat pageFormat) throws PrinterException
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.black);
// The footer will be one line at the bottom of the page, cater for this.
g2.setFont(footerFont);
footerHeight = g2.getFontMetrics().getHeight() + g2.getFontMetrics().getDescent();
g2.setFont(defaultFont);
FontMetrics fontMetrics = g2.getFontMetrics();
int fontHeight = fontMetrics.getHeight();
int fontDescent = fontMetrics.getDescent();
double pageHeight = pageFormat.getImageableHeight() - fontHeight;
double pageWidth = pageFormat.getImageableWidth();
double tableWidth = (double) tableView.getColumnModel().getTotalColumnWidth();
// Shrink or expand the table to fit the page width
double scale = (pageWidth - (cellBuffer * tableView.getColumnCount())) / tableWidth;
// Calculate the width in pixels for each column
double[] columnWidths = new double[tableView.getColumnCount()];
for(int i = 0; i < tableView.getColumnCount(); i++)
columnWidths[i] = (double)Math.floor(tableView.getColumnModel().getColumn(i).getWidth() * scale);
// Calculate the header height
int maxHeight = 0;
g2.setFont(headerFont);
fontMetrics = g2.getFontMetrics();
headerHeight = 0;
if ((m_title != null) && (!m_title.equalsIgnoreCase("")))
headerHeight = fontMetrics.getHeight();
for (int j = 0; j < tableView.getColumnCount(); j++)
String value = tableView.getColumnName(j).toString();
int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);
if (numLines > maxHeight)
maxHeight = numLines;
headerHeight += g2.getFontMetrics().getHeight() * maxHeight;
g2.setFont(defaultFont);
fontMetrics = g2.getFontMetrics();
int pageNum = 0;
int bottom_of_page = (int)(pageFormat.getImageableHeight() + pageFormat.getImageableY()) - footerHeight;
int prev_row = 0;
int next_row = (int)pageFormat.getImageableY() + fontHeight + headerHeight;
int i = 0;
ArrayList page = new ArrayList();
page.add(new Integer(0));
for (i = 0; i < tableView.getRowCount(); i++)
maxHeight = 0;
for (int j = 0; j < tableView.getColumnCount(); j++)
String value = formatObject(tableView.getValueAt(i, j));
int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);
if (numLines > maxHeight)
maxHeight = numLines;
prev_row = next_row;
next_row += (fontHeight * maxHeight);
// If we've reached the bottom of the page then set the current page's end row
if (next_row > bottom_of_page)
page.add(new Integer(i - 1));
pages.add(page);
page = new ArrayList();
page.add(new Integer(i));
pageNum++;
next_row = (int)pageFormat.getImageableY()
+ fontHeight
+ ((int)pageFormat.getHeight() * pageNum)
+ headerHeight;
bottom_of_page = (int)(pageFormat.getImageableHeight()
+ pageFormat.getImageableY())
+ ((int)pageFormat.getHeight() * pageNum)
- footerHeight;
//Include the current row on the next page, because there is no space on this page
i--;
page.add(new Integer(i - 1));
pages.add(page);
* Print the headers or a row from the table to the graphics context
* Return the position of the row following this one
public int printLine(Graphics2D g2,
PageFormat pageFormat,
FontMetrics fontMetrics,
int rowNum,
int next_row,
double[] columnWidths)
throws PrinterException
int lead = 0;
int maxHeight = 0;
for (int j = 0; j < tableView.getColumnCount(); j++)
String value = null;
int align = LEFT_ALIGN;
if (rowNum > -1)
Object obj = tableView.getValueAt(rowNum, j);
if (obj instanceof Number)
align = RIGHT_ALIGN;
value = formatObject(obj);
else
//align = CENTER_ALIGN;
value = tableView.getColumnName(j);
int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);
if (numLines > maxHeight)
maxHeight = numLines;
if (fontMetrics.stringWidth(value) < columnWidths[j])
// Single line
int offset = 0;
// Work out the offset from the start of the column to display alignment correctly
switch (align)
case RIGHT_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value)); break;
case CENTER_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value)) / 2; break;
default: offset = 0; break;
g2.drawString(value,
lead + (int)(pageFormat.getImageableX() + offset),
next_row);
else
for(int a = 0; a < numLines; a++)
//Multi-Line
int x = 0;
int width = 0;
for(x = 0; x < value.length(); x++)
width += fontMetrics.charWidth(value.charAt(x));
if (width > columnWidths[j])
break;
int offset = 0;
// Work out the offset from the start of the column to display alignment correctly
switch (align)
case RIGHT_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value.substring(0, x))); break;
case CENTER_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value.substring(0, x))) / 2; break;
default: offset = 0; break;
g2.drawString(value.substring(0, x),
lead + (int)(pageFormat.getImageableX() + offset),
next_row + (fontMetrics.getHeight() * a));
value = value.substring(x);
lead += columnWidths[j] + cellBuffer;
// Draw a solid line below the row
Color current_color = g2.getColor();
g2.setColor(Color.lightGray);
int y = next_row + (fontMetrics.getHeight() * (maxHeight - 1)) + fontMetrics.getDescent();
g2.draw(new Line2D.Double(pageFormat.getImageableX(),
y,
(pageFormat.getImageableY() + pageFormat.getImageableWidth()),
y));
g2.setColor(current_color);
// Return the position of the row following this one
return next_row + (fontMetrics.getHeight() * maxHeight);
public String formatObject(Object obj)
String value = (obj == null) ? "" : obj.toString();
return value; -
Add rows and sort JTable in the same program
I would like to have a button to add rows to the JTable, but would also like to sort the data within the columns. This program can sort the data prior to clicking the 'add row' button. After I click the button, there is no new row, and I lose the ability to sort the column. Do you have any tips or advice as to what I can do to fix my program? Is it because I have to have the final code for SortFilterModel to work?
Thanks
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableRowColumn extends JFrame
private final static String LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
JTable table;
DefaultTableModel model;
JPanel buttonPanel;
JButton button;
public TableRowColumn()
Object[][] data = {
{"6", "K"},
{"5", "A"},
{"1", "Z"}
String[] columnNames = {
"Number",
"Letter"
model = new DefaultTableModel(data, columnNames);
//comment out this SortFilterModel line
final SortFilterModel sorter = new SortFilterModel(model);
//Change sorter to model
table = new JTable(sorter);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
// Add table and a Button panel to the frame
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
buttonPanel = new JPanel();
getContentPane().add( buttonPanel, BorderLayout.SOUTH );
button = new JButton( "Add Row" );
buttonPanel.add( button );
button.addActionListener( new ActionListener()
public void actionPerformed(ActionEvent e)
model.addRow( createRow() );
int row = table.getRowCount() - 1;
table.changeSelection(row, row, false, false);
table.requestFocusInWindow();
//Set up double click handler for column headers and sort
table.getTableHeader().addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent event)
//check for click
if (event.getClickCount() < 2) return;
//find column of click and
int tableColumn = table.columnAtPoint(event.getPoint());
//translate to table model index and sort
int modelColumn = table.convertColumnIndexToModel(tableColumn);
sorter.sort(modelColumn);
private Object[] createRow()
Object[] newRow = new Object[2];
int row = table.getRowCount() + 1;
newRow[0] = Integer.toString( row );
newRow[1] = LETTERS.substring(row-1, row);
return newRow;
public static void main(String[] args)
TableRowColumn frame = new TableRowColumn();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
}I attempted to modify the code in the correct way, but I ran into a problem near the bottom with the model.addRow(rowData); line. It has an error saying it can't find the addRow method. If I take away the model part, it will compile, but it will cause an infinite loop when I push the 'Add Row' button within the program. I didn't expect that to work, and I think it isn't calling the right model.
I am aware that my code organization and design skills are not very good. I am a fan of basic assembly and low-level hardware languages for the most part.
Thanks for your advice so far, it has been helpful.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableRowColumn extends JFrame
private final static String LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
JTable table;
public DefaultTableModel model;
JPanel buttonPanel;
JButton button;
public TableRowColumn()
Object[][] data = {
{"9", "C"},
{"5", "A"},
{"3", "B"}
String[] columnNames = {
"Number",
"Letter"
model = new DefaultTableModel(data, columnNames);
//comment out this SortFilterModel line
final SortFilterModel sorter = new SortFilterModel(model);
//Change sorter to model
table = new JTable(sorter);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
// Add table and a Button panel to the frame
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
buttonPanel = new JPanel();
getContentPane().add( buttonPanel, BorderLayout.SOUTH );
button = new JButton( "Add Row" );
buttonPanel.add( button );
button.addActionListener( new ActionListener()
public void actionPerformed(ActionEvent e)
sorter.addRow( createRow() );
int row = table.getRowCount() - 1;
table.changeSelection(row, row, false, false);
table.requestFocusInWindow();
//Set up double click handler for column headers and sort
table.getTableHeader().addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent event)
//check for click
if (event.getClickCount() < 2) return;
//find column of click and
int tableColumn = table.columnAtPoint(event.getPoint());
//translate to table model index and sort
int modelColumn = table.convertColumnIndexToModel(tableColumn);
sorter.sort(modelColumn);
private Object[] createRow()
Object[] newRow = new Object[2];
int row = table.getRowCount() + 1;
newRow[0] = Integer.toString( row );
newRow[1] = LETTERS.substring(row-1, row);
return newRow;
public static void main(String[] args)
TableRowColumn frame = new TableRowColumn();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
class SortFilterModel extends AbstractTableModel{
public SortFilterModel(TableModel m){
model = m;
rows = new Row[model.getRowCount()];
for (int i = 0; i < rows.length; i++) {
rows[i] = new Row();
rows.index = i;
public void sort(int c){
sortColumn = c;
Arrays.sort(rows);
fireTableDataChanged();
public Object getValueAt(int r, int c) {
return model.getValueAt(rows[r].index, c);
public boolean isCellEditable(int r, int c){
return model.isCellEditable(rows[r].index, c);
public void setValueAt(Object aValue, int r, int c){
model.setValueAt(aValue, rows[r].index, c);
public int getRowCount() {
return model.getRowCount();
public int getColumnCount(){
return model.getColumnCount();
public String getColumnName(int c) {
return model.getColumnName(c);
public Class getColumnClass(int c){
return model.getColumnClass(c);
private class Row implements Comparable {
public int index;
public int compareTo(Object other) {
Row otherRow = (Row)other;
Object a = model.getValueAt(index, sortColumn);
Object b = model.getValueAt(otherRow.index, sortColumn);
if (a instanceof Comparable) {
return ((Comparable)a).compareTo(b);
else{
return a.toString().compareTo(b.toString());
public void addRow(Object[] rowData) {
Row[] oldRows = new Row[rows.length];
for (int i=0; i<rows.length; i++) {
oldRows[i] = rows[i];
rows = new Row[rows.length +1];
for (int i=0; i < oldRows.length; i++) {
rows[i] = oldRows[i];
rows[oldRows.length] = new Row();
rows[oldRows.length].index = oldRows.length;
addRow (rowData);
//model.addRow(rowData);
fireTableDataChanged();
private TableModel model;
private int sortColumn;
private Row[] rows; -
JTable Problem (table does not show rows and columns)
Hi All,
What the table is suppose to do.
- Load information from a database
- put all the values in the first column
- in the second column put combobox (cell editor with numbers 1-12)
- the 3rd column put another combobox for something else
- the 4th column uses checkbox as an edit
The number of rows of the table should be equal to the number of
record from
the database. If not given it default to 20 (poor but ok for this)
The number of columns is 4.
But the table does not show any rows or
column when I put it inside a
JScrollPane (Otherwise it works).
Please help,
thanks in advance.
public class SubjectTable extends JTable {
* Comment for <code>serialVersionUID</code>
private static final long serialVersionUID = 1L;
/** combo for the list of classes */
protected JComboBox classCombo;
/** combo for the list of subjects */
protected JComboBox subjectsCombo;
/** combo for the list of grade */
protected JComboBox gradeCombo;
boolean canResize = false;
boolean canReorder = false;
boolean canSelectRow = false;
boolean canSelectCell = true;
boolean canSelectColumn = true;
// the row height of the table
int rowHeight = 22;
// the height of the table
int height = 200;
// the width of the table
int width = 300;
// the size of the table
Dimension size;
* Parameterless constructor. Class the one of the other constructors
to
* create a table with the a new <code>SubjectTableModel</code>.
public SubjectTable() {
this(new SubjectTableModel());
* Copy constructor to create the table with the given
* <code>SubjectTableModel</code>
* @param tableModel -
* the <code>SubjectTableModel</code> with which to
initialise
* the table.
SubjectTable(SubjectTableModel tableModel) {
setModel(tableModel);
setupTable();
* Function to setup the table's functionality
private void setupTable() {
clear();
// set the row hieght
this.setRowHeight(this.rowHeight);
// set the font size to 12
//TODO this.setFont(Settings.getDefaultFont());
// disble reordering of columns
this.getTableHeader().setReorderingAllowed(this.canReorder);
// disble resing of columns
this.getTableHeader().setResizingAllowed(this.canResize);
// enable the horizontal scrollbar
this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// disable row selection
setRowSelectionAllowed(this.canSelectRow);
// disable column selection
setColumnSelectionAllowed(this.canSelectColumn);
// enable cell selection
setCellSelectionEnabled(this.canSelectCell);
setPreferredScrollableViewportSize(getSize());
TableColumn columns = null;
int cols = getColumnCount();
for (int col = 0; col < cols; col++) {
columns = getColumnModel().getColumn(col);
switch (col) {
case 0:// subject name column
columns.setPreferredWidth(130);
break;
case 1:// grade column
columns.setPreferredWidth(60);
break;
case 2:// class room column
columns.setPreferredWidth(120);
break;
case 3:// select column
columns.setPreferredWidth(65);
break;
} // end switch
}// end for
// set up the cell editors
doGradeColumn();
doClassColumn();
//doSubjectColumn();
* Function to clear the table selection. This selection is different
to
* <code>javax.swing.JTable#clearSelection()</code>. It clears the
user
* input
public void clear() {
for (int row = 0; row < getRowCount(); row++) {
for (int col = 0; col < getColumnCount(); col++) {
if (getColumnName(getColumnCount() - 1).equals("Select")) {
setValueAt(new Boolean(false), row, getColumnCount() - 1);
}// if
}// for col
}// for row
* Function to set the cell renderer for the subjects column. It uses
a
* combobox as a cell editor in the teacher's subjects table.
public void doSubjectColumn() {
TableColumn nameColumn = getColumnModel().getColumn(0);
nameColumn.setCellEditor(new DefaultCellEditor(getSubjectsCombo()));
// set up the celll renderer
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setToolTipText("Click for drop down list");
nameColumn.setCellRenderer(renderer);
// Set up tool tip for the sport column header.
TableCellRenderer headerRenderer = nameColumn.getHeaderRenderer();
if (headerRenderer instanceof DefaultTableCellRenderer) {
((DefaultTableCellRenderer) headerRenderer)
.setToolTipText("Click the Name to see a list of choices");
}// end doSubjectsColumn----------------------------------------------
/** Function to set up the grade combo box. */
public void doGradeColumn() {
TableColumn gradeColumn = getColumnModel().getColumn(1);
gradeColumn.setCellEditor(new DefaultCellEditor(getGradeCombo()));
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setToolTipText("Click for drop down list");
gradeColumn.setCellRenderer(renderer);
// Set up tool tip for the sport column header.
TableCellRenderer headerRenderer = gradeColumn.getHeaderRenderer();
if (headerRenderer instanceof DefaultTableCellRenderer) {
((DefaultTableCellRenderer) headerRenderer)
.setToolTipText("Click the Grade to see a list of choices");
}// end doGradeColumn-------------------------------------------------
* Function to setup the Class room Column of the subjects
public void doClassColumn() {
// set the column for the classroom
TableColumn classColumn = getColumnModel().getColumn(2);
classColumn.setCellEditor(new DefaultCellEditor(getClassCombo()));
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setToolTipText("Click for drop down list");
classColumn.setCellRenderer(renderer);
// Set up tool tip for the sport column header.
TableCellRenderer headerRenderer = classColumn.getHeaderRenderer();
if (headerRenderer instanceof DefaultTableCellRenderer) {
((DefaultTableCellRenderer) headerRenderer)
.setToolTipText("Click the Class to see a list of choices");
}// end doClassColumn--------------------------------------------------
* Function to get the size of the table
* @return Returns the size.
public Dimension getSize() {
if (this.size == null) {
this.size = new Dimension(this.height, this.width);
return this.size;
* Function to set the size of the table
* @param dim
* The size to set.
public void setSize(Dimension dim) {
if (dim != null) {
this.size = dim;
return;
* Function to create/setup the class room comboBox. If the comboBox
is
* <code>null</code> a nwew one is created else the functon returns
the
* function that was returned initially.
* @return Returns the classCombo.
private JComboBox getClassCombo() {
if (this.classCombo == null) {
this.classCombo = new JComboBox();
// fill up the class name combo
ArrayList classRooms = new ArrayList();
try {
//TODO classRooms = Settings.getDatabase().getClassRooms();
for (int i = 0; i < 10; i++) {
String string = new String("Class");
string += i;
if (!classRooms.isEmpty()) {
classRooms.trimToSize();
for (int i = 0; i < classRooms.size(); i++) {
this.classCombo.addItem(classRooms.get(i));
} catch (Exception e) {
e.printStackTrace();
return this.classCombo;
* Function to create/setup the subjects comboBox. If the comboBox is
* <code>null</code> a nwew one is created else the functon returns
the
* function that was returned initially.
* @return Returns the subjectsCombo.
private JComboBox getSubjectsCombo() {
if (this.subjectsCombo == null) {
this.subjectsCombo = new JComboBox();
try {
ArrayList subjects = loadSubjectsFromDatabase();
if (!subjects.isEmpty()) {
Iterator iterator = subjects.iterator();
while (iterator.hasNext()) {
// create a new subject instance
//TODO Subject subct = new Subject();
// typecast to subject
//TODO subct = (Subject) iterator.next();
String name = (String) iterator.next();
// add this subject to the comboBox
//TODO this.subjectsCombo.addItem(subct.getName());
subjectsCombo.addItem(name);
}// end while
}// end if
else {
JOptionPane.showMessageDialog(SubjectTable.this,
"Subjects List Could Not Be Filled");
System.out.println("Subjects List Could Not Be Filled");
} catch (Exception e) {
e.printStackTrace();
return this.subjectsCombo;
* Function to load subjects from the <code>Database</code>
* @return Returns the subjects.
private ArrayList loadSubjectsFromDatabase() {
// list of all the subject that the school does
ArrayList subjects = new ArrayList();
try {
//TODO to be removed later on
for (int i = 0; i < 10; i++) {
String string = new String("Subject");
string += i;
subjects.add(i, string);
// set the school subjects
//TODO subjects = Settings.getDatabase().loadAllSubjects();
} catch (Exception e1) {
e1.printStackTrace();
return subjects;
* Function to create/setup the grade comboBox. If the comboBox is
* <code>null</code> a nwew one is created else the functon returns
the
* function that was returned initially.
* @return Returns the gradeCombo.
private JComboBox getGradeCombo() {
if (this.gradeCombo == null) {
this.gradeCombo = new JComboBox();
// fill with grade 1 to 12
for (int i = 12; i > 0; i--) {
this.gradeCombo.addItem(new Integer(i).toString());
return this.gradeCombo;
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(new Plastic3DLookAndFeel());
System.out.println("Look and Feel has been set");
} catch (UnsupportedLookAndFeelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
SubjectTableModel model = new SubjectTableModel();
int cols = model.getColumnCount();
int rows = model.getRowCount();
Object[][] subjects = new Object[rows][cols];
for (int row = 0; row < rows; row++) {
subjects[row][0] = new String("Subjectv ") + row;
}//for
model.setSubjectsList(subjects);
SubjectTable ttest = new SubjectTable(model);
JFrame frame = new JFrame("::Table Example");
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(ttest);
frame.getContentPane().add(scrollPane);
frame.pack();
frame.setVisible(true);
**************************************END
TABLE******************************
----------------------------THE TABLE
MODEL----------------------------------
* Created on 2005/03/21
* SubjectTableModel
package com.school.academic.ui;
import javax.swing.table.AbstractTableModel;
* Class extending the <code>AbstractTableModel</code> for use in
creating the
* <code>Subject</code>s table. In addition to the implemented methods
of
* <code>AbstractTableModel</code> The class creates a model that has
initial
* values - the values have their own <code>getter</code> and
* <code>setter</code> methods - but can still be used for values that
a user
* chooses.
* <p>
* @author Khusta
public class SubjectTableModel extends AbstractTableModel {
* Comment for <code>serialVersionUID</code>
private static final long serialVersionUID = 3257850978324461113L;
/** Column names for the subjects table */
String[] columnNames = { "Subject", "Grade", "Class Room",
"Select" };
/** Array of objects for the subjects table */
Object[][] subjectsList;
private int totalRows = 20;
protected int notEditable = 0;
* Parameterless constructor.
public SubjectTableModel() {
// TODO initialise the list
// add column to the default table model
this.subjectsList = new
Object[getTotalRows()][getColumnNames().length];
* Copy constructor with the <code>subjectList</code> to set
* @param subjects
public SubjectTableModel(Object[][] subjects) {
this(0, null, subjects, 0);
* Copy constructor with the initial number of row for the model
* @param rows -
* the initial rows of the model
* @param cols -
* the initial columns of the model
* @param subjects -
* the initial subjects for the model
* @param edit - the minimum number of columns that must be
uneditable
public SubjectTableModel(int rows, String[] cols, Object[][]
subjects, int edit) {
// set the initial rows
setTotalRows(rows);
// set the column names
setColumnNames(cols);
// set the subjectlist
setSubjectsList(subjects);
//set not editable index
setNotEditable(edit);
* Function to get the total number of columns in the table
* @return int -- the columns in the table
public int getColumnCount() {
if (this.subjectsList == null) {
return 0;
return getColumnNames().length;
* Function to get the total number of rows in the table
* @return int -- the rows in the table
public int getRowCount() {
if (this.subjectsList == null) {
return 0;
return this.subjectsList.length;
* Function to get the name of a column in the table.
* @param col --
* the column to be named
* @return String -- the column in the table
public String getColumnName(int col) {
if (getColumnNames()[col] != null) {
return getColumnNames()[col];
return new String("...");
* Function to get the value of the given row.
* @param row --
* the row of the object.
* @param col --
* the col of the object.
* @return Object -- the value at row, col.
public Object getValueAt(int row, int col) {
return getSubjectsList()[row][col];
* Function to return the data type of the given column.
* @param c --
* the column whose type must be determined.
* @return Class -- the type of the object in this col.
public Class getColumnClass(int c) {
if (getValueAt(0, c) != null) {
return getValueAt(0, c).getClass();
return new String().getClass();
* Function to put a value into a table cell.
* @param value --
* the object that will be put.
* @param row --
* the row that the object will be put.
* @param col --
* the col that the object will be put.
public void setValueAt(Object value, int row, int col) {
* TODO: Have a boolean value to determine whether to clear or
to set.
* if true clear else set.
if (value != null) {
if (getSubjectsList()[0][col] instanceof Integer
&& !(value instanceof Integer)) {
try {
getSubjectsList()[row][col] = new
Integer(value.toString());
fireTableCellUpdated(row, col);
} catch (NumberFormatException e) {
* JOptionPane .showMessageDialog( this., "The \""
+
* getColumnName(col) + "\" column accepts only
values
* between 1 - 12");
return;
System.out.println("Value = " + value.toString());
System.out.println("Column = " + col + " Row = " + row);
// column = Grade or column = Select
switch (col) {
case 2:
try {
// TODO
if (Boolean.getBoolean(value.toString()) == false
&& getValueAt(row, 0) != null
&& getValueAt(row, 1) != null
&& getValueAt(row, 2) != null) {
// subjectsList[row][col + 1] = new
Boolean(true);
System.out.println("2. false - Updated...");
* this.subjectListModel.add(row,
* this.subjectsList[row][0] + new String(" -
") +
* this.subjectsList[row][2]);
} catch (ArrayIndexOutOfBoundsException exception) {
exception.printStackTrace();
break;
case 3:
if (Boolean.getBoolean(value.toString()) == false
&& getValueAt(row, 0) != null
&& getValueAt(row, 1) != null
&& getValueAt(row, 2) != null) {
System.out.println("3. If - Added...");
getSubjectsList()[row][3] = new Boolean(true);
this.subjectListModel.addElement(this.subjectsList[row][0] +
* new String(" - ") + this.subjectsList[row][2]);
// subjectListModel.remove(row);
fireTableCellUpdated(row, col);
fireTableDataChanged();
// this.doDeleteSubject();
} else if (Boolean.getBoolean(value.toString()) ==
true
&& getValueAt(row, 0) != null
&& getValueAt(row, 1) != null
&& getValueAt(row, 2) != null) {
setValueAt("", row, col - 1);
setValueAt("", row, col - 2);
setValueAt("", row, col - 3);
System.out.println("3. Else - Cleared...");
// this.subjectListModel.remove(row);
break;
default:
break;
}// end switch
getSubjectsList()[row][col] = value;
fireTableCellUpdated(row, col);
fireTableDataChanged();
}// end if
}// end
* Function to enable edition for all the columns in the table
* @param row --
* the row that must be enabled.
* @param col --
* the col that must be enabled.
* @return boolean -- indicate whether this cell is editble or
not.
public boolean isCellEditable(int row, int col) {
if (row >= 0
&& (col >= 0 && col <= getNotEditable())) {
return false;
return true;
* Function to get the column names for the model
* @return Returns the columnNames.
public String[] getColumnNames() {
return this.columnNames;
* Function to set the column names for the model
* @param cols
* The columnNames to set.
public void setColumnNames(String[] cols) {
// if the column names are null the default columns are used
if (cols != null) {
this.columnNames = cols;
* Function to get the rows of subjects for the model
* @return Returns the subjectsList.
public Object[][] getSubjectsList() {
if (this.subjectsList == null) {
this.subjectsList = new
Object[getTotalRows()][getColumnNames().length];
return this.subjectsList;
* Function to set the subjects list for the model
* @param subjects
* The subjectsList to set.
public void setSubjectsList(Object[][] subjects) {
// if the subject list is null create a new one
// using default values
if (subjects == null) {
this.subjectsList = new
Object[getTotalRows()][getColumnNames().length];
return;
this.subjectsList = subjects;
* Function to get the total number of rows for the model. <b>NB:
</b> This
* is different to <code>
getRowCount()</code>.<code>totalRows</code>
* is the initial amount of rows that the model must have before
data can be
* added.
* @return Returns the totalRows.
* @see #setTotalRows(int)
public int getTotalRows() {
return this.totalRows;
* Function to set the total rows for the model.
* @param rows
* The totalRows to set.
* @see #getTotalRows()
public void setTotalRows(int rows) {
// if the rows are less than 0 the defaultRows are used
// set getTotalRows
if (rows > 0) {
this.totalRows = rows;
* Function to get the number of columns that is not editble
* @return Returns the notEditable.
public int getNotEditable() {
return this.notEditable;
* Function to set the number of columns that is not editable
* @param notEdit The notEditable to set.
public void setNotEditable(int notEdit) {
if (notEdit < 0) {
notEdit = 0;
this.notEditable = notEdit;
----------------------------END TABLE MODEL----------------------------------I hope you don't expect us to read hundreds of lines of unformatted code? Use the "formatting tags" when you post.
Why are you creating your own TableModel? It looks to me like the DefaultTableModel will store you data. Learn how to use JTable with its DefaultTableModel first. Then if you determine that DefaultTableModel doesn't provide the required functionality you can write your own model. -
I have a problem, The scenario is that when I click any folder that si in my JTable's first row, the table is update by removing all the rows and showing only the contents of my selected folder. Right now it's not removing the rows and instead throwing exceptions. The code is attached. The methods to look are upDateTabel(...) and clearTableData(....), after clearing all my rows then I proceed on adding my data to the Jtable and inserting rows but it's not being done. May be I have a problem in my DefaultTableModel class. Please see the code below what I am doing wrong and how should I do it. Any help is appreciated.
Thanks
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.table.*;
import javax.swing.border.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class SimpleTable extends JPanel{
/** Formats the date */
protected SimpleDateFormat formatter;
/** variable to hold the date and time in a raw form for the directory*/
protected long dateDirectory;
/** holds the readable form converted date for the directories*/
protected String dirDate;
/** holds the readable form converted date for the files*/
protected String fileDate;
/** variable to hold the date and time in a raw form for the file*/
protected long dateFile;
/** holds the length of the file in bytes */
protected long totalLen;
/** convert the length to the wrapper class */
protected Long longe;
/** Vector to hold the sub directories */
protected Vector subDir;
/** holds the name of the selected directory */
protected String dirNameHold;
/** converting vector to an Array and store the values in this */
protected File directoryArray[];
/** hashtable to store the key-value pair */
protected static Hashtable hashTable = new Hashtable();
/** refer to the TableModel that is the default*/
protected MyTableModel tableModel;
/** stores the path of the selected file */
protected static String fullPath;
/** stores the currently selected file */
protected static File selectedFilename;
/** stores the extension of the selected file */
protected static String extension;
protected int COLUMN_COUNT = 4;
protected Vector data = new Vector( 0, 1 );
protected final JTable table;
/** holds the names of the columns */
protected final String columnNames[] = {"Name", "Size", "Type", "Modified"};
public SimpleTable(File directoryArray[])
this.setLayout(new BorderLayout());
this.setBorder( BorderFactory.createEmptyBorder( 0, 0, 0, 0 ) );
(SimpleTable.hashTable).clear();
formatter = new SimpleDateFormat("mm/dd/yyyy hh:mm aaa");
for(int k = 0; k < directoryArray.length; k++)
if(directoryArray[k].isDirectory())
dateDirectory = directoryArray[k].lastModified();
dirDate = formatter.format(new java.util.Date(dateDirectory));
data.addElement( new MyObj( directoryArray[k].getName(), "", "File Folder", "" + dirDate ) );
(SimpleTable.hashTable).put(directoryArray[k].getName(), directoryArray[k]);
else if(directoryArray[k].isFile())
dateDirectory = directoryArray[k].lastModified();
fileDate = formatter.format(new java.util.Date(dateDirectory));
totalLen = directoryArray[k].length();
longe = new Long(totalLen);
data.addElement( new MyObj( directoryArray[k].getName(), longe + " Bytes", "", "" + fileDate ) );
(SimpleTable.hashTable).put(directoryArray[k].getName(), directoryArray[k]);
tableModel = new MyTableModel();
table = new JTable( tableModel );
table.getTableHeader().setReorderingAllowed(false);
table.setRowSelectionAllowed(false);
table.setBorder( BorderFactory.createEmptyBorder( 0, 0, 0, 0 ) );
table.setShowHorizontalLines(false);
table.setShowVerticalLines(false);
table.addMouseListener(new MouseAdapter()
public void mouseReleased(MouseEvent e)
Object eventTarget = e.getSource();
if( eventTarget == table )
upDateTable(table);
table.tableChanged( new javax.swing.event.TableModelEvent(tableModel) ) ;
DefaultTableCellRenderer D_headerRenderer = (DefaultTableCellRenderer ) table.getTableHeader().getDefaultRenderer();
table.getColumnModel().getColumn(0).setHeaderRenderer(D_headerRenderer );
((DefaultTableCellRenderer)D_headerRenderer).setToolTipText("File and Folder in the Current Folder");
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this window.
this.add(scrollPane, BorderLayout.CENTER);
* Searches the Hashtable and returns the path of the folder or the value.
public File findPath(String value)
return (File)((SimpleTable.hashTable).get(value));
* This clears the previous data in the JTable
public void clearTableData(JTable table)
for(int row = 0; row < table.getRowCount() ; row++)
//for (int col = 0; col < table.getColumnCount() ; col++)
tableModel.deleteSelections( row );
tableModel.fireTableStructureChanged();
tableModel.fireTableRowsDeleted(0,table.getRowCount());
//table.getModel().fireTableChanged(new TableModelEvent(table.getModel()));
private void upDateTable(JTable table)
if((table.getSelectedColumn() == 0) && ((table.getColumnName(0)).equals(columnNames[0])))
dirNameHold =(String) table.getValueAt(table.getSelectedRow(),table.getSelectedColumn());
File argument = findPath(dirNameHold);
if(argument.isFile())
CMRDialog.fileNameTextField.setText(argument.getName());
try
fullPath = argument.getCanonicalPath();
selectedFilename = argument.getCanonicalFile();
CMRDialog.filtersComboBox.removeAllItems();
extension = fullPath.substring(fullPath.lastIndexOf('.'));
CMRDialog.filtersComboBox.addItem("( " + extension + " )" + " File");
catch(IOException e)
System.out.println("THE ERROR IS " + e);
return;
else if(argument.isDirectory())
String path = argument.getName();
//find the system dependent file separator
//String fileSeparator = System.getProperty("file.separator");
CMRDialog.driveComboBox.addItem(" " + path);
subDir = Search.subDirs(argument);
/**TBD:- needs a method to convert the vector to an array and return the array */
directoryArray = new File[subDir.size()];
int indexCount = 0;
/** TBD:- This is inefficient way of converting a vector to an array */
Iterator e = subDir.iterator();
while( e.hasNext() )
directoryArray[indexCount] = (File)e.next();
indexCount++;
/** now calls this method and clears the previous data */
clearTableData(table);
(SimpleTable.hashTable).clear();
//data = new Object[this.getRowTotal(directoryArray)][this.getColumnTotal()];
formatter = new SimpleDateFormat("mm/dd/yyyy hh:mm aaa");
for(int k = 0; k < directoryArray.length; k++)
if(directoryArray[k].isDirectory())
dateDirectory = directoryArray[k].lastModified();
dirDate = formatter.format(new java.util.Date(dateDirectory));
data.addElement( new MyObj( directoryArray[k].getName(), "", "File Folder", "" + dirDate ) );
(SimpleTable.hashTable).put(directoryArray[k].getName(), directoryArray[k]);
else if(directoryArray[k].isFile())
dateDirectory = directoryArray[k].lastModified();
fileDate = formatter.format(new java.util.Date(dateDirectory));
totalLen = directoryArray[k].length();
longe = new Long(totalLen);
data.addElement( new MyObj( directoryArray[k].getName(), longe + " Bytes", "", "" + fileDate ) );
(SimpleTable.hashTable).put(directoryArray[k].getName(), directoryArray[k]);
// tableModel.fireTableDataChanged();
// tableModel.fireTableRowsInserted(0,1);
table.revalidate();
table.validate();
class MyTableModel extends DefaultTableModel
int totalRows;
int totalCols;
public MyTableModel()
super();
setColumnIdentifiers (columnNames);
this.totalRows = data.size();
this.totalCols = columnNames.length;
// this will return the row count of your table
public int getRowCount()
return totalRows;
// this return the column count of your table
public int getColumnCount()
return totalCols;
// this return the data for each cell in your table
public Object getValueAt(int row, int col)
MyObj obj = (MyObj)data.elementAt( row );
if( obj != null )
if( col == 0 ) return( obj.first );
else if( col == 1 ) return( obj.last );
else if( col == 2 ) return( obj.third );
else if( col == 3 ) return( obj.fourth );
else return( "" );
return "";
// if you want your table to be editable then return true
public boolean isCellEditable(int row, int col)
return false;
// if your table is editable edit the data vector here and
// call table.tableChanged(...)
public void setValueAt(Object value, int row, int col)
protected void deleteSelections (int rows)
try
removeRow(rows);
catch(ArrayIndexOutOfBoundsException e)
System.out.println("The error in the row index " + rows);
fireTableDataChanged() ;
class MyObj
String first;
String last;
String third;
String fourth;
public MyObj( String f, String l, String t, String fo )
this.first = f;
this.last = l;
this.third = t;
this.fourth = fo;
#####################################The following code works fine but it doesn't show me the new updated date in my JTable. I tried to print the values that I am getting and it does give the values on the prompt but doesn't show me on the JTable only first two are shown and the rest of the table is filled with the same values. I don't know what's going on and am tired of this TableModel thing so pla. take a time to give me some suggestions. Thanks
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.table.*;
import javax.swing.border.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class SimpleTable extends JPanel {
/** Formats the date */
protected SimpleDateFormat formatter;
/** two-dimensional array to hold the information for each column */
protected Object data[][];
/** variable to hold the date and time in a raw form for the directory*/
protected long dateDirectory;
/** holds the readable form converted date for the directories*/
protected String dirDate;
/** holds the readable form converted date for the files*/
protected String fileDate;
/** variable to hold the date and time in a raw form for the file*/
protected long dateFile;
/** holds the length of the file in bytes */
protected long totalLen;
/** convert the length to the wrapper class */
protected Long longe;
/** Vector to hold the sub directories */
protected Vector subDir;
/** holds the name of the selected directory */
protected String dirNameHold;
/** converting vector to an Array and store the values in this */
protected File directoryArray[];
/** hashtable to store the key-value pair */
protected static Hashtable hashTable = new Hashtable();
/** refer to the TableModel that is the default*/
protected DefaultTableModel model;
/** stores the path of the selected file */
protected static String fullPath;
/** stores the currently selected file */
protected static File selectedFilename;
/** stores the extension of the selected file */
protected static String extension;
protected Vector m = new Vector(0,1);
/** holds the names of the columns */
protected final String columnNames[] = {"Name", "Size", "Type", "Modified"};
public SimpleTable(File directoryArray[])
this.setLayout(new BorderLayout());
this.setBorder( BorderFactory.createEmptyBorder( 0, 0, 0, 0 ) );
(SimpleTable.hashTable).clear();
data = new Object[this.getRowTotal(directoryArray)][this.getColumnTotal()];
formatter = new SimpleDateFormat("mm/dd/yyyy hh:mm aaa");
for(int k = 0; k < directoryArray.length; k++)
if(directoryArray[k].isDirectory())
data[k][0] = directoryArray[k].getName();
data[k][2] = "File Folder";
dateDirectory = directoryArray[k].lastModified();
dirDate = formatter.format(new java.util.Date(dateDirectory));
data[k][3] = dirDate;
(SimpleTable.hashTable).put(directoryArray[k].getName(), directoryArray[k]);
else if(directoryArray[k].isFile())
data[k][0] = directoryArray[k].getName();
totalLen = directoryArray[k].length();
longe = new Long(totalLen);
data[k][1] = longe + " Bytes";
dateFile = directoryArray[k].lastModified();
fileDate = formatter.format(new java.util.Date(dateFile));
data[k][3] = fileDate;
(SimpleTable.hashTable).put(directoryArray[k].getName(), directoryArray[k]);
model = new DefaultTableModel();
model.addTableModelListener( new TableModelListener(){
public void tableChanged( javax.swing.event.TableModelEvent e )
System.out.println("************ I am inside the table changed method ********" );
final JTable table = new JTable(model);
table.getTableHeader().setReorderingAllowed(false);
table.setRowSelectionAllowed(false);
table.setBorder( BorderFactory.createEmptyBorder( 0, 0, 0, 0 ) );
table.setShowHorizontalLines(false);
table.setShowVerticalLines(false);
table.addMouseListener(new MouseAdapter()
/* public void mousePressed(MouseEvent e)
//System.out.println("The clicked component is " + table.rowAtPoint(e.getPoint()) + "AND the number of clicks is " + e.getClickCount());
/* if(e.getClickCount() >= 2 &&
(table.getSelectedColumn() == 0) &&
((table.getColumnName(0)).equals(columnNames[0])))
//System.out.println("The clicked component is " + table.rowAtPoint(e.getPoint()) + "AND the number of clicks is " + e.getClickCount());
upDateTable(table);
public void mouseReleased(MouseEvent e)
//System.out.println("The clicked component is " + table.rowAtPoint(e.getPoint()) + "AND the number of clicks is " + e.getClickCount());
/* if(e.getClickCount() >= 2 &&
(table.getSelectedColumn() == 0) &&
((table.getColumnName(0)).equals(columnNames[0]))) */
//System.out.println("The clicked component is " + table.rowAtPoint(e.getPoint()) + "AND the number of clicks is " + e.getClickCount());
upDateTable(table);
/** set the columns */
for(int c = 0; c < columnNames.length; c++)
model.addColumn(columnNames[c]);
/** set the rows */
for(int r = 0; r < data.length; r++)
model.addRow(data[r]);
DefaultTableCellRenderer D_headerRenderer = (DefaultTableCellRenderer ) table.getTableHeader().getDefaultRenderer();
table.getColumnModel().getColumn(0).setHeaderRenderer(D_headerRenderer );
((DefaultTableCellRenderer)D_headerRenderer).setToolTipText("File and Folder in the Current Folder");
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this window.
this.add(scrollPane, BorderLayout.CENTER);
* Returns the number of columns
public int getColumnTotal()
return columnNames.length;
* Returns the number of rows
public int getRowTotal(Object directoryArray[])
return directoryArray.length;
private void upDateTable(JTable table)
if((table.getSelectedColumn() == 0) && ((table.getColumnName(0)).equals(columnNames[0])))
dirNameHold =(String) table.getValueAt(table.getSelectedRow(),table.getSelectedColumn());
File argument = findPath(dirNameHold);
if(argument.isFile())
CMRDialog.fileNameTextField.setText(argument.getName());
try
fullPath = argument.getCanonicalPath();
selectedFilename = argument.getCanonicalFile();
CMRDialog.filtersComboBox.removeAllItems();
extension = fullPath.substring(fullPath.lastIndexOf('.'));
CMRDialog.filtersComboBox.addItem("( " + extension + " )" + " File");
catch(IOException e)
System.out.println("THE ERROR IS " + e);
return;
else if(argument.isDirectory())
String path = argument.getName();
//find the system dependent file separator
//String fileSeparator = System.getProperty("file.separator");
CMRDialog.driveComboBox.addItem(" " + path);
subDir = Search.subDirs(argument);
/**TBD:- needs a method to convert the vector to an array and return the array */
directoryArray = new File[subDir.size()];
int indexCount = 0;
/** TBD:- This is inefficient way of converting a vector to an array */
Iterator e = subDir.iterator();
while( e.hasNext() )
directoryArray[indexCount] = (File)e.next();
indexCount++;
/** now calls this method and clears the previous data */
clearTableData(table);
(SimpleTable.hashTable).clear();
data = new Object[this.getRowTotal(directoryArray)][this.getColumnTotal()];
formatter = new SimpleDateFormat("mm/dd/yyyy hh:mm aaa");
m.clear();
data = null;
data = new Object[this.getRowTotal(directoryArray)][this.getColumnTotal()];
for(int k = 0; k < directoryArray.length; k++)
if(directoryArray[k].isDirectory())
System.out.println("Inside the if part");
data[k][0] = directoryArray[k].getName();
table.setValueAt(directoryArray[k].getName(),k,0);
//model.fireTableCellUpdated(k,0);
data[k][2] = "File Folder";
table.setValueAt("File Folder",k,2);
//model.fireTableCellUpdated(k,2);
dateDirectory = directoryArray[k].lastModified();
dirDate = formatter.format(new java.util.Date(dateDirectory));
data[k][3] = dirDate;
table.setValueAt(dirDate,k,3);
//model.fireTableCellUpdated(k,3);
(SimpleTable.hashTable).put(directoryArray[k].getName(), directoryArray[k]);
m.add(data);
model.addRow(m);
model.fireTableDataChanged();
else if(directoryArray[k].isFile())
System.out.println("******* Inside the else part *******");
data[k][0] = directoryArray[k].getName();
System.out.println("The Name is == " + data[k][0]);
table.setValueAt(directoryArray[k].getName(),k,0);
System.out.println("The table cell value of the name is == " + table.getValueAt(k,0));
//model.fireTableCellUpdated(k,0);
totalLen = directoryArray[k].length();
longe = new Long(totalLen);
data[k][1] = longe + " Bytes";
System.out.println("The length == " + data[k][1]);
table.setValueAt(longe + " Bytes",k,1);
System.out.println("The table cell value of the length is == " + table.getValueAt(k,1));
//model.fireTableCellUpdated(k,0);
dateFile = directoryArray[k].lastModified();
fileDate = formatter.format(new java.util.Date(dateFile));
data[k][3] = fileDate;
System.out.println("The modified date == " + data[k][3]);
table.setValueAt(fileDate,k,3);
System.out.println("The table cell value of the name is == " + table.getValueAt(k,3));
//model.fireTableCellUpdated(k,0);
(SimpleTable.hashTable).put(directoryArray[k].getName(), directoryArray[k]); }
m.add(data);
model.addRow(m);
model.fireTableDataChanged();
// model.fireTableDataChanged();
// model.fireTableRowsInserted(0,1);
table.revalidate();
table.validate();
else
* Searches the Hashtable and returns the path of the folder or the value.
public File findPath(String value)
return (File)((SimpleTable.hashTable).get(value));
* This clears the previous data in the JTable
public void clearTableData(JTable table)
for(int row = 0; row < table.getRowCount() ; row++)
for (int col = 0; col < table.getColumnCount() ; col++)
table.setValueAt(null, row , col);
model.fireTableStructureChanged();
### -
Mapping of JTable Rows and columns and paint it to the JPanel
Hi,
I am using JTable and graphics object to draw the JTable on JPanel. But due to some lack of measurement I am not able to draw table cells correctly.
Apart from this on changing the fontSize I have to redraw it according to the requirement. But when the data size increases it draws absurdly.
I am using jTable.getCellRect() api to get the row width and height. Please help to redraw a JTable cell row and height on JPanel.
I am also attaching a sample code with this mail.
Thanks,
Ajay
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.*;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.table.*;
import java.util.*;
import java.awt.*;
public class SimpleTableDemo extends JPanel {
private boolean DEBUG = false;
private int spacing = 6;
private Map columnSizes = new HashMap();
String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};
Object[][] data = {
{"Kathy", "Smith",
"SnowboardingXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new Integer(5), new Boolean(false)},
{"John", "Doe",
"Rowing", new Integer(3), new Boolean(true)},
{"Sue", "Black",
"Knitting", new Integer(2), new Boolean(false)},
{"Jane", "White",
"Speed reading", new Integer(20), new Boolean(true)},
{"Joe", "Brown",
"Pool", new Integer(10), new Boolean(false)}
final JTable table = new JTable(data, columnNames);
Panel1 panel;
public SimpleTableDemo() {
super(new GridLayout(3,0));
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
//table.setFillsViewportHeight(true);
if (DEBUG) {
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
printDebugData(table);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this panel.
add(scrollPane);
panel = new Panel1();
Rectangle rect = table.getCellRect(0,0,true);
panel.setX(table.getWidth());
panel.setY(0);
panel.setWidth(rect.width);
panel.setHeight(rect.height);
panel.setStr(table.getModel().getValueAt(0,0).toString());
panel.setModel(table);
add(panel);
final JComboBox jNumberComboBoxSize = new JComboBox();
jNumberComboBoxSize.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "11", "12", "14", "16", "18", "20", "24", "30", "36", "48", "72" }));
jNumberComboBoxSize.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jNumberComboBoxSizeActionPerformed(jNumberComboBoxSize);
JPanel panel2 = new JPanel();
panel2.add(jNumberComboBoxSize);
add(panel2);
adjustColumns();
private void jNumberComboBoxSizeActionPerformed(JComboBox jNumberComboBoxSize)
int fontSize = Integer.parseInt(jNumberComboBoxSize.getSelectedItem().toString());
table.setRowHeight(fontSize);
table.setFont(new Font("Serif", Font.BOLD, fontSize));
Rectangle rect = table.getCellRect(0,0,true);
panel.setX(0);
panel.setY(0);
// panel.setWidth(rect.width);
panel.setHeight(rect.height);
panel.setStr(table.getModel().getValueAt(0,0).toString());
panel.setModel(table);
panel.repaint();
table.revalidate();
private void printDebugData(JTable table) {
int numRows = table.getRowCount();
int numCols = table.getColumnCount();
javax.swing.table.TableModel model = table.getModel();
System.out.println("Value of data: ");
for (int i=0; i < numRows; i++) {
System.out.print(" row " + i + ":");
for (int j=0; j < numCols; j++) {
System.out.print(" " + model.getValueAt(i, j));
System.out.println();
System.out.println("--------------------------");
* Adjust the widths of all the columns in the table
public void adjustColumns()
TableColumnModel tcm = table.getColumnModel();
for (int i = 0; i < tcm.getColumnCount(); i++)
adjustColumn(i);
* Adjust the width of the specified column in the table
public void adjustColumn(final int column)
TableColumn tableColumn = table.getColumnModel().getColumn(column);
if (! tableColumn.getResizable()) return;
int columnHeaderWidth = getColumnHeaderWidth( column );
int columnDataWidth = getColumnDataWidth( column );
int preferredWidth = Math.max(columnHeaderWidth, columnDataWidth);
panel.setWidth(preferredWidth);
updateTableColumn(column, preferredWidth);
* Calculated the width based on the column name
private int getColumnHeaderWidth(int column)
TableColumn tableColumn = table.getColumnModel().getColumn(column);
Object value = tableColumn.getHeaderValue();
TableCellRenderer renderer = tableColumn.getHeaderRenderer();
if (renderer == null)
renderer = table.getTableHeader().getDefaultRenderer();
Component c = renderer.getTableCellRendererComponent(table, value, false, false, -1, column);
return c.getPreferredSize().width;
* Calculate the width based on the widest cell renderer for the
* given column.
private int getColumnDataWidth(int column)
int preferredWidth = 0;
int maxWidth = table.getColumnModel().getColumn(column).getMaxWidth();
for (int row = 0; row < table.getRowCount(); row++)
preferredWidth = Math.max(preferredWidth, getCellDataWidth(row, column));
// We've exceeded the maximum width, no need to check other rows
if (preferredWidth >= maxWidth)
break;
return preferredWidth;
* Get the preferred width for the specified cell
private int getCellDataWidth(int row, int column)
// Inovke the renderer for the cell to calculate the preferred width
TableCellRenderer cellRenderer = table.getCellRenderer(row, column);
Component c = table.prepareRenderer(cellRenderer, row, column);
int width = c.getPreferredSize().width + table.getIntercellSpacing().width;
return width;
* Update the TableColumn with the newly calculated width
private void updateTableColumn(int column, int width)
final TableColumn tableColumn = table.getColumnModel().getColumn(column);
if (! tableColumn.getResizable()) return;
width += spacing;
// Don't shrink the column width
width = Math.max(width, tableColumn.getPreferredWidth());
columnSizes.put(tableColumn, new Integer(tableColumn.getWidth()));
table.getTableHeader().setResizingColumn(tableColumn);
tableColumn.setWidth(width);
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("SimpleTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
SimpleTableDemo newContentPane = new SimpleTableDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
class Panel1 extends JPanel
int x;
int y;
int width;
int height;
String str;
JTable model;
public void setModel(JTable model)
this.model = model;
public void setX(int x)
this.x = x;
public void setY(int y)
this.y = y;
public void setWidth(int w)
this.width = w;
public void setHeight(int h)
this.height = h;
public void setStr(String s)
this.str = s;
public void paint(Graphics g)
super.paint(g);
int initX= 0;
for(int row=0;row < 5; ++row)
initX = x;
for (int col=0;col < 5;++col)
g.drawRect(x,y,width,height);
g.drawString(model.getModel().getValueAt(row,col).toString(),x + 10,y + 10);
x = x + width;
x = initX;
y = y + height;
};an easy way would be to use setSize()
-
Multi coloured spinning cursor and mac air keeps freezing?
multi coloured spinning cursor and mac air keeps freezing?
Force Quit .
Press command + option + esc keys together at the same time for 3 seconds. Wait.
When Force Quit window appears, select the application if not already.
Press Force Quit button at the bottom of the window. Wait.
Application will quit.
http://support.apple.com/kb/HT3411
Start up in Safe Mode.
http://support.apple.com/kb/PH11212?viewlocale=en_US -
How to know the row and col numbers of a cell in JTable at mouseclicked
Hi, I'm coding an app using swing and JTable, in this table I will display the records from a database, now, each time the user has click in any cell I want to display it value, whit this method:
private void setpuntero(JTable table, int row, int col){
Object o = table.getValueAt(row, col);
System.out.println("Valor de la celda: "+o.toString());
}The mouseclick event was coded like this:
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
setpuntero(table, 1, 3);
});My question is:
how in the mouseClicked I can pass to setpuntero() method the dynamic values of the cell that the user clicked?
In this example, setpuntero(table, 1, 3); I have chosen the cell(1,3) to display the value, but really I don't know how to capture those values dinamically using the mouse click
Regards
Herbertperhaps:
public void mouseClicked(MouseEvent e)
int row = table.getSelectedRow();
int col = table.getSelectedColumn();
String selected = table.getValueAt(row, col).toString(); // this will need to be changed if not String data
} -
How to set the Selected row and Column in JTable
Hi,
i have a problem like the JTable having one Method getSelectedRow() and getSelectedColumn to know the Selected row and Column but if i want to explicitly set the Selected Row and Column,then there is no such type of Methods.If anybody has any solution then i will be thankful to him/her.
Praveen K SaxenaIs that what you're looking for? :myTable.getSelectionModel().setSelectionInterval(row, row);
myTable.getColumnModel().getSelectionModel().setSelectionInterval(column, column); -
JTable fixed Row and Column in the same window
Hi
Could anyone tip me how to make fixed row and column in the same table(s).
I know how to make column fixed and row, tried to combine them but it didnt look pretty.
Can anyone give me a tip?
Thanks! :)Got it to work!
heres the kod.. nothing beautiful, didnt clean it up.
* NewClass.java
* Created on den 29 november 2007, 12:51
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
package tablevectortest;
* @author Sockan
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
public class FixedRowCol extends JFrame {
Object[][] data;
Object[] column;
JTable fixedTable,table,fixedColTable,fixedTopmodelTable;
private int FIXED_NUM = 16;
public FixedRowCol() {
super( "Fixed Row Example" );
data = new Object[][]{
{ "","A","A","A","",""},
{ "a","b","","","",""},
{ "a","","c","","",""},
{ "","","","d","",""},
{ "","","","","e",""},
{ "","","","","","f"},
{ "","b","","","",""},
{ "","","c","","",""},
{ "","","","d","",""},
{ "","","","","e",""},
{ "","b","","","",""},
{ "","","c","","",""},
{ "","","","d","",""},
{ "","","","","e",""},
{ "","","","","","f"},
{ "I","","W","G","A",""}};
column = new Object[]{"A","B","C","D","E","F"};
AbstractTableModel fixedColModel = new AbstractTableModel() {
public int getColumnCount() {
return 1;
public int getRowCount() {
return data.length;
public String getColumnName(int col) {
return (String) column[col];
public Object getValueAt(int row, int col) {
return data[row][col];
public boolean CellEditable(int row, int col) {
return true;
AbstractTableModel model = new AbstractTableModel() {
public int getColumnCount() { return column.length-2; }
public int getRowCount() { return data.length - FIXED_NUM; }
public String getColumnName(int col) {
return (String)column[col+1];
public Object getValueAt(int row, int col) {
return data[row][col+1];
public void setValueAt(Object obj, int row, int col) {
data[row][col+1] = obj;
public boolean CellEditable(int row, int col) {
return true;
AbstractTableModel fixedTopModel = new AbstractTableModel() {
public int getColumnCount() { return 1; }
public int getRowCount() { return data.length - FIXED_NUM; }
public String getColumnName(int col) {
return (String)column[col];
public Object getValueAt(int row, int col) {
return data[row][col];
public void setValueAt(Object obj, int row, int col) {
data[row][col] = obj;
public boolean CellEditable(int row, int col) {
return true;
AbstractTableModel fixedModel = new AbstractTableModel() {
public int getColumnCount() { return column.length-2; }
public int getRowCount() { return FIXED_NUM; }
public Object getValueAt(int row, int col) {
return data[row + (data.length - FIXED_NUM)][col+1];
table = new JTable( model );
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fixedTable = new JTable( fixedModel );
fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
fixedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fixedColTable= new JTable(fixedColModel);
fixedColTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
fixedColTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fixedTopmodelTable = new JTable(fixedTopModel);
fixedTopmodelTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
fixedTopmodelTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane scroll = new JScrollPane( table );
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JScrollPane fixedScroll = new JScrollPane( fixedTable ) {
public void setColumnHeaderView(Component view) {}
fixedScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
fixedScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
JScrollBar bar = scroll.getVerticalScrollBar();
JScrollBar dummyBar = new JScrollBar() {
public void paint(Graphics g) {}
dummyBar.setPreferredSize(bar.getPreferredSize());
scroll.setVerticalScrollBar(dummyBar);
final JScrollBar bar1 = scroll.getHorizontalScrollBar();
JScrollBar bar2 = fixedScroll.getHorizontalScrollBar();
bar2.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
bar1.setValue(e.getValue());
JViewport viewport = new JViewport();
viewport.setView(fixedColTable);
viewport.setPreferredSize(fixedColTable.getPreferredSize());
fixedScroll.setRowHeaderView(viewport);
fixedScroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixedColTable
.getTableHeader());
JViewport viewport2 = new JViewport();
viewport2.setView(fixedTopmodelTable);
viewport2.setPreferredSize(fixedTopmodelTable.getPreferredSize());
scroll.setRowHeaderView(viewport2);
scroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixedTopmodelTable
.getTableHeader());
scroll.setPreferredSize(new Dimension(600, 19));
fixedScroll.setPreferredSize(new Dimension(600, 100));
getContentPane().add( scroll, BorderLayout.NORTH);
getContentPane().add(fixedScroll, BorderLayout.CENTER);
public static void main(String[] args) {
FixedRowCol frame = new FixedRowCol();
frame.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit(0);
frame.pack();
frame.setVisible(true);
} -
How to freeze row and column in JTable
Hi,
I need to freeze first two rows and columns in a large JTable. I found ways to freeze either a row or a column, but not both at the same time.
Can any of you help ?
Found this code which allows freezing a col. Similar method can be used to freeze column
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableModel;
public class FrozenTablePane extends JScrollPane{
public FrozenTablePane(JTable table, int colsToFreeze){
super(table);
TableModel model = table.getModel();
//create a frozen model
TableModel frozenModel = new DefaultTableModel(
model.getRowCount(),
colsToFreeze);
//populate the frozen model
for (int i = 0; i < model.getRowCount(); i++) {
for (int j = 0; j < colsToFreeze; j++) {
String value = (String) model.getValueAt(i, j);
frozenModel.setValueAt(value, i, j);
//create frozen table
JTable frozenTable = new JTable(frozenModel);
//remove the frozen columns from the original table
for (int j = 0; j < colsToFreeze; j++) {
table.removeColumn(table.getColumnModel().getColumn(0));
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
//format the frozen table
JTableHeader header = table.getTableHeader();
frozenTable.setBackground(header.getBackground());
frozenTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
frozenTable.setEnabled(false);
//set frozen table as row header view
JViewport viewport = new JViewport();
viewport.setView(frozenTable);
viewport.setPreferredSize(frozenTable.getPreferredSize());
setRowHeaderView(viewport);
setCorner(JScrollPane.UPPER_LEFT_CORNER, frozenTable.getTableHeader());
}Hi,
I need to freeze first two rows and columns in a large JTable. I found ways to freeze either a row or a column, but not both at the same time.
Can any of you help ?
Found this code which allows freezing a col. Similar method can be used to freeze column
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableModel;
public class FrozenTablePane extends JScrollPane{
public FrozenTablePane(JTable table, int colsToFreeze){
super(table);
TableModel model = table.getModel();
//create a frozen model
TableModel frozenModel = new DefaultTableModel(
model.getRowCount(),
colsToFreeze);
//populate the frozen model
for (int i = 0; i < model.getRowCount(); i++) {
for (int j = 0; j < colsToFreeze; j++) {
String value = (String) model.getValueAt(i, j);
frozenModel.setValueAt(value, i, j);
//create frozen table
JTable frozenTable = new JTable(frozenModel);
//remove the frozen columns from the original table
for (int j = 0; j < colsToFreeze; j++) {
table.removeColumn(table.getColumnModel().getColumn(0));
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
//format the frozen table
JTableHeader header = table.getTableHeader();
frozenTable.setBackground(header.getBackground());
frozenTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
frozenTable.setEnabled(false);
//set frozen table as row header view
JViewport viewport = new JViewport();
viewport.setView(frozenTable);
viewport.setPreferredSize(frozenTable.getPreferredSize());
setRowHeaderView(viewport);
setCorner(JScrollPane.UPPER_LEFT_CORNER, frozenTable.getTableHeader());
} -
Select row and column from header in jtable
hello i have a problem to select row and column from header in jtable..
can somebody give me an idea on how to write the program on it.Hi Vicky Liu,
Thank you for your reply. I'm sorry for not clear question.
Answer for your question:
1. First value of Open is item fiels in Dataset2 and this value only for first month (january). But for other month Open value get from Close in previous month.
* I have 2 Dataset , Dataset1 is all data for show in my report. Dataset2 is only first Open for first month
2. the picture for detail of my report
Detail for Red number:
1. tb_Open -> tb_Close in previous month but first month from item field in Dataset2
espression =FormatNumber(Code.GetOpening(Fields!month.Value,First(Fields!open.Value, "Dataset2")))
2. tb_TOTAL1 group on item_part = 1
expression =FormatNumber(Sum(CDbl(Fields!budget.Value)))
3. tb_TOTAL2 group on item_part = 3 or item_part = 4
expression =FormatNumber(Sum(CDbl(Fields!budget.Value)) + ReportItems!tb_TOTAL1.Value )
4. tb_TOTAL3 group on item_part = 2
expression =FormatNumber(Sum(CDbl(Fields!budget.Value)) - ReportItems!tb_TOTAL2 .Value)
5. tb_Close -> calculate from tb_TOTAL3 - tb_Open
expression =FormatNumber(Code.GetClosing(ReportItems!tb_TOTAL3.Value,ReportItems!tb_Open.Value))
I want to calculate the value of tb_Open and tb_Close. I try to use custom code for calculate them. tb_close is correct but tb_Open is not correct that show value = 0 .
My custom code:
Dim Shared prev_close As Double
Dim Shared now_close As Double
Dim Shared now_open As Double
Public Function GetClosing(TOTAL3 as Double,NowOpening as Double)
now_close = TOTAL3 + NowOpening
prev_close = now_close
Return now_close
End Function
Public Function GetOpening(Month as String,NowOpen as Double)
If Month = "1" Then
now_open = NowOpen
Else
now_open = prev_close
End If
Return now_open
End Function
Thanks alot for your help!
Regards
Panda A
Maybe you are looking for
-
Replaced display even WORSE !!!
*I am so frustrated with Apple and its policy to repair and replace their defective products.* Ok, my iMac G5 is almost three years, I bought AppleCare, which is about to expire... that's my main concern as my iMac display started to go bad these las
-
No way to get a free recovery disc?
So I spend $740 to buy this Toshiba Laptop and now I am unable to reinstall windows after having corrupt files and because Toshiba decided to be cheap and not provide recovery discs. What genius decided to add important recovery files on the hard dri
-
My main file displays a large number of dynamically generated graphics. I have a listener to remove and then re-position the graphics if the browser is re-sized: stage.addEventListener(Event.RESIZE, stageResized) //When stage is resized, remove all c
-
Why is the screen cropped?
Now my Netflix programming is cropped on the sides as if I had one of those ancient narrow obsolete TVs, and there's no apparent adjustment.
-
Greetings. I've got following problem, wich seems to be related with SunWS cache. I try following simple program: #include <algorithm> #include <functional> #include <iostream> #include <vector> using namespace std; struct A { int process2(int i) { c