I'm building a custom table cell editor so it adjusts row height during editing. I have this code, but instead of resizing the cell it seams to resize the whole panel, or the frame. When I try to enter a character in a cell the main frame width narrows down to a couple of pixels.
Can anyone see the problem?
class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor {
MyTextpane component = new MyTextpane();
MyTable table;
private int row;
private int col;
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
int rowIndex, int vColIndex) {
((MyTextpane) component).setText((String) value);
component.addKeyListener(new KeyListener1());
this.table =(MyTable) table;
this.row = rowIndex;
this.col = vColIndex;
return component;
}
public Object getCellEditorValue() {
return ((MyTextpane) component).getText();
}
public class KeyListener1 implements KeyListener {
#Override
public void keyTyped(KeyEvent ke) {
}
#Override
public void keyPressed(KeyEvent ke) {
}
#Override
public void keyReleased(KeyEvent ke) {
adjustRowHeight(table, row, col);
}
private java.util.List<java.util.List<Integer>> rowColHeight = new ArrayList<java.util.List<Integer>>();
private void adjustRowHeight(JTable table, int row, int column) {
//The trick to get this to work properly is to set the width of the column to the
//textarea. The reason for this is that getPreferredSize(), without a width tries
//to place all the text in one line. By setting the size with the with of the column,
//getPreferredSize() returnes the proper height which the row should have in
//order to make room for the text.
int cWidth = table.getTableHeader().getColumnModel().getColumn(column).getWidth();
setSize(new Dimension(cWidth, 1000));
int prefH = getPreferredSize().height;
while (rowColHeight.size() <= row) {
rowColHeight.add(new ArrayList<Integer>(column));
}
java.util.List<Integer> colHeights = rowColHeight.get(row);
while (colHeights.size() <= column) {
colHeights.add(0);
}
colHeights.set(column, prefH);
int maxH = prefH;
for (Integer colHeight : colHeights) {
if (colHeight > maxH) {
maxH = colHeight;
}
}
if (table.getRowHeight(row) != maxH) {
table.setRowHeight(row, maxH);
}
}
}
}
have look at
my answer about doLayout(could be fired from CellEditor)
or (more than confortable way to use TextUtils) comment by #kleopatra about getPreferredSize
this could (very) confusing the users,
because I miss JScrollPane, there have to override MaxSize, max size is height & weight for JScrollPane, otherwise part of CellEditor can going outside of screeens bounds .........,
don't do that, put there JScrollPane with JTextComponents, override PreferredSize for CellEditor,
everything are wrong, my view,
create applications modal popup window (based only on JDialog, becasue JWindow doesn't alloved input to the JTextComponent) with JTextComponent, implements there KeyBindings for ESC key, the same for lost Fucus for JDialog, then could be undecorated without any issue
put there Save JButton
output from Save Button reditect to the selected cell, you can't lost focus from application modal inside JTable
contents should be formatted, filtered, modified one JDialog for all cells from JTable
As an alternative to resizing the row while editing, consider TablePopupEditor, which uses JTextArea.
Related
I would like to make an editable table and then check the data to make sure its valid. Im not sure how to change the color of just one cell. I would like to get a cell, for example (0,0) and color the foreground to red. I have read the other posts on SO as well as Oracle about the custom ColorRenderer, but i just don't get how i would use this.
Thanks.
Say that the cell you would like to render with a different color represents a status (I'll take Rejected and Approved as examples). I'd then implement a method in my table model called getStatus(int row) which returns the status for any given row.
Then, when that is in place, I'd go about creating a cell renderer responsible for rendering the column which the cell belongs to. The cell renderer would be something in the lines of the below code.
public class StatusColumnCellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
//Cells are by default rendered as a JLabel.
JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
//Get the status for the current row.
CustomTableModel tableModel = (CustomTableModel) table.getModel();
if (tableModel.getStatus(row) == CustomTableModel.APPROVED) {
l.setBackground(Color.GREEN);
} else {
l.setBackground(Color.RED);
}
//Return the JLabel which renders the cell.
return l;
}
Then, when the renderer is in place, simply "apply" the renderer to the table with the following piece of code:
Table.getColumnModel().getColumn(columnIndex).setCellRenderer(new StatusColumnCellRenderer());
With regard to making a cell editable, simply implement the isCellEditable(int rowIndex, int columnIndex) method in your table model. You also need to implement the method
setValueAt(Object value, int rowIndex, int columnIndex) if you would like to keep the value which the user provides (which i assume you do!).
I would like to make an editable table and then check the data to make sure its valid.
Another approach would be to edit the data before it is saved to the table model to prevent invalid data from being entered.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class TableEdit extends JFrame
{
TableEdit()
{
JTable table = new JTable(5,5);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollpane = new JScrollPane(table);
getContentPane().add(scrollpane);
// Use a custom editor
TableCellEditor fce = new FiveCharacterEditor();
table.setDefaultEditor(Object.class, fce);
}
class FiveCharacterEditor extends DefaultCellEditor
{
FiveCharacterEditor()
{
super( new JTextField() );
}
public boolean stopCellEditing()
{
try
{
String editingValue = (String)getCellEditorValue();
if(editingValue.length() != 5)
{
JTextField textField = (JTextField)getComponent();
textField.setBorder(new LineBorder(Color.red));
textField.selectAll();
textField.requestFocusInWindow();
JOptionPane.showMessageDialog(
null,
"Please enter string with 5 letters.",
"Alert!",JOptionPane.ERROR_MESSAGE);
return false;
}
}
catch(ClassCastException exception)
{
return false;
}
return super.stopCellEditing();
}
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
Component c = super.getTableCellEditorComponent(
table, value, isSelected, row, column);
((JComponent)c).setBorder(new LineBorder(Color.black));
return c;
}
}
public static void main(String [] args)
{
JFrame frame = new TableEdit();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
I believe the correct way to do colouring in a table is via a ColorHighlighter. The table renderers have problems to render different colours in the same column.
Here is an example of how to use highlighters. In this case it is for highlighting a cell that is not editable.
public class IsCellEditablePredicate implements HighlightPredicate {
private JXTable table;
public IsCellEditablePredicate (final JXTable table) {
this.table = table;
}
#Override
public boolean isHighlighted(Component component, ComponentAdapter componentAdapter) {
return !table.isCellEditable(componentAdapter.row,
componentAdapter.column);
}
}
and then in your code for setuping the table you add the highlighter and its colour parameters:
ColorHighlighter grayHighlighter = new ColorHighlighter(new IsCellEditablePredicate(table));
grayHighlighter.setBackground(Color.LIGHT_GRAY);
grayHighlighter.setForeground(table.getForeground());
grayHighlighter.setSelectedBackground(table.getSelectionBackground().darker());
grayHighlighter.setSelectedForeground(table.getSelectionForeground().darker());
table.setHighlighters(grayHighlighter);
This is the simplest way to color a particular Column or cell in a jTable.
First just create a simple class of CustomRenderer
class CustomRenderer extends DefaultTableCellRenderer <br />
{
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);
setForeground(Color.blue); >
return c;
}
}
This code gets the column of cell to render
TableColumn col = tblExamHistoryAll.getColumnModel().getColumn(5);
DefaultTableModel model3 = (DefaultTableModel)tblExamHistoryAll.getModel();
col.setCellRenderer(new CustomRenderer());
This is to clear all previous rows from your table. If you do not want them just remove these lines
model3.getDataVector().removeAllElements();
model3.fireTableDataChanged();
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int col) {
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
int control = row;
control = control % 2;
control = (control == 0) ? 1 : 0;
if (control == 1) {
c.setBackground(Color.green);
} else {
c.setBackground(Color.cyan);
}
return c;
}
The most straightforward way is to write a simple TableCellRenderer by extending the DefaultTableCellRenderer and overwriting the getTableCellRendererComponent method to setBackground( Color.RED ). For example:
final JTable table = new JTable(...);
table.setCellRenderer( new DefaultTableCellRenderer() {
public Component getTableCellRenderer(JTable table, Object value, ...) {
super.getTableCellRenderer(...);
if ( value should be highlighted ) {
setBackground( Color.RED );
}
return this;
}
});
You can extend DefaultTableCellRenderer, override getTableCellRendererComponent and call something like
if (myConditions) setBackground(myColor);
before returning "this" when conditions apply but it has a very annoying side-effect of changing the default back-color due to the way DefaultTableCellRenderer.setBackGround is coded.
The trick I found was to entirely duplicate the code of DefaultTableCellRenderer in a class named HackedDefaultTableCellRenderer, add a method that calls directly the Component's setBackground implementation:
public void setComponentBackground(Color c) {
super.setBackground(c);
}
then derive my customized rendered from this hacked class instead of from DefaultTableCellRenderer, and finally call setComponentBackground instead of setBackground in my customized getTableCellRendererComponent.
The drawback is that this HackedDefaultTableCellRenderer relies on a snapshot of DefaultTableCellRenderer.
I 'm a Java beginner.
I create an application with a JTable which is populated with a database.
In my database I have some 'news'. In my JTable I display titles of 'news' and when an user click on a row, it display a popup with the right contents of the news.
But I want to colorize the cell which are 'read' when the user clicked on it.
I use my own TableModel.
I hope I'm clear...
If I need to put some code, tell me what please...
public class JTableTest extends JFrame {
private JTable table;
private int col;
private int rowz;
/**
* Create the frame.
*/
public JTableTest() {
initComponents();
}
private void initComponents() {
/** any other components */
table = new JTable();//create the table
table.setDefaultRenderer(Object.class, new CustomModel());
table.addMouseListener(new CustomListener());
}
public class CustomListener extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent arg0) {
super.mouseClicked(arg0);
//get the clicked cell's row and column
rowz = table.getSelectedRow();
col = table.getSelectedColumn();
// Repaints JTable
table.repaint();
}
}
public class CustomModel extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
#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);
Color c = Color.WHITE;//define the color you want
if (isSelected && row == rowz & column == col)
c = Color.GREEN;
label.setBackground(c);
return label;
}
}
}
Found this example of how to get the table cell on mouseClick: http://codeprogress.com/java/showSamples.php?index=52&key=JTableValueofSelectedCell
You can use this to get the selected row and column.
Then you need to create a custom TableCellRenderer, possibly as an inner class so that it can use the selected row and column data and set the background of the cell to your highlighted color
I'm trying to build a table which includes JComboBoxes as both the renderer and editor components. This mostly works fine, however there are two things I can't seem to solve.
Tabbing between cells should make the JComboBox active
Clicking the drop-down arrow should immediately open the option list
Regarding 1, the editable combo should place focus within the embedded text field, the fixed combo should allow the down arrow to open the list of options.
Regarding 2, I find that this sometimes works depending on what other cell is currently active, but other times I have to double click. I cannot make this behaviour consistent.
For convenience I have included a clear example which (I believe) uses the recommended approach for embedding JComboBoxes within Jtables.
Thank you for constructive advice.
import java.awt.Component;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableCombos
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Frame");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
AbstractTableModel model = new DefaultTableModel()
{
String[] columnHeaders = new String[]{"label", "combo-edit", "combo-fixed"};
Class<?>[] columnClasses = new Class<?>[]{String.class, Double.class, Double.class};
List<Object[]> data = new ArrayList<>();
{
data.add(new Object[]{"row 1", 1.0d, 2.0d});
data.add(new Object[]{"row 2", 2.0d, 3.0d});
}
#Override
public int getColumnCount()
{
return columnHeaders.length;
}
#Override
public boolean isCellEditable(int row, int column)
{
return column != 0;
}
#Override
public int getRowCount()
{
if (data == null) // race condition
return 0;
return data.size();
}
#Override
public Object getValueAt(int row, int column)
{
return data.get(row)[column];
}
#Override
public void setValueAt(Object aValue, int row, int column)
{
data.get(row)[column] = aValue;
}
#Override
public Class<?> getColumnClass(int column)
{
return columnClasses[column];
}
#Override
public String getColumnName(int column)
{
return columnHeaders[column];
}
};
JTable table = new JTable(model);
table.setSurrendersFocusOnKeystroke(true);
TableColumn c1 = table.getColumnModel().getColumn(1);
TableColumn c2 = table.getColumnModel().getColumn(2);
JComboBox<Double> editorComboEditable = new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d});
editorComboEditable.setEditable(true);
c1.setCellEditor(new DefaultCellEditor(editorComboEditable));
c2.setCellEditor(new DefaultCellEditor(new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d})));
final JComboBox<Double> rendererComboEditable = new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d});
rendererComboEditable.setEditable(true);
final JComboBox<Double> rendererComboFixed = new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d});
c1.setCellRenderer(new TableCellRenderer()
{
#Override
public Component getTableCellRendererComponent(JTable t, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
rendererComboEditable.setSelectedItem(value);
return rendererComboEditable;
}
});
c2.setCellRenderer(new TableCellRenderer()
{
#Override
public Component getTableCellRendererComponent(JTable t, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
rendererComboFixed.setSelectedItem(value);
return rendererComboFixed;
}
});
frame.getContentPane().add(new JScrollPane(table));
frame.pack();
frame.setVisible(true);
}
}
Both of your issues be resolved by overriding the DefaultCellEditor#isCellEditable method and returning true
You may need to set JTable#setSurrendersFocusOnKeystroke to true as well
Update
The short answer is "It's messy". The long answer is "it's very messy"
I did a "continuos editing" process some time back. Basically, I overrode the Enter and Tab key bindings.
What I'd did was basically stop any active cell editor, take note of the current cell and then tried to finding the next editable cell, looping back around to the start (cell 0x0) if required.
When I found a editable cell, I called JTable#esitCellAt to start editing the cell.
To get the popup to be visible when the cell starts editing, you will need to override the addNotify method of the JComboBox and, using SwingUtilities#invokeLater, set the popup visible
Compilable source can be found at: http://www.splashcd.com/jtable.tar
I'm new to the language, so I'm not sure if this is acceptable behavior or not.
I created a JTable to display a row for each message received (it receives about
one every 20 seconds). One of the table columns can contain a large amount of
text, so I created a custom cell renderer which word wraps and sets the row
height accordingly.
All that works as expected, except that once the table displays its first row,
it calls the cell renderer about ten times a second... until the user closes the
table.
Once I get approx 20 rows in there, the table gets fairly sluggish, taking 2-8
seconds to resize a column, scoll up or down, or render a selected row with the
selected background color.
I inserted a print statement inside the renderer, so I can see how many times
the getTableCellRendererComponent method is being called.
I disabled tool tips, and disabled all cell editing. I do have a listener that
scrolls the view to the last row when either a new row is added or the table is
resized.
Should the getTableCellRendererComponent method be called several times a second
when I'm just viewing the screen (not touching mouse or keyboard)?
TIA
aaaaach
you need doLayout(),
next level :-), then there you can to set Maximum visible rows for JTextComponents too, with little effort
doLayout()
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;
//http://tips4java.wordpress.com/2008/10/26/text-utilities/
public class AutoWrapTest {
public JComponent makeUI() {
String[] columnNames = {" Text Area Cell Renderer "};
Object[][] data = {
{"123456789012345678901234567890"},
{"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddx"},
{"----------------------------------------------0"},
{">>>>>>>>>>>>>dddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddxdddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddddddx>>>>>>>>>>>>>>>>>>>>>>>>>|"},
{">>>>>>>>>>>>ddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "ddddddx>>>>>>>>>>>>>>>>>>>>>>>>>>|"},
{"a|"},
{">>>>>>>>bbbb>>>>>>>>>>>>>>>>>>>|"},
{">>>>>>>>>>>>>>>>>>|"},
{">>>>>>>>>>>>>dddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddxdddddddddddddd123456789012345678901234567890dddddd"
+ "dddddddddddddddddddddddddddddddddddddx>>>>>>>>>>>>>>>>>>>>"
+ ">>>>>|"},
{">>>>>>>>>>>>>dddddddddddddd123456789012345678901234567890dddddd"
+ "dddddddddddddddddddddddddddddddddddddxdddddddddddddd123456"
+ "789012345678901234567890dddddddddddddddddddddddddddddddddd"
+ "ddddd123456789012345678901234567890ddddx>>>>>>>>>>>>>>>>>>"
+ ">>>>>>>|"},};
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();
}
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());
//table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane sp = new JScrollPane(table);
sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
sp.setPreferredSize(new Dimension(250, 533));
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.setLocation(100, 100);
f.pack();
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);
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;
}
}
To get the most performance out of a TableCellRenderer, make sure you're not creating a new instance of a component every time getTableCellRenderer is called. Make the components once and save them as fields of the class.
Also, you'll want to make sure each of the Components you use have the following methods overridden to do nothing:
validate
invalidate
revalidate
repaint
firePropertyChange
(and you probably want to hard code isOpaque).
For more information see: http://docs.oracle.com/javase/6/docs/api/javax/swing/tree/DefaultTreeCellRenderer.html
The problem seems to stem from having JTable's setRowHeight() inside the custom cell renderer, as it calls the custom cell renderer, throwing it into an infinite loop.
I had to add in a check to see if the current row height matched the calculated word wrapped row height. If it did, I didnt try to setRowHeight() again.
Corrected Code:
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.table.TableCellRenderer;
//custom cell renderer for word wrapping, but if you use, you have to
//implement zebra striping functionality which the default renderer has
public class LineWrapCellRenderer extends JTextArea implements TableCellRenderer
{
private int numOfTimesCalled;
#Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column)
{
System.out.println("Line Wrap Cell Renderer Called: " + numOfTimesCalled++);
System.out.println("row:"+ row + ", col:" + column);
//set up the row size based on the number of newlines in the text in the cell
int fontHeight = this.getFontMetrics(this.getFont()).getHeight();
int numWraps = value.toString().split("\r\n|\r|\n").length;
int rowHeight = fontHeight * numWraps;
//if the calculated rowHeight is the same as the row height of row,
// then don't call setRowHeight again, as doing so will throw us into
// an infinite loop
if(rowHeight != table.getRowHeight(row))
{
table.setRowHeight(row, rowHeight);
//configure word wrapping
setWrapStyleWord(true);
setLineWrap(true);
//use the table's font
setFont(table.getFont());
}
//zebra striping, because whatever cell uses this renderer loses the
//default cell renderer zebra striping
if(isSelected)
{
setBackground(table.getSelectionBackground());
}
else
{
if(row%2 == 1)
{
setBackground(UIManager.getColor("Table.alternateRowColor"));
}
else
{
setBackground(table.getBackground());
}
}
this.setText(value.toString());
return this;
}
}
I have a JTable with custom TableCellRenderer.
public class DateCellRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 58L;
public DateCellRenderer() {
super();
setHorizontalAlignment(CENTER);
setOpaque(true);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof Date) {
String date = new SimpleDateFormat("dd-MM-yyyy").format((Date) value);
setText(date);
}
return this;
}
}
Also in my application I have a drop down menu by which I can change the look and feel. This drop down menu is in a parent frame and the table is in a dialog. When the dialog is opened the parent frame is inaccessible. So to change the look and feel I have to close the dialog first.
Now in a particular skin if the table is populated by some data and I change the look and feel from parent frame and again open the dialog then the column, where I have added the TableCellRenderer, is keeping the old look and feel. It is not updating while the other columns render themselves in the new look and feel.
I am unable to find the problem and its solution. Any help is appreciable.
Note: The look and feel update of the application is made by the following snippet
javax.swing.UIManager.setLookAndFeel(uiProperties.getThemeModel().getThemeClass());
ComponentFactory.getLibraryFrame().getRootPane().updateUI();
for (int i = 0; i < Frame.getWindows().length; i++) {
SwingUtilities.updateComponentTreeUI(Frame.getWindows()[i]);
}
for (int i = 0; i < Frame.getFrames().length; i++) {
SwingUtilities.updateComponentTreeUI(Frame.getFrames()[i]);
}
Thanks in advance.
In HiFi theme chosen first:
Then I change the theme to Fast, and the second column "Released" not updated its ui:
The JTable is:
public class MovieSearchResultTable extends BaseTable {
private static final long serialVersionUID = 45L;
public MovieSearchResultTable(TableModel tableModel) {
super(tableModel);
LibraryLogger.initMessage(getClass().getSimpleName());
}
#Override
public void initialize() {
setFillsViewportHeight(true);
setAutoResizeMode(AUTO_RESIZE_OFF);
getColumnModel().getColumn(1).setCellRenderer(new DateCellRenderer());//if I comment out this line then no problem. but without CellRenderer how could I format a Date, if I use formatted String instead of Date, then the column will not sort!!
}
#Override
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().getWidth() < getParent().getWidth();
}
}
I think that not good L&F, JTable looks like ... ok, but other Compound JComponents aren't ...., not sure I haven't wasting my time, I leaving to test that, maybe is there something described about that on their Forum or Documentation or BugParades, but nothing from your question
there is very simple way and you can any time to check that
1) go to Insubstantial
2) download code source,
3) import all classes to the IDE (2-15 min depends of PC HardWare)
4) search for folder test, there is Check.java,
5) run that and to try everything in JMenu Look and Feel, before that required to download API's for every Custom Java Swing Look and Feels
The solution, you need to override public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
Here is the class:
public class MovieSearchResultTable extends BaseTable {
private static final long serialVersionUID = 45L;
private int rolloverRowIndex = -1;
public MovieSearchResultTable(TableModel tableModel) {
super(tableModel);
LibraryLogger.initMessage(getClass().getSimpleName());
}
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component component = super.prepareRenderer(renderer, row, column);
Color foreground = getForeground();
Color background = getBackground();
if (isRowSelected(row)) {
foreground = getSelectionForeground();
background = getSelectionBackground();
}
else if (row == rolloverRowIndex) {
foreground = getSelectionForeground();
background = ColorHelper.brighter(getSelectionBackground(), 40);
}
else if (row % 2 == 0) {
background = ColorHelper.brighter(getParent().getBackground(), 20);
}
component.setForeground(foreground);
component.setBackground(background);
return component;
}
private class RolloverListener extends MouseInputAdapter {
public void mouseExited(MouseEvent e) {
rolloverRowIndex = -1;
repaint();
}
public void mouseMoved(MouseEvent e) {
int row = rowAtPoint(e.getPoint());
if (row != rolloverRowIndex) {
rolloverRowIndex = row;
repaint();
}
}
}
#Override
public void initialize() {
setFillsViewportHeight(true);
setAutoResizeMode(AUTO_RESIZE_OFF);
TableColumnModel tableColumnModel = getColumnModel();
for(ComponentConstant.ColumnName columnName : ComponentConstant.Column.MOVIE_SEARCH_RESULT_TABLE) {
int order = columnName.getOrder();
TableColumn tableColumn = tableColumnModel.getColumn(order);
if(order == 0) {
continue;
}
tableColumn.setCellRenderer(RendererFactory.getMovieSearchResultTableCellRenderer());
}
RolloverListener listener = new RolloverListener();
addMouseMotionListener(listener);
addMouseListener(listener);
}
#Override
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().getWidth() < getParent().getWidth();
}
}
Thanks.