I have set the default font in my JTable as show below
myTable.setFont(new java.awt.Font("Verdana", 1, 10));
I wanted to show a bigger font in my JTable,while some data is being typed into the cells.So I used MyTableCellEditor custom class.
public class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor {
JComponent component = new JTextField();
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
int rowIndex, int vColIndex) {
((JTextField) component).setText((String) value);
((JTextField) component).setFont(new Font("Verdana", 1, 12));
return component;
}
public Object getCellEditorValue() {
return ((JTextField) component).getText();
}
}
Below is the code where I attached the CustomCellEditor to my table.
myTable.getColumnModel().getColumn(1).setCellEditor(new MyTableCellEditor());
But this code do not seem to work.The cells font becomes small while editing and once I finish editing and hit enter,the default JTable font which I set ( Verdana 10 ) takes effect.Why is this happening ? I have already set CustomCellEditor font as ( Verdana 12 ) to my cells.
Don't create a new class for this. Just change the property of the DefaultCellEditor:
JTextField textField = new JTextField();
textField.setFont(new Font("Verdana", 1, 12));
textField.setBorder(new LineBorder(Color.BLACK));
DefaultCellEditor dce = new DefaultCellEditor( textField );
myTable.getColumnModel().getColumn(1).setCellEditor(dce);
Related
for this, I tried this method
table.setFont(new Font("Lucida Console", Font.PLAIN, 18));
but by using this I cannot find the appropriate Font at the time of Writing in the cell of the JTable.
I attach an image so you can find my question clearly .in this image u can see that at the time of writing font is small but after going to the next cell it becomes to change but I want that big font you can see that in image at the time of writing in the cell.
The problem is that table.setFont(new Font("Lucida Console", Font.PLAIN, 18)); will set the font of the cells when not being edited, it will not even set the font of the header. When editing, you have override the default setup by defining your own DefaultCellEditor. There are two ways to do so, the first (easier and cleaner) way is to create a JTextField and customize it the way you like and then pass it to the DefaultCellEditor constructor. The second (longer and not as clean) way is to override the getTableCellEditorComponent in the DefaultCellEditor and achieve the same result. I have included both solutions in a MCVE:
import java.awt.Color;
import java.awt.Font;
import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
public class Example extends JFrame {
private final JTable table;
private final String[] header = new String[]{"Column 0", "Column 1", "Column 2", "Column 3"};
private String[][] data = new String[][]{
{"(0,0)", "(1,0)", "(2,0)", "(3,0)"},
{"(0,1)", "(1,1)", "(2,1)", "(3,1)"},
{"(0,2)", "(1,2)", "(2,2)", "(3,2)"},
{"(0,3)", "(1,3)", "(2,3)", "(3,3)"}};
private final Font tableFont = new Font("Lucida Console", Font.PLAIN, 18);
public Example() {
table = new JTable(data, header);
table.getTableHeader().setFont(tableFont);//font of the header
table.setFont(tableFont);//set the font of the whole table
//Since each cell is editable, you could think about it as a JTextField. You can create a
//new JTextField and customize it. Then, you pass it as the new cell editor to the columns
//of the JTable.
JTextField textField = new JTextField();
textField.setFont(tableFont);//this is what you need.
//Extra changes, no boarder and selection colour is yellow... just to get the point across.
textField.setBorder(null);
textField.setSelectionColor(Color.YELLOW);
//Create DefaultCellEditor and pass the textfield to the constructor.
DefaultCellEditor customCellEditor = new DefaultCellEditor(textField);
//Loop through all the columns and set the cell editor as the customized one.
for (int i = 0; i < table.getColumnCount(); i++) {
table.getColumnModel().getColumn(i).setCellEditor(customCellEditor);
}
/*
OR, don't create a JTextField and use the following instead:
DefaultCellEditor customCellEditor2 = new DefaultCellEditor(new JTextField()) {
#Override
public java.awt.Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
JTextField result = (JTextField) super.getTableCellEditorComponent(table, value,
isSelected, row, column);
result.setFont(tableFont);//this is what you need.
result.setBorder(null);
result.setSelectionColor(Color.YELLOW);
return result;
}
};
//Loop through all the columns and set the cell editor as the customized one.
for (int i = 0; i < table.getColumnCount(); i++) {
table.getColumnModel().getColumn(i).setCellEditor(customCellEditor2);
}
*/
//probably, you should make the height of the cells larger.
for (int i = 0; i < table.getRowCount(); i++) {
table.setRowHeight(i, 25);
}
add(new JScrollPane(table));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
pack();
setVisible(true);
}
public static void main(String[] args) {
new Example();
}
Maybe you could check how many characters have been typed in and calculate approximately how big the font should be.
Calculation shouldn't be hard, is it? And then just change the size in this cell.
I already add a picture with JLabel in my JTable with TableCellRenderer. But how to add a border to the JLabel when mouse moves over the cell, on specific column and row?
This is the 1st renderer class:
public class RenderTabel implements TableCellRenderer{
#Override
public Component getTableCellRendererComponent(JTable table, Object
value,boolean isSelected, boolean hasFocus,int row, int column){
JLabel gambar=new JLabel();
String url="D:\\Kuliah Semester 4\\Pemrograman Berorientasi Objek\\DINUS BOOKSTORE\\image";
ImageIcon img=scalegmbr(url+"\\"+table.getModel().getValueAt(row, 0)+".png");
gambar.setIcon(img);
gambar.setText("");
gambar.setHorizontalAlignment(SwingConstants.CENTER);
table.setRowHeight(row, 50);
table.getColumnModel().getColumn(column).setPreferredWidth(80);
return gambar;
}
public ImageIcon scalegmbr(String file){
Image image=new ImageIcon(file).getImage();
return new ImageIcon(image.getScaledInstance(80,50,SCALE_SMOOTH));
}
}
This is 2nd renderer class:
public class RenderTabel1 implements TableCellRenderer{
#Override
public Component getTableCellRendererComponent(JTable table, Object
value,boolean isSelected, boolean hasFocus,int row, int column){
JLabel gambar=new JLabel();
String url="D:\\Kuliah Semester 4\\Pemrograman Berorientasi Objek\\DINUS BOOKSTORE\\image";
ImageIcon img=scalegmbr(url+"\\"+table.getModel().getValueAt(row, 0)+".png");
gambar.setIcon(img);
gambar.setText("");
gambar.setHorizontalAlignment(SwingConstants.CENTER);
gambar.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(200, 100, 52), 2));
table.setRowHeight(row, 50);
table.getColumnModel().getColumn(column).setPreferredWidth(80);
return gambar;
}
public ImageIcon scalegmbr(String file){
Image image=new ImageIcon(file).getImage();
return new ImageIcon(image.getScaledInstance(80,50,SCALE_SMOOTH));
}
}
and this is how I set the mouse enter and mouse clicked in my JTable:
private void tblbukuMouseEntered(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
tblbuku.getColumnModel().getColumn(6).setCellRenderer( new RenderTabel1());
}
private void tblbukuMouseExited(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
tblbuku.getColumnModel().getColumn(6).setCellRenderer( new RenderTabel());
}
But this adds a border to all cells in column 6 when mouse moves ofer a cell of that column. How to change it only into specific row and column when mouse entered that row and column?
So, for a particular column of your table, you want to paint a border on the cell that is hovered by the mouse (only the hovered cell, only in this column).
(edit: after clarification it appears that this question has been asked before -- I'm leaving my answer below as it might still help)
don't change the cell renderer dynamically, have only 1 renderer for that column, and handle that situation within the single renderer.
don't add listeners on the Component that is returned by the renderer: such listeners won't be triggered, as the component is only used for its paint()-ing logic.
instead, add a mouse motion listener on the table itself, and compute the coordinates of hovered cells with JTable's methods rowAtPoint and columnAtPoint, when mouse moves over table, or exits the area.
(irrelevant to problem at hand, but deserves a mention) Avoid creating a new JLabel for each call of your renderer, this is wasteful. Swing is single-thread, it's safe to reuse the same object (provided you don't forget to reset all its properties that might have changed between 2 calls)
Small demo that shows the effect:
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class SimpleTableDemo extends JPanel {
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(SimpleTableDemo::createAndShowGUI);
}
private int
hoveredRow = -1,
hoveredColumn = -1;
SimpleTableDemo() {
super(new GridLayout(1,0));
String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"};
Object[][] data = {
{"Kathy", "Smith", "Snowboarding", 5, Boolean.FALSE},
{"John", "Doe", "Rowing", 3, Boolean.TRUE},
{"Sue", "Black", "Knitting", 2, Boolean.FALSE},
{"Jane", "White", "Speed reading", 20, Boolean.TRUE},
{"Joe", "Brown", "Pool", 10, Boolean.FALSE}
};
final JTable table = new JTable(data, columnNames);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
table.getColumn("Sport").setCellRenderer(new MyCellRenderer());
table.addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
Point p = e.getPoint();
hoveredRow = table.rowAtPoint(p);
hoveredColumn = table.columnAtPoint(p);
table.repaint();
}
public void mouseExited(MouseEvent e) {
hoveredRow = hoveredColumn = -1;
table.repaint();
}
});
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("SimpleTableDemo");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
SimpleTableDemo newContentPane = new SimpleTableDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
private class MyCellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (hoveredColumn == column && hoveredRow == row) {
label.setBorder(BorderFactory.createLineBorder(Color.GREEN, 2));
}
else {
label.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
}
return label;
}
}
}
Note 1: I'm using the default cell renderer, unlike you, but the same idea applies. The demo above is a generic example, that will be more useful as example to keep here than a specific solution for your case (for example, in my interpretation of the problem, I understand the details about icon are irrelevant).
Note 2: In the demo I repaint the whole visible area each time, but if you want to optimize it should be possible to repaint only 2 cells, that's an entire new question, see here for help about that.
I want to render a JTable component's cell to support line wrapping, so I am using a JTextarea inside the cell, because text area allows line wrapping. This is my code:
//Render column with header Person
table.getColumn("Person").setCellRenderer(new RenderRedGreen());
final class RenderRedGreen extends DefaultTableCellRenderer {
JTextArea textarea;
#Override public Component getTableCellRendererComponent(
JTable aTable, Object aNumberValue, boolean aIsSelected,
boolean aHasFocus, int aRow, int aColumn )
{
String value = (String)aNumberValue;
textarea = new JTextArea();
aTable.add(textarea);
textarea.setLineWrap(true);
textarea.setWrapStyleWord(true);
textarea.setText(value);
aTable.setRowHeight(90);
if (aNumberValue == null) return this;
Component renderer = super.getTableCellRendererComponent(
aTable, aNumberValue, aIsSelected, aHasFocus, aRow, aColumn
);
if (value.equals("Me"))
renderer.setForeground(Color.red);
else
renderer.setForeground(Color.black);
return this;
}
}
The problem is that the text is not wrapped, so I can not see long texts completely. What am I doing wrong?
These lines of code would help you to wrap the data and show multiple lines properly :
textarea.setWrapStyleWord(true);
textarea.setLineWrap(true);
DefaultCaret caret = (DefaultCaret) textarea.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
I am having trouble with one a custom ListCellRenderer on a JList. When there is only 1 item in the List the cell is displayed correctly, but when there is more than 1 item, each cell seams to be painted with the content of all cells overlapping each other, like this:
My CellRenderer looks like this:
public class SendungsCellRenderer extends JPanel implements ListCellRenderer {
private EmptyBorder eb = new EmptyBorder(5, 2, 5, 2);
private LineBorder lb = new LineBorder(new Color(255,255,255), 5);
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
uiSendungsbutton p = (uiSendungsbutton) value;
if(isSelected){
this.setBackground(new Color(200,200,250));
this.setBorder(new CompoundBorder(lb, new StrokeBorder(new BasicStroke())));
}else{
this.setBackground(new Color(252,252,252));
this.setBorder(lb);
}
this.setLayout(p.getLayout());
this.add(p.getNamePnl(),BorderLayout.NORTH);
this.add(p.getKdnrPnl(), BorderLayout.CENTER);
return this;
}
}
and it is set using
list_Sendung = new JList(getSendungen().toArray());
list_Sendung.setVisibleRowCount(1);
list_Sendung.setValueIsAdjusting(true);
list_Sendung.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list_Sendung.setCellRenderer(new SendungsCellRenderer());
The method getSendungen() returns an ArrayList of uiSendungsbutton.
How do I get the JList to display each item in a cell of its own correctly?
The problem is that the same cell renderer is being used for all cells, and for each new cell, you add the components to this again. To fix this problem, remove all components from this each time, using removeAll. Your code would look like this after it was fixed:
public class SendungsCellRenderer extends JPanel implements ListCellRenderer {
private EmptyBorder eb = new EmptyBorder(5, 2, 5, 2);
private LineBorder lb = new LineBorder(new Color(255,255,255), 5);
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
this.removeAll();
uiSendungsbutton p = (uiSendungsbutton) value;
if(isSelected){
this.setBackground(new Color(200,200,250));
this.setBorder(new CompoundBorder(lb, new StrokeBorder(new BasicStroke())));
}else{
this.setBackground(new Color(252,252,252));
this.setBorder(lb);
}
this.setLayout(p.getLayout());
this.add(p.getNamePnl(),BorderLayout.NORTH);
this.add(p.getKdnrPnl(), BorderLayout.CENTER);
return this;
}
}
I'm making a table where I want to make the first column with a higher Font Size.
For example in column 0 I want Font size of 30 and on columns 1-3 y want Font size of 13.
Here's my code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.*;
public class kanji_list extends JFrame {
kanji_list(){
JTable table = new JTable();
JScrollPane scroll = new JScrollPane();
Image icon = Toolkit.getDefaultToolkit().getImage("JLPT.jpg");
ImageIcon ima = new ImageIcon("JLPT.jpg");
DefaultTableModel model = new DefaultTableModel(get_data(), get_header());
table = new JTable(model){
public boolean isCellEditable(int rowIndex, int vColIndex){
return false;
}
};
JTableHeader th = table.getTableHeader();
TableColumnModel tcm = th.getColumnModel();
TableColumn column = null;
table.setFont(new Font("Microsoft JhengHei", Font.BOLD, 13));
for (int i = 0; i < 4; i++) {
column = table.getColumnModel().getColumn(i);
DefaultTableCellRenderer tcr = new DefaultTableCellRenderer();
tcr.setHorizontalAlignment(SwingConstants.CENTER);
column.setCellRenderer(tcr);
if (i==0) {
column.setPreferredWidth(50);
}
else{
if(i==1){
column.setPreferredWidth(175);
}
else{
if(i==2){
column.setPreferredWidth(200);
}
else{
column.setPreferredWidth(875);
}
}
}
}
table.setRowHeight(table.getRowHeight()+30);
table.setModel(model);
scroll.add(table);
this.add(scroll);
this.setTitle("Katakana");
this.setSize(1350, 700);
this.setIconImage(icon);
this.setVisible(true);
this.setLocationRelativeTo(null);
scroll.setViewportView(table);
}
Object [][]get_data(){
Object data[][] = new Object[][]{
{"\u4e00", "Uno, 1", "ICHI, ITSU", "hito-, hitotsu"},
{"\u4e8c", "Dos, 2", "NI, JI", "futa, futatsu, futatabi"},
{"\u4e09", "Tres, 3", "SAN, JOU", "mi, mitsu, mittsu"},
{"\u99c5", "EstaciĆ³n", "EKI", ""}
};
return data;
}
String []get_header(){
String header [] = new String[]{"KANJI", "SIGNIFICADO", "LECTURA ON", "LECTURA KUN"};
return header;
}
}
This is a Japanese learning system, and Kanjis on unicode on 1st column aren't visible at all with my 13 size font, but if I make all the table on a higher size, all the other columns get bigger and it doesn't looks fine.
In core JTable you basically need a custom renderer which sets the Font to something different from the table's font, f.i. in a subclass of DefaultTableCellRenderer. Note that setting the font on DefaultTableCellRenderer once after instantiation won't work because it's reset on each call to getTableCellRendererComponent.
JTable table = new JTable(new AncientSwingTeam());
// the default renderer uses the table's font,
// so set it as appropriate
table.setFont(fontToUseForAllColumnsExceptFirst);
// a custom renderer which uses a special font
DefaultTableCellRenderer r = new DefaultTableCellRenderer() {
Font font = fontToUseForFirstColumn;
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
row, column);
setFont(font);
return this;
}
};
// doesn't work because the default renderer's font is reset
// to the table's font always
// r.setFont(font);
// set the custom renderer for first column
table.getColumnModel().getColumn(0).setCellRenderer(r);
An alternative is the renderer decoration approach, supported in the SwingX project (biased me can't resist :-) Then the above would be a two-liner (assuming table is of type JXTable):
Highlighter hl = new FontHighlighter(font);
table.getColumnExt(0).setHighlighter(hl);