I have a custom renderer in a JTable. When my JTable displays, I get a NullPointerException on JTable.prepareRenderer(). I'm not sure what part of my custom renderer isn't preparable, but I'm sure it's my fault.
Condensed version of my renderer (full version at this spot):
public class GradeRenderer extends JLabel implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object grade,
boolean isSelected, boolean hasFocus, int row, int column) {
if (grade == null) return new JLabel();
Grade myself = (Grade) grade;
int score = myself.getScore();
setText(String.valueOf(score));
Assessment thing = myself.getThing();
GradeStatus status = myself.getStatus();
AssessmentType type = thing.getType();
// do some work with status
// do some work with type
return this;
}
}
Code where I add the renderer (full version here):
model = new GradeEntryModel();
table = new JTable(model);
// some work with table
table.setDefaultRenderer(Grade.class, new GradeRenderer(true));
Any pointers as to where I've gone wrong?
The NPE message will give you the statement causing the error. So that is the place to start looking. Once you know which variable is null, you can start to solve the problem. We can't help you because we have no idea where the error is occuring.
The only think I can suggest is that you should not use "return null" to return a null renderer. You would set the text to "" or something like that and then return the renderer.
If you need more help then post your SSCCE that demonstrates the problem.
I agree with camickr, the NPE is telling you what is null so that should give you a clue.
But looking at your code i guess
if (grade == null) return null;
returning null is a good way to trigger a NullPointerException
Turns out some of my data in model is null. That'd do it.
Related
I created cellrenderer class for change my rows background.
if row's(rate%)colums value is something i try to change background of row.
But when i try it. Renderer only change non-Integer colums' background.
Here is my renderer.
public class hucreRenderer extends DefaultTableCellRenderer {
Color orginal=Color.white;
#Override
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);
int value;
try {
//10th column is a 'rate' column
v=Integer.parseInt(table.getModel().getValueAt(
table.convertRowIndexToView(row), 10).toString());
}catch(Exception e){value=1000;}
if(value<100){
cell.setBackground(Color.red);
else{
cell.setBackground(orginal);
}
return cell;
}
}
and Here is Table Inıt.
String col[] = {"ID","AD","GRUP", "ADET", "Kritik","TELEFON", "TEDARİKÇİ", "ALIŞ", "SATIŞ", "ADRES","RATE(%)"};
urunTablo.setModel(new DefaultTableModel(new Object[0][], col) {
Class[] types =
{ Integer.class, String.class,String.class,Integer.class,Integer.class,String.class,String.class,Integer.class,Integer.class,String.class,Integer.class };
DefaultTableModel t =(DefaultTableModel)urunTablo.getModel();
t.getDataVector().removeAllElements();
t.setColumnIdentifiers(col);
for(Urun u:urunler){
int r=new Integer(u.getRate());
Object row[]={
new Integer( u.getKod()),
u.getAd(),
u.getGrup(),
new Integer( u.getAdet()),
new Integer(u.getKritikAdet()),
u.getTelefon(),
u.getTedarikci(),
new Integer( u.getAlis()),
new Integer( u.getSatis()),
u.getAdres(), r};
t.addRow(row);
}
And here is result.
and intresting thing is. if i use Nimbus look and feel theme i dont come across whit this problem.
and there is a code for nimbus. i use this in main method of this dialog
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
//and the catchs...
Thank a lot alredy now.
have a nice day.
Edit:default cell renderer doesnt work for cells which is hold Integer.class.
Thats the main problem.
After a lot of reseach and test :) finally i found the problem.
Problem is setting the tables default renderer style
I was using this type before(Ex code)
myTable.setDefaultRenderer(Object.class,new MyDefaultCellRenderer());
and this is getting object.class to String.class (in Default)(cause DefaultCellRenderer xD)
and the renderer just work on String cells
And i set my renderer again like this
myTable.setDefaultRenderer(Integer.class,new MyDefaultCellRenderer());
myTable.setDefaultRenderer(String.class,new MyDefaultCellRenderer());
Now this is can work for Integer and String cells
Working and Metal! :)
So u gonna say what about the Look and feel stuff
I think in Nimbus LAF setDefaultRenderer(Object.class,new MyDefaultCellRenderer()) get all type of Object.
Other LAF's doesnt.
Thanks a lot guys. If you have a extra thought about that please leave comment below.
Have a easy work :)
We are using a JTable which displays data along with Status (New, Processed, Closed). Each status row has a different color which is achieved by overloading prepareRenderer() of JTable.
Now we need to sort that table and we are using table.setAutoCreateRowSorter(true); to achieve that. The rows get sorted properly, but the color of rows remains the same. We need to reapply the color to all the rows after this operation based on the status column.
I was wondering what could be the best way to achieve that. There are several ways I can think of:
Repaint/Revalidate the table. But simply doing this would not work I think.
Capture mouseClicked event and identify whether column header was clicked then call prepareRenderer() manually and then call repaint/revalidate
Then I read one of the questions here wherein one of the answers was mentioned not to call repaint/revalidate directly, rather change the underlying data model and it will automatically call the above methods.
I don't know how to go about it. Can anyone please provide an insight into what is the correct way to achieve this?
For change cell color in JTable with setAutoCreateRowSorter(true) I used method table.getRowSorter().convertRowIndexToModel(row) in my TableCellRenderer
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;
import java.awt.*;
public class OwnTableCellRenderer extends DefaultTableCellRenderer {
public OwnTableCellRenderer() {
super();
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
setBackground(Color.white);
setForeground(Color.black);
TableModel model = table.getModel();
int modelRow = table.getRowSorter().convertRowIndexToModel(row);
int columnStatusPosition = 5;
String statusColumnValue = (String) model.getValueAt(modelRow, columnStatusPosition);
if (statusColumnValue.equals("ACTIVE")) {
if (isSelected) {
setBackground(Color.green);
} else {
setBackground(Color.yellow);
}
}
setText(value != null ? value.toString() : "");
return this;
}
}
And then
table.setDefaultRenderer(Object.class, new OwnTableCellRenderer());
This summer is not a real summer, i thought.
A cup of coffee make me feel it as a summer, tough (lol).
I have a little bit naughty JTable. OMG.
Below is my JTable that use my own customized TableModel. You could see it on its method of getColumnClass(), there... it was made for returning as JLabel only.
ANd then, I also customize the DefaultRenderer.
jtbl_inGameEasy = new javax.swing.JTable();
jtbl_inGameEasy.setFont(new java.awt.Font("squeaky chalk sound", 0, 14)); // NOI18N
jtbl_inGameEasy.setForeground(new java.awt.Color(255, 255, 255));
jtbl_inGameEasy.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
"null", "null", "null", "null", "null"
}
) {
boolean[] canEdit = new boolean [] {
false, false, false, false, false
};
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
public Class getColumnClass(int columnIndex) {
return JLabel.class;
}
});
jtbl_inGameEasy.setDefaultRenderer(JLabel.class, new JLabelTableRenderer());
jtbl_inGameEasy.setFocusable(false);
jtbl_inGameEasy.setOpaque(false);
jtbl_inGameEasy.setRowHeight(55);
jtbl_inGameEasy.setShowHorizontalLines(false);
jtbl_inGameEasy.setShowVerticalLines(false);
jtbl_inGameEasy.setTableHeader(null);
jtbl_inGameEasy.addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent evt) {
jtbl_inGameEasyMousePressed(evt);
}
});
And Where is the JTableRenderer? Here...
this is my Custom Renderer below...
public class JLabelTableRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
if (value instanceof JLabel) {
//This time return only the JLabel without icon
return (JLabel) value;
} else {
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}
And then, I need to pu JLabel inside each of the Cell.
I start to add some JLabel(s) inside the Object of Array over the Cells of the JTable using this code; (which is no problem).
DefaultTableModel o_dtb = jtbl_inGameEasy.getModel();
o_dtb.addRow(myArrayCustomizedObjectofJLabel);
Everything works fine, I guess. But because of My purpose is that ---> To put an Icon or to make it Invisible once the user Click on JTable Cells, thus I I tried to do my MouseEvent once pressed and calling these lines of code;
private void jtbl_inGameEasyMousePressed(java.awt.event.MouseEvent evt) {
// Checking inGameEasy Table Ans
javax.swing.JTable source = (javax.swing.JTable) evt.getSource();
int row = source.rowAtPoint(evt.getPoint());
int column = source.columnAtPoint(evt.getPoint());
DefaultTableModel o_dtb = (DefaultTableModel) jtbl_inGameEasy.getModel();
String s_questAns = "" + Game.getCurrentQuestion().getResult();
String s_userAns = "" + o_dtb.getValueAt(row, column);
// These two lines below are not Working, why yaa??
((JLabel) o_dtb.getValueAt(row, column)).setVisible(false);
((JLabel) o_dtb.getValueAt(row, column)).setIcon(myIcon);
if (s_questAns.equals(s_userAns)) {
Game.correct();
System.err.println("nice ans!");
} else {
jll_txtMiss.setText("Miss : " + Game.wrong());
System.err.println("nope!");
}
nextQuestion();
}
And seems to me that the Marked (below the commented) code above are not working.
Yeah, the JLabel casted couldn't be changed its Icon (image), and nor its visibility as well. Is it the Model cause all of this?
NB: My Cells data added later after the Model created differently.
It seems to me that what you want to do is to just leave all table cells empty, except the ones clicked by the user, where some mark icon should appear, right?
If so, your table model should not contain JLabel instances. A JLabel is a visual component, used to render some data graphically. The data itself is not a JLabel. In your case, I think it should thus be a Boolean (true when clicked by the user, false otherwise).
Now you could use a custom renderer (although the default one for booleans could also be OK) to display your booleans. This renderer would be a subclass of DefaultTableCellRenderer, which is itself a subclass of JLabel. The renderer (the same instance for all the cells configured to use this renderer) would just display a marked icon if the Boolean value to render is true, and a not marked icon (or no icon at all) when the Boolean value to render is false.
Then, your click handler would just have one mission: make the clicked cell contain true rather than false. To do that, it would just have to change the appropriate value in the table model.
To recap: a table model is used to hold data. Think of it as the data you would find in a database. Would you hold a JLabel in the database? No, you would hold a boolean, a string or an integer. The table can render this data as you want, and this is the mission of the renderer.
Side note: stop with the hungarian notation: it doesn't make sense in Java. It makes code hard to read. Everything except primitive types is an object, and you can't assign a meaningful prefix to every possible type. Rather, use readable and meaningful english names : tableModel rather than o_dtb, correctAnswer rather than s_questAns, userAnswer rather than s_userAns.
Im trying to create a scrollPanel that holds a list of checkbox item. My main problem is constructing a CellList with CheckboxCell. Here is a snippet of whats causing the compile time error.
CheckboxCell testCheckBox = new CheckboxCell();
CellList<String> cellList = new CellList<String>(testCheckBox);
Error Message: The constructor CellList(CheckboxCell) is undefined.
If this is the wrong constructor, what is the correct way?
Try changing the type of CellList to Boolean.
CheckboxCell testCheckBox = new CheckboxCell();
CellList<Boolean> cellList = new CellList<Boolean>(testCheckBox);
update:
More examples on various cells (this is combined checkbox + picture, but you might want to replace picture with text):
http://gwt.google.com/samples/Showcase/Showcase.html#!CwCellTree
It's little trickier, but this showcase contains also sources so might want to dive into them.
PS: Lazier solution is not to use Cell Widgets and make own (extends Composite) combo/label and place it in say FlexTable :)
You can try something like that. You are going to need some extra native code to handle the "check" event.
public class StyleCell extends AbstractCell<Style> {
#Override
public void render(Context context, Style row, SafeHtmlBuilder sb) {
if (row == null) {
return;
}
sb.appendHtmlConstant("<INPUT TYPE=CHECKBOX NAME='property'>" + row.getProperty() + "</INPUT>");
}
}
StyleCell styleCell = new StyleCell();
CellList<Style> styleList = new CellList<Style>(styleCell);
I am creating my first JTable that requires me to create a custom AbstractTableModel, TableCellEditor, and DefaultTableCellRenderer. Given that I have not needed to create these before, I've made some significant progress in getting my table to behave as desired.
However, I am getting overwhelmed with all the different methods I am overriding, and am spinning my wheels trying to figure out how to modify the ImageIcon of a particular cell. The cell must contain a JLabel, as it needs both an ImageIcon as well as a text string. I can already set the initial ImageIcon (although I am probably doing it incorrectly), but I can't set an updated ImageIcon. Nothing fails, but no change is made.
In a general sense, what is the best way to get and set an icon to a JLabel cell of a JTable, assuming all of these models, editors, and renderers have already been instantiated?
My model has already been defined to return JLabel.class for these cells, if you're wondering, and I also do a fireTableCellUpdated(row, col) once the change has supposedly been made. If I do a System.out.println(getIcon()) before and after the update, I can even see the source has changed.
Here is some of the code (updated with URL/ImageIcon fix in place):
class MonitorTable extends JTable {
MonitorTableModel model = new MonitorTableModel(rows, columnNames);
setModel(model);
...
public void setIconAt(ImageIcon icon, int row, int col) {
model.setIconAt(icon, row, col);
} // End setIconAt(ImageIcon, int, int)
...
class MonitorTableModel extends AbstractTableModel {
...
public void setIconAt(ImageIcon icon, int row, int col) {
StatusTableCellRenderer cell =
(StatusTableCellRenderer)getColumnModel().getColumn(col).getCellRenderer().
getTableCellRendererComponent(myTableObject, null, false, false, row, col);
System.out.println(cell.getIcon()); // Shows initial icon source
cell.setIcon(icon);
fireTableCellUpdated(row, col); // Should update the table
System.out.println(cell.getIcon()); // Shows new icon source
System.out.println("Cell updated");
} // End setIconAt(ImageIcon, int, int)
} // End class MonitorTableModel
public class StatusTableCellRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int col) {
setIcon(imgGray);
setText((String)value);
return this;
} // End getTableCellRendererComponent(JTable, Object, boolean, boolean, int, int)
} // End class StatusTableCellRenderer
} // End class MonitorTable
My model has already been defined to return JLabel.class for these cells,
But according to the code in your renderer you expect a String value in these cells:
setText((String)value);
I don't like your setIcon() method. I would not pass in the URL. I would pass in the Icon. Maybe you have a problem that the icon has not been read into memory at the time the cell is rendered.
what is the best way to get and set an icon to a JLabel cell of a JTable,
You should not store a JLable in the TableModel. It is expensive to store Swing components in the model, that is why Swing components use renderers. Instead you store a custom Object like "LabelInfo" which contains two properties, the text and the Icon. Then your custom renderer will extend the default renderer and invoke super.getTableCellRendererComponent(). You can then access your object and rest the text/icon properties of the renderer. You should not be creating objects in the renderer.
Now when you want to change something in the model you can do:
LabelInfo info = (LabelInfo)table.getValueAt(row, column);
info.setIcon(...);
table.setValueAt(info, row, column);
Thats all you need. There is not custom code to repaint the cell or anything because that is already built intothe setValueAt(...) method. of your table model.
Edit: a simple example for using a custom Object in the TableModel.
1) to add the object to the model you do something like:
LabelInfo info = new LabelInfo("some Text", yourIcon);
table.setValueAt(info, row, column);
2) the code for your custom renderer would be:
class LabelInfoRenderer extends DefaultTableCellRenderer
{
#Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
LableInfo info = (LabelInfo)value;
setIcon( info.getIcon() );
return this;
}
}
Call the fireTableDataChanged from your model.
Try call the repaint method from JLabel too.
The better way to do it, is implement a CellRenderer, with returns a JPanel and make the draw method in the paintComponent. You can load a BufferedImage instead of a ImageIcon and use it to draw in the JPanel.
Try change you Renderer to:
public class StatusTableCellRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int col) {
JLabel comp = new JLabel(new ImageIcon(imgGray));
comp.setText((String)value);
return comp;
} // End getTableCellRendererComponent(JTable, Object, boolean, boolean, int, int)
}
You are doing some mess, this is not the right way to work with the TableModel, you should return the URL for the image in the getValueAt(int row, int col), after it, register the CellRenderer to correspond to cells with URL.class. The renderer is automatically called from the JTable, you don't need to extends JTable either, you have only to implement the Renderer and the Model.
The setIconAt should only call the setValueAt and put your URL at the column, the renderer take care of the rest.
I fixed this by changing setIcon(imgGray) to if (getIcon() == null) setIcon(imgGray);.
The issue is my getTableCellRendererComponent method was setting the icon to imgGray every time. Apparently my setIconAt method, which calls getTableCellRendererComponent, was being overridden, even though the "new" icon value was processed after the "old" value was (re)set.
I ended up removing all my setIcon methods and moved the relevant logic into my StatusTableCellRenderer class. That way I pass the value of the cell and let the renderer do the icon setting based on that value. It makes more sense this way, and works beautifully. I have confirmed that initial setting and all subsequent updates are performing as expected.
The logic of setting the icon is pretty simple -- set the predefined icon based on certain predefined threshold values.
double val;
if (getIcon() == null) setIcon(imgGray); // Initialize
if ((value == null) || (value == "")) {
val = 0;
} else {
val = Double.parseDouble(value.toString());
} // End if
if (val <= THRESHOLD1) {
setIcon(icon1);
} else if (val <= THRESHOLD2) {
setIcon(icon2);
...
} // End if
setText(value.toString());
I was very concerned about suggestions to make brand new objects to use, when the default JLabel was exactly what I needed. It was both unnecessary and a potential performance hit to the JTable. Thank you all for your insight and assistance. This was driving me batty!