How to set Font in JTable
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11

Thread: How to set Font in JTable

  1. #1
    Guest

    How to set Font in JTable

    Hi,
    I need to set font for a particular column. I did the foll:

    TableColumn col0 = colmodel.getColumn(0);
    DefaultTableCellRenderer cellrenderer = new DefaultTableCellRenderer();
    cellrenderer.setFont(new Font("Arial", Font.BOLD, 12));
    col0.setCellRenderer(cellrenderer);
    cellrenderer.repaint();

    But this didn't work. The column font doesnt change at all at run time.

    Any ideas??? Someone must have done this already.




  2. #2
    Guest

    Re: How to set Font in JTable

    Hi there,

    I have the same problem you are facing.
    You try to change the font of the cell in column.
    I try to change the font of the cell in header.
    I was told to call the fireTableChanged from the TableModel of the JTable.
    I am still working on it.

    I wish I could be more helpful ...

    Good luck.



  3. #3
    Join Date
    Aug 2008
    Posts
    1

    Re: How to set Font in JTable

    I realize this thread is real old, but maybe this will help someone else.
    calling cellrenderer.setFont(...) doesn't work. Don't know why.
    If you want to set the font for a particular column you can subclass DefaultTableCellRenderer and override its getTableCellRendererComponent(...) method, then set your column renderer to use your subclass.
    Something like this:
    <code>
    DefaultTableCellRenderer rdr = new DefaultTableCellRenderer() {
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,boolean hasFocus, int row, int column) {
    if (value == null)
    return super.getTableCellRendererComponent(table,
    value, isSelected, hasFocus, row, column);
    JLabel label = new JLabel(value.toString());
    label.setFont(new Font("Helvetica Bold", Font.ITALIC,12));
    return label;
    }
    };

    tableColumn.setCellRenderer(rdr);
    </code>

  4. #4
    Join Date
    Apr 2007
    Posts
    442

    Re: How to set Font in JTable

    tnjed111 is on te right track. However a few additions.

    DefaultTableCellRenderer is in its self a JLabel, so you have no need to create another one in the method. All you can do to JLabel you can reference through this in a DefaulTableCellRenderer.

    Also, in most cases, especially if your primary interest is only on changing a font. You do want to call super method. Have it handle to focused, selected etc, and you then override the changes where appropriate. This way the table cell will be different where wanted, else consistent with the look of other cells.

    To set font etc. to the columns header, you find the right TableColumn and call setHeaderRenderer(...) on that TableColumn. Incidentally, if you want to specify a renderer for all cell of a column, call setCellRenderer(...) on that column.

    You get the TableColumns from tables column model (aka. TableColumnModel), by calling getColumn(...)

  5. #5
    Join Date
    Dec 2009
    Posts
    4

    Re: How to set Font in JTable

    After reading through the preceding suggestions and struggling with getting the table to do what I wanted, I found something that works well, and has the advantage of efficiency. The whole thing was such a pain that I just had to sign up here and give something back.

    Having a cell renderer which extends DefaultTableCellRenderer is the right thing to do, but having it return a custom made JLabel for the cells is not. DefaultTableCellRenderer itself extends JLabel, but has important changes to improve the speed of the table display. Returning a JLabel undoes all of that. It also loses all the logic for setting the cell colors differently for selected or focused cells.

    You might think that simply calling setFont(Font customFont) on the instance of the
    DefaultTableCellRenderer already used by the JTable would do what you want, but it does not.

    However, if you extend the class and override Font getFont() to return the font you want to use, everything works great, and you don't lose any of the speed or color logic.

    import javax.swing.JTable;
    public class MyTable extends JTable {
    public MyTable(Font customFont) {
    FontMetrics metrics = getFontMetrics(customFont);
    int fontHeight = metrics.getHeight();
    setRowHeight(fontHeight);

    StringCellRenderer stringCellRenderer = new StringCellRenderer(customFont);
    NumberCellRenderer numberCellRenderer = new NumberCellRenderer(customFont);

    // assume you added some columns here
    TableColumn someStringColumn columnModel.getColumn(0);
    TableColumn someNumberColumn columnModel.getColumn(1);

    someStringColumn.setCellRenderer(stringCellRenderer);
    someNumberColumn.setCellRenderer(numberCellRenderer);
    }
    }

    Use this renderer for columns displaying strings, or values which should be left-justifed:

    import javax.swing.table.DefaultTableCellRenderer;
    public class StringCellRenderer extends DefaultTableCellRenderer {

    private Font customFont;

    public StringCellRenderer(Font customFont) {
    this.customFont = customFont;
    setFont(customFont);
    }

    @Override
    public Font getFont() {
    return customFont;
    }
    }

    Use this class for columns displaying numbers, or values which should be right-justified:

    import javax.swing.table.DefaultTableCellRenderer;
    public class NumberCellRenderer extends StringCellRenderer {

    public NumberCellRenderer(Font customFont) {
    super(customFont);
    setHorizontalAlignment(SwingConstants.RIGHT);
    }
    }

  6. #6
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: How to set Font in JTable

    Quote Originally Posted by eleutieri View Post
    Having a cell renderer which extends DefaultTableCellRenderer is the right thing to do, but having it return a custom made JLabel for the cells is not. DefaultTableCellRenderer itself extends JLabel, but has important changes to improve the speed of the table display. Returning a JLabel undoes all of that. It also loses all the logic for setting the cell colors differently for selected or focused cells.
    Well quite - that's why Londbrok took the trouble to explain how it should be done - he assumed people knew to override the getTableCellRendererComponent(..) method.

    You might think that simply calling setFont(Font customFont) on the instance of the DefaultTableCellRenderer already used by the JTable would do what you want, but it does not.
    Because the renderer instance font (and other properties) is reset in the getTableCellRendererComponent(..) method for every cell. You have to change it after that method call, which means overriding the call, which means providing your own TableCellRenderer.

    However, if you extend the class and override Font getFont() to return the font you want to use, everything works great, and you don't lose any of the speed or color logic.
    That's fine if you want to set a single font for the whole table, or for a single column, you can have a renderer for each, but you lose all the information supplied by the table to the renderer for each cell. How do you change the font for a specific cell or a specific value, or depending on the focus or selected property of the cell?

    The getTableCellRendererComponent method is there to be overridden to do custom rendering. See Using Custom Renderers.

    The simplest and most flexible way to set the font in a table is to override the DefaultTableCellRenderer like this:
    Code:
    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {
        // override renderer preparation
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                       boolean hasFocus,
                                                       int row, int column)
        {
            // allow default preparation
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    
            // replace default font
            setFont(new Font("Helvetica Bold", Font.ITALIC, 22));
            return this;
        }
    };
    This method has the table, the cell value, the cell selection and focus, and the cell row and column all in context, so you can use them all to decide whether to change the font and what font to use.

    Purists might want to do it like this (i.e. assuming no knowledge of the superclass implementation):
    Code:
    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {
        // override renderer preparation
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                       boolean hasFocus,
                                                       int row, int column)
        {
            // allow default preparation
            Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    
            // replace default font
            comp.setFont(new Font("Helvetica Bold", Font.ITALIC, 22));
            return comp;
        }
    };
    The cheapest, fastest, and most reliable components of a computer system are those that aren't there...
    G. Bell
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  7. #7
    Join Date
    Dec 2009
    Posts
    4

    Re: How to set Font in JTable

    Quote Originally Posted by dlorde View Post
    The simplest and most flexible way to set the font in a table is to override the DefaultTableCellRenderer like this:
    Code:
    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {
        // override renderer preparation
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                       boolean hasFocus,
                                                       int row, int column)
        {
            // allow default preparation
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    
            // replace default font
            setFont(new Font("Helvetica Bold", Font.ITALIC, 22));
            return this;
        }
    };
    I tried some code very similar to that, which didn't work. It was like this:
    Code:
    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {
        // override renderer preparation
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                       boolean hasFocus,
                                                       int row, int column)
        {
            Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    
            cell.setFont(new Font("Helvetica Bold", Font.ITALIC, 22));
            return cell;
        }
    };
    My theory as to why it didn't work was that the look-and-feel was subsequently setting the font back to the default, before the cell was rendered, or that somewhere in the class hierarchy, something was interfering with me setting the font, but I was not able to find the definitive cause. I also had the feeling, based on checking the class type returned for the cell that the renderer was returning itself, which agrees with the description in the Javadoc of how it works. If that is the case, then the two methods above are effectively identical.

  8. #8
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: How to set Font in JTable

    Quote Originally Posted by eleutieri View Post
    I tried some code very similar to that, which didn't work.
    That is identical to my second 'purists' example. It's always worked for me.

    My theory as to why it didn't work was that the look-and-feel was subsequently setting the font back to the default, before the cell was rendered, or that somewhere in the class hierarchy, something was interfering with me setting the font, but I was not able to find the definitive cause.
    OK. As far as I know, the method I gave is the recommended way to change the rendering properties for a cell - it's what Sun use in their examples. If something is interfering, it may well be badly or wrongly implemented. If you can post an example that demonstrates the problem, I'll be happy to have a look at it.

    I also had the feeling, based on checking the class type returned for the cell that the renderer was returning itself, which agrees with the description in the Javadoc of how it works. If that is the case, then the two methods above are effectively identical.
    Yes, effectively identical in practice - although the version that uses and returns a reference is more technically correct in terms of Best Practice, as it doesn't rely on knowledge of the superclass implementation (it relies only on the API), as I tried to point out in my previous message.

    Any programming problem can be solved by adding a level of indirection...
    Anon.
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  9. #9
    Join Date
    Dec 2009
    Posts
    4

    Re: How to set Font in JTable

    The reason I had a problem with setting a font size for the table cells was because of the overloading of deriveFont(), which can take an int parameter for style, or a float for size. I wanted to simply change the size of the existing font, rather than worry about which actual font to use.

    To demonstrate that both overriding getFont() and calling setFont() in a subclass of the DefaultTableCellRenderer work, and the effects of different approaches, I created a complete test program:
    Code:
    import java.awt.Component;
    import java.awt.Container;
    import java.awt.Font;
    import java.awt.FontMetrics;
    
    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTable;
    import javax.swing.border.TitledBorder;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.TableColumn;
    import javax.swing.table.TableColumnModel;
    
    public class TableTest extends JFrame {
    
    	private Object[] columnNames = {"Col1", "Col2", "Col3"};
    	private Object[][] rowData = {
    		{"Abc", "Def", "Ghi"}, {"Jkl", "Mno", "Pqr"}, {"Stu", "Vwx", "Yz"}
    	};
    	private Font customFont = new Font("Helvetica Bold", Font.PLAIN, 18);
    	
    	public TableTest() {
    		Container contentPane = getContentPane();
    		contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
    		add(wrappedTable("using setFont, non-derived", false, false, false));
    		add(wrappedTable("using getFont, non-derived", true, false, false));
    		add(wrappedTable("using setFont, derived (int)", false, true, false));
    		add(wrappedTable("using getFont, derived (int)", true, true, false));
    		add(wrappedTable("using setFont, derived (float)", false, true, true));
    		add(wrappedTable("using getFont, derived (float)", true, true, true));
    		pack();
    	}
    
    	private JPanel wrappedTable(String title, boolean useGetFont,
    			boolean deriveNewFont, boolean castToFloat) {
    		JPanel panel = new JPanel();
    		panel.setBorder(new TitledBorder(title));
    		panel.add(getTable(useGetFont, deriveNewFont, castToFloat));
    		return panel;
    		
    	}
    	private JTable getTable(boolean useGetFont, boolean deriveNewFont, 
    			boolean castToFloat) {
    		JTable table = new JTable(rowData, columnNames);
    		FontMetrics metrics = table.getFontMetrics(customFont);
    		table.setRowHeight(metrics.getHeight()); // set row height to match font
    		CellRenderer cellRenderer =	new CellRenderer(customFont, useGetFont,
    				deriveNewFont, castToFloat);
    		TableColumnModel columnModel = table.getColumnModel();
    		for (int i = 0; i < columnModel.getColumnCount(); i++) {
    			TableColumn column = columnModel.getColumn(i);
    			column.setCellRenderer(cellRenderer);
    		}
    		return table;
    	}
    
        public static void main(String[] args) {
        	TableTest test = new TableTest();
        	test.setVisible(true);
        }
    	
    	public static class CellRenderer extends DefaultTableCellRenderer {
    
    		private Font customFont;
    	    private boolean overrideGetFont;
    	    private boolean deriveNewFont;
    	    private boolean castToFloat;
    	    
    		public CellRenderer(Font customFont, boolean overrideGetFont,
    				boolean deriveNewFont, boolean castToFloat) {
    			this.customFont = customFont;
    			this.overrideGetFont = overrideGetFont;
    			this.deriveNewFont = deriveNewFont;
    			this.castToFloat = castToFloat;
    		}
    
    		public Font getFont() {
    			if (!overrideGetFont) {
    				return super.getFont();
    			}
    			if (deriveNewFont) {
    				Font oldFont = super.getFont();
    				int fontSize = customFont.getSize();
    				if (castToFloat) {
    					return oldFont.deriveFont((float) fontSize);
    				}
    				else {
    					// Here's the problem I tripped over...
    					return oldFont.deriveFont(fontSize);
    				}
    			}
    			else {
    				return customFont;
    			}
    		}
    
    		public Component getTableCellRendererComponent(	JTable table,
    				Object value, boolean isSelected, boolean hasFocus,
    				int row, int column) {
    			super.getTableCellRendererComponent(table,	value,
    					isSelected, hasFocus, row, column);
    			if (!overrideGetFont) {
    				if (deriveNewFont) {
    					Font oldFont = super.getFont();
    					int fontSize = customFont.getSize();
    					Font newFont = null;
    					if (castToFloat) {
    						newFont = oldFont.deriveFont((float) fontSize);
    					}
    					else {
    						// Here's the problem I tripped over...
    						newFont = oldFont.deriveFont(fontSize);
    					}
    					setFont(newFont);
    				}
    				else {
    					setFont(customFont);
    				}
    			}
    			return this;
    		}
    	}
    }

  10. #10
    Join Date
    Dec 2009
    Posts
    4

    How to set Fonts in JTable with 3rd Party LnF

    Here is another way to set the font for a table, in your own subclass of JTable. It also shows how to set a different foreground color for the last row in the table, which might for example be holding column totals. I found this to work better when using 3rd party look-and-feels, in particular Substance.

    Code:
    public class MyTable extends JTable {
    
    	private static final Color TOTALS_ROW_FOREGROUND = Color.BLUE;
    	
    	private Font customFont;
    	private int customRowHeight;
    
    	public MyTable(int customFontSize) {
    		// Create font based on desired font size.
    		customFont = getFont().deriveFont((float) customFontSize);
    
    		// Get the actual height of the custom font.
    		FontMetrics metrics = getFontMetrics(customFont);
    		customRowHeight = metrics.getHeight();
    
    		// Set table row height to match font height.
    		setRowHeight(customRowHeight);
    	}
    
    	/**
    	 * Override <tt>getRowHeight()</tt> so that look-and-feels which do not use
    	 * the default table cell renderer (for example Substance) use the desired
    	 * row height.
    	 */
    	@Override
    	public int getRowHeight() {
    		if (customRowHeight > 0) {
    			return customRowHeight;
    		}
    		return super.getRowHeight();
    	}
    
    	/**
    	 * Override <tt>prepareRenderer()</tt> to set the font size in the instances
    	 * of the cell renderers returned by the look-and-feel's renderer.
    	 * <p>
    	 * Extending <tt>DefaultTableCellRenderer</tt>, setting the font in method
    	 * <tt>getTableCellRendererComponent()</tt>, and setting the columns to use
    	 * the custom renderer does work with the built-in look-and-feels. It also
    	 * works sufficiently with other look-and-feels, but some of these normally
    	 * supply their own table cell renderers, and setting a custom renderer
    	 * means that some of the functionality of the look-and-feel's renderer is
    	 * lost. For example, with Substance, one loses the different backgrounds
    	 * for alternate rows.
    	 * <p>
    	 * By overriding the table's prepareRenderer() method instead, the
    	 * functionality of the look-and-feel's renderer is retained.
    	 */
    	public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
    		Component c = super.prepareRenderer(renderer, row, column);
    		if (customFont != null) {
    			c.setFont(customFont);
    			fontSet = true;
    			if (row == getRowCount() - 1) {
    				// Set different foreground color for Totals row.
    				c.setForeground(TOTALS_ROW_FOREGROUND);
    			}
    			else {
    				// Reset foreground color so that default is used.
    				c.setForeground(null);
    			}
    		}
    		return c;
    	}
    }

  11. #11
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: How to set Font in JTable

    Cool - this is good stuff, keep it coming

    Give me a fish and I eat for a day. Teach me to fish and I eat for a lifetime...
    Chinese proverb
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center