Is it possible to switch off word wraping in JTable? - java

I have a JTable Component. In one column I insert HTML code and if a line in this column is longer than column width, the text is wrapped. Is it possible to switch off wrap?
#sandlex
public Object getValueAt(int row, int col) {
return new String(
"<html>dgdfsgsdfg dfgdsfg sdfgs dfgsdfgsdfgsdfgsd afsdf asdfasd</html>");
}
Check your code with this function. It will display text in few lines - not in one.

Is it possible to take a look at your code?
For example in this simplest example nothing is wrapped:
public class TableTest {
public static void main(String[] args) {
JFrame frm = new JFrame();
TableModel dataModel = new AbstractTableModel() {
public int getColumnCount() {
return 10;
}
public int getRowCount() {
return 10;
}
public Object getValueAt(int row, int col) {
return new String(
"row*col*1000000000");
}
};
JTable table = new JTable(dataModel);
table.getColumnModel().getColumn(2).setMaxWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setMinWidth(120);
frm.getContentPane().add(table);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setPreferredSize(new Dimension(300, 300));
frm.pack();
frm.setVisible(true);
}
}
Edited #latata
You can try to create your own CellRenderer and play around with it applying to needed column:
table.getColumnModel().getColumn(0).setCellRenderer(new NonWrappedCellRenderer());
Renderer may look like this:
class NonWrappedCellRenderer extends JTextArea implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
this.setText((String)value);
this.setLineWrap(false);
return this;
}
}
Here line won't be wrapped cuz JTextArea by default use
setLineWrap(false)
The problem is JTextArea cannot display html tags properly as I can see. So you will solve this somehow. You can try JTextPane or something else that can deal with tags and check if this has wrapping property.
Alternatively you can calculate font metrics, cell width and trim text by hands.

Related

Cells with centered value and background based on value

here is my problem
I read a DB and show the data via the renderer. Shown data must be centered and bgcolor must change according to the value of the cell.
Following is the renderer. First table.getColumnModel() shows the centered value, second one calls a customer renderer to change the color. If I remove the comment on the second call I get the bgcolor but not the centered value and viceversa
for (int row = 0; row < table.getColumnCount(); row++) {
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
centerRenderer.setHorizontalAlignment(JLabel.CENTER);
table.getColumnModel().getColumn(row).setCellRenderer(centerRenderer);
//table.getColumnModel().getColumn(row).setCellRenderer(new CustomRenderer());
}
This is the Custom renderer
class CustomRenderer extends DefaultTableCellRenderer
{
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if(table.getValueAt(row, column).equals("A")){
cellComponent.setBackground(Color.YELLOW);
} else if(table.getValueAt(row, column).equals("B")){
cellComponent.setBackground(Color.GRAY);
}
else {cellComponent.setBackground(Color.white);}
return cellComponent;
}
}
How can I obtain a colored and center cell?
Than you
paps
Here a short snippet demonstrating what I think you are trying to achieve:
public class Testing {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Testing();
}
});
}
public Testing() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
String[] colNames = { "Col1", "Col2" };
Object[][] data = { { "A", "B" }, { "B", "C" } };
JTable table = new JTable(data, colNames);
CustomRenderer renderer = new CustomRenderer();
renderer.setHorizontalAlignment(JLabel.CENTER);
// table.setDefaultRenderer(String.class, renderer); // if you want to only
// color and center all strings
for (int col = 0; col < table.getColumnCount(); col++) {
// if you want to color and center every entry of the table
table.getColumnModel().getColumn(col).setCellRenderer(renderer);
}
panel.add(table);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
class CustomRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
cellComponent.setBackground(Color.white); // white if not "A" or "B"
if (value instanceof String) {
String temp = (String) value;
if (temp.equals("A")) {
cellComponent.setBackground(Color.YELLOW);
} else if (temp.equals("B")) {
cellComponent.setBackground(Color.GRAY);
}
}
return cellComponent;
}
}
}
The result will look like:
Note that your custom renderer only has to be created once, not on every loop. The issue in your code was, that you didn't use your own renderer, but a DefaultTableCellRenderer instead. Also, if you want to only use the custom rendering on a specific class type, e.g. only on String objects, you can use the commented out line instead of iterating through all columns of the table.
And of course you can add further restrictions to the CustomRenderer according to your needs.

Custom TableCellRenderer vs. prepareRenderer or how to fix row highlighting issue?

To put this short:
What is this about
I have a JTable with Model which displays data fetched from an SAP system.
My Goal is in a specific column to display only a part of the data which is in the model. For example the row of the model has Object["a","b"] but the user is only supposed to see a.
So I read a lot of threads here on StackOverflow and a lot of tutorials on how to use custom tablecellrenderers and editors etc. but I am not able to fix my problem, which is that the cell where i registered the renderer will not be highlighted when selected.
A possible solution is described HERE but this does not work for me.
Here is my custom Renderer:
public class SapChangeNumberCellRenderer extends DefaultTableCellRenderer{
private static final long serialVersionUID = -2649719064483586819L;
private SapChangeNumberTable table;
private int valuesSize;
public final static String ASM_AMOUNT = LanguageServer.getString("71", "Baugruppen");
public SapChangeNumberCellRenderer(SapChangeNumberTable table) {
super();
this.table = table;
}
#Override
public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected,
final boolean hasFocus,
final int row, final int column) {
// components & Layout
JPanel panel = new JPanel(new BorderLayout());
JButton buttonDots = new JButton("...");
JLabel text = new JLabel();
List<String> values = (List<String>) value;
valuesSize = values.size();
if (valuesSize > 0) {
// set values
buttonDots.setPreferredSize(new Dimension(14, 14));
text.setText(values.get(0));
} else {
text.setText("");
}
if (valuesSize > 1) {
// button to open dialog only if we have more than 1 item
panel.add(buttonDots, BorderLayout.EAST);
}
panel.add(text, BorderLayout.WEST);
panel.setOpaque(true);
return panel;
}
#Override
public String getToolTipText(MouseEvent e) {
String toolTip = String.valueOf(valuesSize) + Initializer.SPACE + ASM_AMOUNT;
return toolTip;
}
public SapChangeNumberTable getTable() {
return table;
}
}
So as you can see depending on the list size of the values I manipulate the component which will be given back from the method. The setOpaque(true) method does somehow not achieve my goal.
Here is the according JTabel (note: BaseTable is just a wrapper for JTable with some goodies I need...nothing fancy here)
public class SapChangeNumberTable extends BaseTable {
/** the model */
private SapChangeNumberTableModel model = new SapChangeNumberTableModel();
/** parent frame */
private SapPanel parent = null;
public SapChangeNumberTable(SapPanel parent) {
this.parent = parent;
this.init();
}
/**
* init the table
*/
private void init() {
// set model (not filled yet)
this.setModel(model);
// set renderer
setRendererAndEditor();
// add search filter row, enabling sorting is included
this.addFilterSearchRowPanel();
// single selection
this.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
// hide
this.hideColumns();
this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
}
/**
* sets the default table cell renderer
*/
private void setRendererAndEditor() {
getColumnModel().getColumn(convertColumnIndexToView(SapChangeNumberTableModel.COL_ID_SPM_ASM_NUMBER))
.setCellRenderer(new SapChangeNumberCellRenderer(this));
getColumnModel().getColumn(convertColumnIndexToView(SapChangeNumberTableModel.COL_ID_SPM_ASM_NUMBER))
.setCellEditor(new SapChangeNumberAsmRefTableCellEditor(this));
}
#Override
public void setStatusBarDataCount(boolean value) {
}
#Override
public void hideColumns() {
}
#Override
public int getColModelSortIndex() {
return 0;
}
#Override
public void load() {
}
#Override
public SapChangeNumberTableModel getModel() {
return model;
}
public boolean isChanging() {
return model.isFilling();
}
public SapFactoryChange getRow(int row) {
return model.getSapFactoryChange(row);
}
#Override
public void clear() {
model.clear();
}
#Override
public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) {
Component comp = super.prepareRenderer(renderer, rowIndex, vColIndex);
if (vColIndex == SapChangeNumberTableModel.COL_ID_SPM_ASM_NUMBER) {
//what the hack to do here to manipulate the comp ? I can't add a JPanel to a plain Component
}
return comp;
}
}
In the table I tried some stuff with prepareRenderer but here I can't manipulate the data (values) and all other stuff I am doing in the custom renderer. Maybe I have a basic understanding problem of how to approach this. I am thankful for any hints !
I just found a very simple solution which I thought would overwrite my wanted behavior, but it doesn't.
Just implemented this into the Table:
#Override
public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) {
Component comp = super.prepareRenderer(renderer, rowIndex, vColIndex);
if (isRowSelected(rowIndex)) {
comp.setBackground(Color.ORANGE);
}
return comp;
}
works like a charme!

Get JTable default TableCellRenderer and Manipulate it?

I am going to be using a lot of custom TableCellRenderers in a JTable, but I don't want to have to recreate the default properties for every single one, because it seems I have to start with a plain JLabel. This creates a ton of annoying overhead, because I even have to populate the value myself as well as the matching background, the foreground, the font, etc... to match the rest of the JTable.
Is there a way I can retrieve the parent TableCellRenderer or the it's resulting JLabel and manipulate that? That way I have all the defaults set already, and I can just manipulate the properties I am actually changing? I have tried everything with super.getCellRenderer and it is not giving me anything to accomplish that.
Also, my TableCellRenderer is not column-specific. Each cell can vary.
public class ActionTable extends JTable {
...
public TableCellRenderer getCellRenderer(int row, int column) {
String colName = ((ActionTableModel)this.getModel()).getColumnName(column);
if ( colName.equals("CUSTOM COL") ) {
return new ActionCellRenderer(this);
}
return super.getCellRenderer(this.convertRowIndexToModel(row), this.convertColumnIndexToModel(column));
}
public class ActionCellRenderer extends JLabel implements TableCellRenderer {
private ActionTable actionTable;
public ActionCellRenderer(ActionTable actionTable) {
this.actionTable = actionTable;
setOpaque(true); //MUST do this for background to show up.
}
#Override
public Component getTableCellRendererComponent(JTable table, Object color,boolean isSelected, boolean hasFocus,int row, int column) {
int modelRow = actionTable.convertRowIndexToModel(row);
int modelCol = actionTable.convertColumnIndexToModel(column);
String colName = table.getModel().getColumnName(modelCol);
/*
annoying overhead to retrieve default cell renderer properties
to match the rest of the JTable
*/
if (isSelected)
{
setBackground(table.getSelectionBackground());
setForeground(table.getSelectionForeground());
}
else
{
setBackground(table.getBackground());
setForeground(table.getForeground());
}
//AND I HAVE TO RETRIEVE THE VALUE MYSELF TOO
String textVal = ((ActionTableModel)table.getModel()).getValueAt(modelRow, modelCol).toString();
this.setHorizontalAlignment(SwingConstants.CENTER);
this.setFont(new Font("Serif", Font.PLAIN, 15));
this.setText(textVal);
//NOW I CAN DO CUSTOMIZATIONS
//PUT CUSTOMIZATIONS HERE
return this;
}
Just have your ActionCellRenderer extend DefaultTableCellRenderer and call the getTableCellRendererComponent() method to get the JLabel:
public class ActionCellRenderer extends DefaultTableCellRenderer{
public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus,int row, int column){
//get the label
JLabel label = (JLabel)super.getTableCellRendererComponent(table, value,isSelected, hasFocus,row, column);
//do whatever you want with the label
return label;
}
}

JTable cell with two data types

I have a column in JTable which should display two types: String OR ImageIcon, not both. Each cell in that column has own thread which calculates data. In the beginning I put to each cell an image(like waiting logo), then REPLACE(not append) the image with a string of calculated data. I tried to extend default TableCell renderer, but it displays image like object address(javax.swing.ImageIcon#342...) and then replaces with string. Another variant, it displays the image correctly, but replaces it with empty string(or it is not visible?).
How to set it up so the table displays cell content correctly according to type?
Here is what I have at the moment:
class IconAndStringRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 3606788739290618405L;
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
if (value instanceof Icon) {
setIcon((Icon) value);
setText("");
}
return this;
}
}
Here is JTable:
table = new JTable(model) {
private static final long serialVersionUID = 8058795799817761161L;
public Class<?> getColumnClass(int column) {
if (column == TARGET_COLUMN)
return ImageIcon.class;
else
return super.getColumnClass(column);
}
};
A few more questions:
How to set it so the text replaces the image, not write text after image(even if it's not visible);
How to set text color, I gonna use setForebackground(Color c), but if I use it, the image is not dislayed.
Is it possible to make it working with Jlabel? Set up required Jlabel(with image or text) in the thread which modifies a cell and just setValueAt(label, row, column);
You need a custom renderer which can understand both types you use.
For example
public class IconAndStringRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
if (value instanceof Icon) {
setText("");
setIcon((Icon) value);
}
return this;
}
}
Try to set this class as your column renderer
The default renderer knows how to display both strings and icons. All you have to do is ensure that your TableModel returns the correct class from getColumnClass(), String.class and Icon.class, respectively. Examples may be found here.
Addendum: Here's a minimal example to illustrate the principle, based on default implementations.
Addendum: Not sure if it works when needed to return different classes for the same column.
If you really need to choose the renderer on a per-cell basis, override prepareRenderer(), as shown here.
import java.awt.EventQueue;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
/** #see https://stackoverflow.com/a/14672312/230513 */
public class Test {
private static final Icon YES = UIManager.getIcon("InternalFrame.maximizeIcon");
private static final Icon NO = UIManager.getIcon("InternalFrame.closeIcon");
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultTableModel model = new DefaultTableModel(
new Object[]{"Name", "Icon"}, 0) {
#Override
public Class<?> getColumnClass(int col) {
if (col == 1) {
return Icon.class;
} else {
return super.getColumnClass(col);
}
}
};
model.addRow(new Object[]{"One", YES});
model.addRow(new Object[]{"Two", NO});
final JTable table = new JTable(model);
table.setRowHeight(YES.getIconHeight() +2);
f.add(table);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test().display();
}
});
}
}
To take advantage of the default renderers you can override the getCellRenderer(...) method of JTable to return the appropriate renderer. Something like:
public TableCellRenderer getCellRenderer(int row, int column)
{
int modelColumn = convertColumnIndexToModel(column);
if (modelColumn == ???)
{
Class rowClass = getModel().getValueAt(row, modelColumn).getClass();
return getDefaultRenderer( rowClass );
}
else
return super.getCellRenderer(row, column);
}

CellTable with Image Column

I have celltable with 4 column (name size addedBy modifiedBy )
all the value is filled during the run time.
The table actully show the documents.
Documents can be pdf, txt , doc so
i want to add icon before the name of the document.
and i also want one more Image column before name column
My code so far.
*
private CellTable<FDocument> getDocumentTable() {
if (documentTable == null) {
documentTable = new CellTable<FDocument>();
documentTable.setSize("600px", "300px");
documentTable.addColumn(nameColumnD, "NAME");
documentTable.addColumn(sizeColumnD, "SIZE");
documentTable.addColumn(modified_by_ColumnD, "MODIFIED BY");
documentTable.addColumn(dateColumnD, "MODIFIED ON");
}
return documentTable;
}
TextColumn<FDocument> idColumnD = new TextColumn<FDocument>() {
#Override
public String getValue(FDocumentobject) {
// TODO Auto-generated method stub
return object.getId();
}
};
TextColumn<FDocument> nameColumnD = new TextColumn<FDocument>() {
#Override
public String getValue(FDocumentobject) {
return object.getName();
}
};
TextColumn<FDocument> sizeColumnD = new TextColumn<FDocument>() {
#Override
public String getValue(FDocumentobject) {
return object.getSize();
}
};
TextColumn<FDocument> modified_by_ColumnD = new TextColumn<FDocument>() {
#Override
public String getValue(FilenetDocument object) {
return object.getModifiedBy();
}
};
TextColumn<FDocument> dateColumnD = new TextColumn<FDocument>(){
#Override
public String getValue(FDocumentobject){
return object.getModifiedOn();
}
};
private void addValuesToTable(){
List<FDocument> FDC = null;
/*
* Adding data to folder Table
*/
ArrayList<FDocument> documentsArrayList = new ArrayList<FDocument>();
Iterator<String> iteratorDocument = documents.getDocuments().getDocumentCollection().keySet().iterator();
while(iteratorDocument.hasNext()){
String key = iteratorDocument.next().toString();
FDocument value = documents.getDocuments().getDocumentCollection().get(key);
documentsArrayList.add(new FDocument(value.getName(), value.getSize(),value.getModifiedBy(), value.getModifiedOn(),value.getId()));
}
FDC = documentsArrayList;
// Create a data provider.
ListDataProvider<FDocument> dataProvider1 = new ListDataProvider<FDocument>();
// Connect the table to the data provider.
dataProvider1.addDataDisplay(documentTable);
// Add the data to the data provider, which automatically pushes it to the widget.
List<FDocument> listDocument = dataProvider1.getList();
for (FDocument fDocument: FDC) {
listDocument.add(fDocument1);
}
This the way i have made my table and the value.
Plz any one tell me the procedure
to add icon before the name of the document.
and i also want one more Image column before name column
Use DefaultTableCellRenderer to set custom renderer against the column with the desired icon. As shown below, the renderer creates a new label to mask all the cells within the selected column.
private class CellRenderer extends DefaultTableCellRenderer
{
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
JLabel label = new JLabel((String)value);
label.setOpaque(true);
Icon icon = new ImageIcon("icon.png");
label.setIcon(icon);
return label;
}
}
And then apply it to your table as shown below:
table.getColumnModel().getColumn(0).setCellRenderer(new CellRenderer());
Edited:
If you're using GWT then see here for an example code for Grid Cell format.
For creating image column, You need to define a custom renderer that sets the icon on the label
import java.awt.Component;
import javax.swing.ImageIcon;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
public class MyRenderer extends DefaultTableCellRenderer {
/*
* #see TableCellRenderer#getTableCellRendererComponent(JTable, Object, boolean, boolean, int, int)
*/
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
ImageIcon icon = new ImageIcon(getClass().getResource("images/moon.gif"));
setText((String)value);
setIcon(icon);
return this;
}
}
And then, use the renderer in a table as follows,
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
public class Sample {
public static void main(String[] args) {
JFrame f = new JFrame("Sample");
f.getContentPane().setLayout(new GridLayout(1,0,0,0));
TableModel model = new AbstractTableModel() {
public Object getValueAt(int rowIndex, int columnIndex) {
return rowIndex + "," + columnIndex;
}
public int getColumnCount() {
return 3;
}
public int getRowCount() {
return 10;
}
};
JTable table = new JTable(model);
table.getColumnModel().getColumn(1).setCellRenderer(new MyRenderer());
JScrollPane pane = new JScrollPane(table);
f.getContentPane().add(pane);
f.pack();
f.setVisible(true);
}
}
Both of these will probably need a custom TableCellRenderer...
Refer to the API docs here... http://docs.oracle.com/javase/1.4.2/docs/api/javax/swing/table/DefaultTableCellRenderer.html
You basically want to overwrite the getTableCellRendererComponent() method, and add in any additional code for rendering the image.
For example, to add an icon before the document, you would do the following...
public void MyTableCellRenderer extends DefaultTableCellRenderer {
public MyTableCellRenderer(){
super();
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
Component renderer = super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
if (row == 0 && renderer instanceof JLabel){ // where row == 0 is the row you want to add the icon to
((JLabel)renderer).setIcon(new ImageIcon("image.png"));
}
return renderer;
}
}
You would need to set this as the TableCellRenderer for the column or table.
You would also do a similar thing for adding an image column to the table.

Categories