I want to put JEditorPane in JTable cell.
I've written this:
jTabel1.setDefaultRenderer(String.class, new StringEditorPane());
.........
class StringEditorPane extends JEditorPane
implements TableCellRenderer {
public StringEditorPane() {
setContentType("text/html");
}
public Component getTableCellRendererComponent(
JTable table, Object styledString,
boolean isSelected, boolean hasFocus,
int row, int column) {
if (isSelected) {
String styledText = (String) styledString;
setText(styledText);
setBackground(getSelectionColor());
return this;
} else {
String styledText = (String) styledString;
setText(styledText);
setBackground(Color.white);
return this;
}
}
}
I can compile it and it show JEditorPane but it also throws an exception and I don't know why.
Exception:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.text.DefaultStyledDocument.getParagraphElement(DefaultStyledDocument.java:445)
at javax.swing.text.StyledEditorKit$AttributeTracker.updateInputAttributes(StyledEditorKit.java:223)
at javax.swing.text.StyledEditorKit$AttributeTracker.caretUpdate(StyledEditorKit.java:258)
at javax.swing.text.JTextComponent.fireCaretUpdate(JTextComponent.java:391)
at javax.swing.text.JTextComponent$MutableCaretEvent.fire(JTextComponent.java:4387)
at javax.swing.text.JTextComponent$MutableCaretEvent.stateChanged(JTextComponent.java:4409)
at javax.swing.text.DefaultCaret.fireStateChanged(DefaultCaret.java:782)
at javax.swing.text.DefaultCaret.changeCaretPosition(DefaultCaret.java:1257)
at javax.swing.text.DefaultCaret.handleSetDot(DefaultCaret.java:1153)
at javax.swing.text.DefaultCaret.setDot(DefaultCaret.java:1134)
at javax.swing.text.DefaultCaret$Handler.removeUpdate(DefaultCaret.java:1777)
at javax.swing.text.AbstractDocument.fireRemoveUpdate(AbstractDocument.java:243)
at javax.swing.text.AbstractDocument.handleRemove(AbstractDocument.java:608)
at javax.swing.text.AbstractDocument.remove(AbstractDocument.java:576)
at javax.swing.JEditorPane.setText(JEditorPane.java:1493)
at myProject.StringEditorPane.getTableCellRendererComponent(MainWindow.java:136)
at javax.swing.JTable.prepareRenderer(JTable.java:5720)
........
And the 136 line from MainWindow.java:
setText(styledText);
from getTableCellRendererComponent function.
It seems the crash is thrown from removing old content.
Try to replace document with a new instance. Before setText() call
setDocument(getEditorKit().createDefaultDocument());
Looks like you need to handle a null value for your styledText variable.
Not sure why you need a custom renderer. The default renderer for the String class is a JLabel and JLabels support HTML.
Related
I'm devloping a application with Java swing ,my problem is : if i'm adding a new row , the getTableCellRendererComponent not called , my code :
the create of table :
public Tablecase() {
SystemeBaseConnaissance = new LESSymptomesEnsembleEt();
SystemeBaseConnaissance.lesSymptomesEnsembleEt.add("x");
initComponents();
jTable1.setTableHeader(null);
jTable1.getColumn("Title 1").setCellRenderer(new brmcellrender());
Model model = new Model();
jTable1.setModel( model);
model.addRow(new Object[]{"ss"});
System.out.println(SystemeBaseConnaissance.lesSymptomesEnsembleEt.size());
}
my Defaulttablemodel :
class Model extends DefaultTableModel{
public Model(){
super();
this.addRow(new Object[]{"sx"} );
repaint();
}
#Override
public void addRow(Object[] rowData) {
super.addRow(rowData); //To change body of generated methods, choose Tools | Templates.
}
}
my DefaultCellEditor :
public class brmcelleditor extends DefaultCellEditor{
public brmcelleditor(JTextField textField) {
super(textField);
}
}
public class brmcellrender extends DefaultTableCellRenderer{
public brmcellrender() {
super();
System.out.println("mefgoudabrahim20.Tablecase.brmcellrender.<init>()");
/**/
}
/*affichge */
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
System.out.println("mefgoudabrahim20.Tablecase.brmcellrender.<init>qsdqsdqsd()");
CaseOfTable cas = new CaseOfTable() ;
return ( cas) ;
}
}
if i'm adding a new row , the getTableCellRendererComponent not called
The problem is not because you add a new row.
jTable1.getColumn("Title 1").setCellRenderer(new brmcellrender());
Model model = new Model();
jTable1.setModel( model);
The problem is that you set the model after you set the renderer. When you set the model of a table the TableColumnModel and all the TableColums are recreated which means you lose the custom renderers you added to the TableColumn.
The code should be:
Model model = new Model();
jTable1.setModel( model);
jTable1.getColumn("Title 1").setCellRenderer(new brmcellrender());
Also, you would not create a new model every time you add a row. The point of adding a row is to add it to the existing model.
Finally, class names SHOULD start with an upper case character. Fix your renderer name.
My problem is that I want to change the individual background color of a cell in one column in a jTable. The code I have come up with changes the color to one and it applies to all the columns. What am I doing wrong?
This is my code
public void fillReserveTable() {
MemberDAO dao = DATA.MemberDAO.getInstance();
ResultSet res2 = dao.fillReservationTable();
try {
if (res2.next()) {
res2.beforeFirst();
reserveTable.setModel(DbUtils.resultSetToTableModel(res2));
setUpOnHold(reserveTable, reserveTable.getColumnModel().getColumn(4));
reserveTable.getColumnModel().getColumn(3).setCellRenderer(new CustomRenderer());
jScrollPane14.setVisible(true);
}else{
jScrollPane14.setVisible(false);
}
} catch (SQLException e) {
}
}
class CustomRenderer extends DefaultTableCellRenderer {
MemberDAO dao = DATA.MemberDAO.getInstance();
ResultSet res2 = dao.fillReservationTable();
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component cellComponent = super.getTableCellRendererComponent(reserveTable, value, isSelected, hasFocus, row, column);
int row2 = 0;
try {
while (res2.next()) {
String status = reserveTable.getValueAt(row2, 3).toString();
if (status.equals("Available")) {
cellComponent.setBackground(Color.green);
} else {
cellComponent.setBackground(Color.red);
}
row2++;
}
} catch (SQLException e) {
}
return cellComponent;
}
}
Cell rendering happens very frequently. You don't want to execute an SQL call as part of your rendering. Also, you should log the SQLException when it happens instead of silently swallowing it.
In this case, you're storing a result set as a field in the cell renderer. The first time you render, you iterate to the end of the result set.
Instead of querying for the status, use the value parameter which is passed to the renderer. This will be the value in the cell being rendered. If you need some other cell's value, get it from the TableModel.
In this code, I'm adding the data from Database. I want to set cell renderer with a label. But if I run this code I got only check box.
try {
List<Group> listgrChild = grMgmtModel.performList();
for (final Group group : listgrChild) {
table.getColumnModel().getColumn(0)
.setCellRenderer(new TableCellRenderer() {
// the method gives the component like whome the
// cell must
// be rendered
public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean isFocused,
int row, int col) {
boolean marked = new Boolean(String
.valueOf(value));
JCheckBox rendererComponent = new JCheckBox();
if (marked) {
rendererComponent.setSelected(true);
}
return rendererComponent;
}
});
tbModel.addRow(new Object[] { group.getGroupName() });
}
You comment, "renderComponent.setText("Hello") is giving only last value."
Verify that your TableModel has individual storage for each row's check box state and label value. In this example, the class Value holds the relevant data:
private static class Value implements Comparable<Value> {
private Boolean selected;
private Double value;
…
}
The corresponding TableModel manages a List<Value> and the required renderer and editor use the data from each Value instance accordingly. As an aside, Value implements the Comparable interface for convenience in sorting.
I have a MultilineCellRenderer which should wrap the multiple lines in JTable cell.
public class MultiLineTableCellRenderer
extends JTextArea implements TableCellRenderer {
/**
*
*/
private static final long serialVersionUID = 1L;
public MultiLineTableCellRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
setText(value.toString());//or something in value, like value.getNote()..
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setSize(table.getColumnModel().getColumn(column).getWidth(),
getPreferredSize().height);
if (table.getRowHeight(row) != getPreferredSize().height) {
table.setRowHeight(row, getPreferredSize().height);
}
return this;
}
}
I am creating and assigning this cell renderer as default cell renderer for myjtable(cnr_DATA)
MultiLineTableCellRenderer r = new MultiLineTableCellRenderer();
cnr_DATA.setDefaultRenderer(String.class, r);
cnr_DATA.setModel(new DefaultTableModel(data,columns){
public Class getColumnClass(int col){
return String.class;
};
});
I am also updating the content of jtable dynamically from the database
DefaultTableModel model = (DefaultTableModel)cnr_DATA.getModel();
removeAllCurrentRows(model);
Vector<DocumentRow> data =
RecycleSQL.readRecycledDocuments();//this line returning vector of objects
for(DocumentRow object:data)
model.addRow(new string[]{object.getFilename(),
object.getTitle(),object.getLastTouched()
,object.getLastTouchedBy()});
model.setRowCount(data.size());
cnr_DATA.revalidate();
My problem is that mycellrenderer is not being called and is not wrapping the data. Could some one please advice me how to call it after updating the content of the JTable.
Update according to the suggestion of Madprogrammer and hovercraft
After modifying the code according to the suggestion. Now the cellrenderer is being called but it is resting the row height to default value. This is the logs from debug statement
[2013-08-02 01:20:53,335] [AWT-EventQueue-0] DEBUG MultiLineTableCellRenderer - setting row height 3 128
[2013-08-02 01:20:53,335] [AWT-EventQueue-0] DEBUG MultiLineTableCellRenderer - setting row height 3 16
which means, that after setting the height of the row correctly it is resting it back to the default value
This looks suspect to me:
cnr_DATA.setDefaultRenderer(String.class, r); // ?? String.class
Are you sure that the model holds String data, and that the column type returned by getColumnClass(...) returns String? Consider instead setting the cell renderer for the column that needs it.
I wrote a class that implements TableCellRenderer, since I want to put checkboxes inside the jTable.
In the getTableCellRendererComponent method of this class, i have the condition :
if(isSelected){ do ..... }
inside this if condition, how can I know the row number ?
code :
private static class ValueRenderer extends JCheckBox
implements TableCellRenderer {
private static final Color hilite = new Color(0xE8E8E8);
public ValueRenderer() {
this.setOpaque(true);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,boolean hasFocus, int row, int col) {
Value v = (Value) value;
this.setSelected(v.selected);
if(isSelected)
{
if(v.selected==true)
System.out.println("checked");
else System.out.println("unchecked");
}
return this;
}
}
private static class Value {
private Boolean selected;
public Value(Boolean selected) {
this.selected = selected;
}
}
Why are you creating a Value class and a custom renderer? From the code it is just a Boolean. Just add the Boolean directly to the TableModel and then override the getColumnClass() method of the JTable or TableModel to return Boolean and the table will use the default Boolean renderer.
Read the JTable API and follow the link to the Swing tutorial on How to Use Tables for an example that uses Booleans.
Use the row parameter passed to your renderer. It's zero based just like arrays in Java.