I have a JTable and everytime I select a cell, I want to print its row and column index. I use getSelectedRow() and getSelectedColumn() methods for that reason. Running the code below:
Class TestTimeTable
public class TestTimeTable extends JFrame{
private final int rows = 10;
private final int cols = 8;
private final String daysOfTheWeek[] = {"MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"};
private final JPanel jTablePanel;
private final JScrollPane scrollPane;
private final JTable timeTable;
private final Object[][] rowData;
public TestTimeTable(){
this.rowData = new Object[this.rows][this.cols];
this.timeTable = new JTable(this.rowData,this.daysOfTheWeek){
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
this.timeTable.setRowHeight(200, 200);
this.timeTable.setFillsViewportHeight(true);
this.timeTable.setOpaque(true);
this.timeTable.setColumnSelectionAllowed(true);
this.timeTable.setRowSelectionAllowed(true);
this.timeTable.setCellSelectionEnabled(true);
this.timeTable.setDefaultRenderer(Object.class, new BoardTableCellRenderer());
this.scrollPane = new JScrollPane(this.timeTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.jTablePanel = new JPanel();
this.jTablePanel.add(this.scrollPane);
getContentPane().add(new JScrollPane(this.timeTable), BorderLayout.CENTER);
}
public int getColumn(){
return this.timeTable.getSelectedColumn();
}
public int getRow(){
return this.timeTable.getSelectedRow();
}
public JTable getTimeTable(){
return this.timeTable;
}
public void createAndShowUI(){
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] argas){
TestTimeTable tt = new TestTimeTable();
tt.createAndShowGUI();
}
}
Class BoardTableCellRenderer
class BoardTableCellRenderer extends DefaultTableCellRenderer {
Component c;
private static final long serialVersionUID = 1L;
private final Color selectionBlue = new Color(131,166,198);
private final MatteBorder border = new MatteBorder(1, 1, 0, 0, Color.BLACK);
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (table.isCellSelected(row, column)){
c.setBackground(this.selectionBlue);
setBorder(this.border);
} else {
c.setBackground(Color.WHITE);
}
if(isSelected){
JOptionPane.showMessageDialog(null, table.getSelectedRow() + ""+table.getSelectedColumn(),null, JOptionPane.INFORMATION_MESSAGE);
}
return c;
}
}
Everytime I select a cell, the JOptionPane frame appears and then the app freezes. So I have to interrupt it all the time. Could somebody please tell me why is this happening? What could I do to fix it?
use, override boolean isSelected, boolean hasFocus (built_in methods) from getTableCellRendererComponent instead of referencing back to JTable - table.isCellSelected(row, column), ba reseting Color for rest of cells in else statement, e.g. simple torso
.
private class StatusRenderer implements TableCellRenderer {
private static final long serialVersionUID = 1L;
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setBackground(table.getSelectionBackground());
} else {
setBackground(table.getBackground());
}
return this;
}
}
change ListSelectionMode for JTable
remove every this.Xxx, are useless
don't to setSize, use JFrame.pack() instead and/or set size for JScrollPane e.g. table.setPreferredScrollableViewportSize(table.getPreferredSize());(for reasonable numbers or rows and columns, otherwise use Dimension(x, x))
EDIT
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.UIResource;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class TableRolloverDemo {
private JFrame frame = new JFrame("TableRolloverDemo");
private JTable table = new JTable();
private String[] columnNames = new String[]{"Column"};
private Object[][] data = new Object[][]{{false}, {false}, {true}, {true},
{false}, {false}, {true}, {true}, {false}, {false}, {true}, {true}};
public TableRolloverDemo() {
final DefaultTableModel model = new DefaultTableModel(data, columnNames) {
//private boolean ImInLoop = false;
#Override
public Class<?> getColumnClass(int columnIndex) {
return Boolean.class;
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return true;
} else {
return false;
}
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 0) {
//if (!ImInLoop) {
// ImInLoop = true;
Boolean bol = (Boolean) aValue;
super.setValueAt(aValue, rowIndex, columnIndex);
for (int i = 0; i < this.getRowCount(); i++) {
if (i != rowIndex) {
super.setValueAt(!bol, i, columnIndex);
}
}
// ImInLoop = false;
//}
} else {
super.setValueAt(aValue, rowIndex, columnIndex);
}
}
};
RolloverMouseAdapter rolloverAdapter = new RolloverMouseAdapter(table);
RolloverBooleanRenderer renderer = new RolloverBooleanRenderer(rolloverAdapter);
table.addMouseListener(rolloverAdapter);
table.addMouseMotionListener(rolloverAdapter);
table.setDefaultRenderer(Boolean.class, renderer);
table.setModel(model);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(table));
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private class RolloverMouseAdapter extends MouseAdapter {
private int row = -1;
private int column = -1;
private JTable table;
public RolloverMouseAdapter(JTable table) {
this.table = table;
}
public boolean isRolloverCell(int row, int column) {
return this.row == row && this.column == column;
}
#Override
public void mouseMoved(MouseEvent e) {
int lastRow = row;
int lastColumn = column;
row = table.rowAtPoint(e.getPoint());
column = table.columnAtPoint(e.getPoint());
if (row == lastRow && column == lastColumn) {
return;
}
if (row >= 0 && column >= 0) {
table.repaint(table.getCellRect(row, column, false));
}
if (lastRow >= 0 && lastColumn >= 0) {
table.repaint(table.getCellRect(lastRow, lastColumn, false));
}
}
#Override
public void mouseExited(MouseEvent e) {
if (row >= 0 && column >= 0) {
table.repaint(table.getCellRect(row, column, false));
}
row = column = -1;
}
}
private class RolloverBooleanRenderer extends JCheckBox implements
TableCellRenderer, UIResource {
private final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
private RolloverMouseAdapter adapter;
public RolloverBooleanRenderer(RolloverMouseAdapter adapter) {
super();
this.adapter = adapter;
setHorizontalAlignment(JLabel.CENTER);
setBorderPainted(true);
}
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
getModel().setRollover(adapter.isRolloverCell(row, column));
if (isSelected) {
setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setSelected((value != null && ((Boolean) value).booleanValue()));
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
} else {
setBorder(noFocusBorder);
}
return this;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TableRolloverDemo tableRolloverDemo = new TableRolloverDemo();
}
});
}
}
I have a JTable and everytime I select a cell, I want to print its row and column index.
I would override the changeSelection(...) method of the JTable:
JTable table = new JTable(data, columnNames)
{
public void xxxchangeSelection(
int row, int column, boolean toggle, boolean extend)
{
super.changeSelection(row, column, toggle, extend);
System.out.println(row + " : " + column);
}
};
Related
I have written a renderer and my program does not color the cell and I don't know why. When I try to color the whole row it also colors only 3 of the 7 rows. Can someone please help me?
public void isLow(JTable jTableBestandstabelle) {
jTableBestandstabelle.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
#Override
public Component getTableCellRendererComponent(
JTable aTable, Object aNumberValue, boolean aIsSelected,
boolean aHasFocus, int aRow, int aColumn
) {
if (aNumberValue == null) {
return this;
}
Component renderer = super.getTableCellRendererComponent(
aTable, aNumberValue, aIsSelected, aHasFocus, aRow, aColumn
);
int m = (int) jTableBestandstabelle.getValueAt(aRow, 4);
int a = (int) jTableBestandstabelle.getValueAt(aRow, 5);
if (a < m && column == 5) {
renderer.setForeground(Color.black);
renderer.setBackground(Color.red);
} else {
renderer.setForeground(Color.black);
}
return this;
}
});
}
public void isLow(JTable jTableBestandstabelle) {
jTableBestandstabelle.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
#Override
public Component getTableCellRendererComponent(
JTable aTable, Object aNumberValue, boolean aIsSelected,
boolean aHasFocus, int aRow, int aColumn
) {
if (aNumberValue == null) {
return this;
}
Component renderer = super.getTableCellRendererComponent(
aTable, aNumberValue, aIsSelected, aHasFocus, aRow, aColumn
);
int m = (int) jTableBestandstabelle.getValueAt(aRow, 4);
int a = (int) jTableBestandstabelle.getValueAt(aRow, 5);
if (a < m) {
renderer.setForeground(Color.black);
renderer.setBackground(Color.red);
} else {
renderer.setForeground(Color.black);
}
return this;
}
});
}
You have two problem in your code:
You use a boolean columns in your table (last column). So if you want to present a checkbox in the column you cannot use a DefaultTableCellRenderer
When you use table.setDefaultRenderer(Object.class, renderer) this will not work for some primitive tapes like Boolean.class or Integer.class (don't know why). So you need to set the renderer for these classes too (table.setDefaultRenderer(Integer.class, renderer) and table.setDefaultRenderer(Boolean.class, renderer)). But due to the point 1 its not a good idea.
Here is mine solution:
import java.awt.Color;
import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
/**
* <code>TestTable</code>.
*/
public class TestTable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TestTable()::startUp);
}
private void startUp() {
DefaultTableModel model = new DefaultTableModel(0, 7) {
#Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 6) {
return Boolean.class; // last column is boolean
} else if (columnIndex == 0 && columnIndex > 3) {
return Integer.class; // 1, 4, 5 are integers
}
return super.getColumnClass(columnIndex);
}
};
model.addRow(new Object[] {1, "Test1", "Test2", "Test3", 6, 5, false});
model.addRow(new Object[] {1, "Test11", "Test22", "Test33", 4, 5, true});
JTable table = new JTable(model);
for (int i = 0; i < table.getColumnCount(); i++) {
TableColumn col = table.getColumnModel().getColumn(i);
int modelCol = table.convertColumnIndexToModel(i);
col.setCellRenderer(new MyCellRenderer(table.getDefaultRenderer(model.getColumnClass(modelCol))));
}
JFrame frm = new JFrame("Table test");
frm.add(new JScrollPane(table));
frm.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frm.pack();
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
private static class MyCellRenderer implements TableCellRenderer {
private final TableCellRenderer origin;
public MyCellRenderer(TableCellRenderer origin) {
this.origin = origin;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component c = origin.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
int m = (int) table.getValueAt(row, 4);
int a = (int) table.getValueAt(row, 5);
if (a < m) {
c.setForeground(Color.black);
c.setBackground(Color.red);
} else {
c.setForeground(Color.black);
c.setBackground(Color.white);
}
return c;
}
}
}
I'm trying to present some data in JTable. I've created Jtable everything is clear apart from changing background color of some particular rows - thouse in which user tick a checkbox on the last colum. It has to work dynamically. Could you give me some tips, code, etc. please?
Something like this?
import java.awt.BorderLayout;
import java.util.Vector;
import javax.swing.*;
import java.awt.*;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;
public class JTableTest extends JFrame implements TableModel{
Vector<Object[]> lines = new Vector<Object[]>();
private String[] headers = {"String","Boolean"};
public JTableTest(){
for (int t = 0; t < 100; t++) lines.addElement(new Object[]{"Row "+t,Boolean.FALSE});
JPanel p = (JPanel)getContentPane();
p.setLayout(new BorderLayout());
JTable table = new JTable();
table.setDefaultRenderer(String.class, new MyRenderer());
p.add(new JScrollPane(table));
table.setModel(this);
p.setPreferredSize(new Dimension(400,200));
pack();
setVisible(true);
}
public static void main(String[] args){
new JTableTest();
}
#Override
public int getRowCount() {
return lines.size()+1;
}
#Override
public int getColumnCount() {
return headers.length;
}
#Override
public String getColumnName(int columnIndex) {
return headers[columnIndex];
}
#Override
public Class<?> getColumnClass(int col) {
if (col == 1) return Boolean.class;
return String.class;
}
#Override
public boolean isCellEditable(int row, int col) {
return col==1;
}
#Override
public Object getValueAt(int row, int col) {
return lines.elementAt(row)[col];
}
#Override
public void setValueAt(Object aValue, int row, int col) {
lines.elementAt(row)[col] = aValue;
}
#Override
public void addTableModelListener(TableModelListener l) {
}
#Override
public void removeTableModelListener(TableModelListener l) {
}
private class MyRenderer extends DefaultTableCellRenderer{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (lines.elementAt(row)[1] == Boolean.TRUE) c.setBackground(Color.orange);
else c.setBackground(table.getBackground());
table.repaint();
return c;
}
}
}
I am trying to use JTable as property editor. I would like to use different types of JComponents in within a single column.
So far I could get checkbox to be shown whenever property has a boolean value. However, I am not able to get that checkbox clickable and the set the value accordingly. It justs shows in the cell but when I click on it, it's value turn to string.
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
public class Main extends JFrame {
public static void main(String[] args) {
Main main = new Main();
}
public Main() {
this.setBounds(55, 5, 400, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
init();
this.setVisible(true);
this.validate();
}
private void init() {
JTable table = new JTable() {
#Override
public TableCellRenderer getCellRenderer(int row, int column) {
if (column == 1) {
if (row == 1) {
Class cellClass = getValueAt(row, column).getClass();
return getDefaultRenderer(Boolean.class);
}
}
return super.getCellRenderer(row, column);
}
};
table.setModel(new PropertyModel(new Property(true, 1234)));
getContentPane().add(table);
}
public class Property {
private Integer height;
private boolean visible;
public Property(boolean visible, Integer height) {
super();
this.visible = visible;
this.height = height;
}
public Integer getHeight() {
return height;
}
public boolean isVisible() {
return visible;
}
public void setHeight(Integer height) {
this.height = height;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
#Override
public String toString() {
return "Property [visible=" + visible + ", height=" + height + "]";
}
}
public class PropertyModel extends AbstractTableModel {
private String HEIGHT = "Height";
private String VISIBLE = "Visible";
private Property property;
private String[] columnNames = { "Name", "Value" };
private Object[][] data = { { HEIGHT, "", },
{ VISIBLE, new Boolean(false) } };
public PropertyModel(Property property) {
super();
this.property = property;
initializeData();
this.addTableModelListener(new CustomPropertyTable());
}
#Override
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int c) {
return columnNames[c];
}
#Override
public int getRowCount() {
return data.length;
}
#Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
/*
* Initializes the data as per the world object values.
*/
private void initializeData() {
data[0][1] = property.getHeight();
data[1][2] = property.isVisible();
}
#Override
public boolean isCellEditable(int row, int col) {
if (col == 0) {
return false;
} else {
return true;
}
}
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
public class CustomPropertyTable implements TableModelListener {
#Override
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int column = e.getColumn();
TableModel model = (TableModel) e.getSource();
String columnName = model.getColumnName(column);
String propertyName = (String) model
.getValueAt(row, column - 1);
if (propertyName.equals(HEIGHT)) {
String propertyValue = (String) model.getValueAt(row,
column);
property.setHeight(Integer.valueOf(propertyValue));
} else if (propertyName.equals(VISIBLE)) {
String propertyValue = (String) model.getValueAt(row,
column);
Boolean visible = Boolean.valueOf(propertyValue);
property.setVisible(visible);
}
System.out.println(property);
}
}
}
}
Screenshots:
1) When it starts
2) When I click or try to uncheck it
What could I be doing wrong?
You can provide an editor in the same fashion you already do the renderer. Extend getCellEditor. For example based on the posted code:
#Override
public TableCellEditor getCellEditor(int row, int column) {
if (column == 1) {
Object value = getValueAt(row, column);
if (value != null)
return getDefaultEditor(value.getClass());
}
return super.getCellEditor(row, column);
}
Basically I have a JTable, and this JTabel will have a product in one cell, and then in the cell directly below it the cost.
The product name should be aligned to the left.
The product cost should be aligned to the right.
I don't actually care what the alignment of other cells in each row is.
So I need to set the alignment of either individual cells, or individual rows. I've found ways to set the alignment of the table, and ways to set the alignment of the columns, but never the rows/individual cells.
sscce:
public class Main extends JFrame{
public static void main(String args[]){
new Main();
}
public Main(){
super("Demo");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState(MAXIMIZED_BOTH);
setVisible(true);
setLayout(new BorderLayout());
TableModel dataModel = new AbstractTableModel() {
Object rows[] = new Object[50];
public int getColumnCount(){return 1;}
public int getRowCount(){return rows.length;}
public Object getValueAt(int row, int col){
return rows[row];
}
public boolean isCellEditable(int row, int col){
return false;
}
public void setValueAt(Object value, int row, int col) {
rows[row] = value;
fireTableCellUpdated(row,0);
}
};
JTable receipt = new JTable(dataModel);
receipt.setBorder(BorderFactory.createEtchedBorder());
receipt.setShowGrid(false);
add(receipt,BorderLayout.CENTER);
for(int i = 0; i < 10; i+=2){
receipt.setValueAt("ProductNameHere",i,0);
receipt.setValueAt("Cost",i+1,0);
}
validate();
repaint();
}
}
The default renderer for Number is a right aligned label. In this example, no special renderer is required to right align INT_COL, which is labeled Index and has type Integer.class.
If this is not helpful, please edit your question to include an sscce that shows your current approach and your cost data type.
Addendum: Alternatively, override prepareRender(), as shown here.
JTable receipt = new JTable(dataModel) {
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
JLabel c = (JLabel) super.prepareRenderer(renderer, row, col);
if (row % 2 == 0) {
c.setHorizontalAlignment(JLabel.LEFT);
} else {
c.setHorizontalAlignment(JLabel.RIGHT);
}
return c;
}
};
SSCCE:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
public class Main extends JFrame {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Main();
}
});
}
public Main() {
super("Demo");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TableModel dataModel = new AbstractTableModel() {
Object rows[] = new Object[10];
#Override
public int getColumnCount() {
return 1;
}
#Override
public int getRowCount() {
return rows.length;
}
#Override
public Object getValueAt(int row, int col) {
return rows[row];
}
#Override
public boolean isCellEditable(int row, int col) {
return false;
}
#Override
public void setValueAt(Object value, int row, int col) {
rows[row] = value;
fireTableCellUpdated(row, 0);
}
};
JTable receipt = new JTable(dataModel) {
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
JLabel c = (JLabel) super.prepareRenderer(renderer, row, col);
if (row % 2 == 0) {
c.setHorizontalAlignment(JLabel.LEFT);
} else {
c.setHorizontalAlignment(JLabel.RIGHT);
}
return c;
}
};
receipt.setBorder(BorderFactory.createEtchedBorder());
receipt.setShowGrid(false);
add(receipt, BorderLayout.CENTER);
for (int i = 0; i < 10; i += 2) {
receipt.setValueAt("ProductNameHere", i, 0);
receipt.setValueAt(Integer.valueOf(i + 1), i + 1, 0);
}
pack();
setLocationByPlatform(true);
setVisible(true);
}
}
Please tell me, how to make a JTable column to contain JTextAreas,
so the cell's height will increase when user types a lot of text and
we can see more than one line (cell gets expanded; as result, row will expand too)
You need to write your own cell renderer and editor based on JTextArea:
public class Start
{
public static class JTextPaneCellEditor extends AbstractCellEditor implements TableCellEditor, KeyListener
{
private JViewport viewport;
private JTable table;
private int row;
private JTextPane pane;
public JTextPaneCellEditor(){
viewport = new JViewport();
pane = new JTextPane();
viewport.add(pane);
pane.addKeyListener(this);
}
#Override public Object getCellEditorValue(){
return pane.getText();
}
#Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column){
this.table = table;
this.row = row;
pane.setText(value.toString());
int newHeight = (int)pane.getPreferredSize().getHeight();
if(table.getRowHeight(row) < newHeight){
table.setRowHeight(row, newHeight);
}
return pane;
}
#Override public boolean isCellEditable(EventObject e){
if (e instanceof MouseEvent) {
return ((MouseEvent)e).getClickCount() >= 2;
}
return true;
}
#Override public void keyTyped(KeyEvent e){
table.setRowHeight(row, (int)pane.getPreferredSize().getHeight());
}
#Override public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_ENTER){
stopCellEditing();
}
}
#Override public void keyReleased(KeyEvent e){
}
}
private static class JTextPaneCellRenderer extends JViewport implements TableCellRenderer
{
JTextPane pane;
JTextPaneCellRenderer(){
pane = new JTextPane();
add(pane);
}
#Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
pane.setText(value.toString());
table.setRowHeight(row, (int)pane.getPreferredSize().getHeight());
return this;
}
}
public static void main(String[] args){
JTable table = new JTable(new String[][]{{"String String String String StringString String String String StringString String String String StringString String String String StringString String String String String"}, {"String 2"}}, new String[]{"Column"});
table.setDefaultRenderer(Object.class, new JTextPaneCellRenderer());
table.setDefaultEditor(Object.class, new JTextPaneCellEditor());
JFrame test = new JFrame();
test.add(new JScrollPane(table));
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.setSize(300, 300);
test.setLocationRelativeTo(null);
test.setVisible(true);
}
}
EDIT: add viewports for better sizing. But the row is still not expanded on first edit. Does anyone have any ideas?
EDIT2: I agree with the comments. The thing you want is possible, but you need untested, hackish custom implementation. You will be better off if you redesigned your layout to exclude such JTable sorcery.
#Jakub Zaverka
I'll delete this answer later
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;
public class AutoWrapTest {
public JComponent makeUI() {
String[] columnNames = {"TextAreaCellRenderer"};
Object[][] data = {
{"123456789012345678901234567890"},
{"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddx"},
{"----------------------------------------------0"},
{">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>|"},};
TableModel model = new DefaultTableModel(data, columnNames) {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
JTable table = new JTable(model) {
private static final long serialVersionUID = 1L;
#Override
public void doLayout() {
TableColumn col = getColumnModel().getColumn(0);
for (int row = 0; row < getRowCount(); row++) {
Component c = prepareRenderer(col.getCellRenderer(), row, 0);
if (c instanceof JTextArea) {
JTextArea a = (JTextArea) c;
int h = getPreferredHeight(a) + getIntercellSpacing().height;
if (getRowHeight(row) != h) {
setRowHeight(row, h);
}
}
}
super.doLayout();
} //http://tips4java.wordpress.com/2008/10/26/text-utilities/
private int getPreferredHeight(JTextComponent c) {
Insets insets = c.getInsets();
View view = c.getUI().getRootView(c).getView(0);
int preferredHeight = (int) view.getPreferredSpan(View.Y_AXIS);
return preferredHeight + insets.top + insets.bottom;
}
};
table.setEnabled(false);
table.setShowGrid(false);
table.setTableHeader(null);
table.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer());
JScrollPane sp = new JScrollPane(table);
sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
JPanel p = new JPanel(new BorderLayout());
p.add(sp);
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new AutoWrapTest().makeUI());
f.setSize(200, 200);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {
private static final long serialVersionUID = 1L;
private final Color evenColor = new Color(230, 240, 255);
public TextAreaCellRenderer() {
super();
setLineWrap(true);
setWrapStyleWord(true);
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
setBackground((row % 2 == 0) ? evenColor : getBackground());
}
setFont(table.getFont());
setText((value == null) ? "" : value.toString());
return this;
}
}