Updating/Calling JTable rendering when a value is changed MANUALLY/DYNAMICALLY - java

so i want my JTable to render everytime a value in a variable is changed however this is not taking place, the table is only getting rendered either when I click on it, or move it out of view then back in. Any suggestions? I am using a custom TableCellRender as posted below.
import java.awt.Color;
import java.awt.Component;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.TableCellRenderer;
public class myRenderer extends JLabel implements TableCellRenderer {
private static final long serialVersionUID = 1L;
public myRenderer()
{
super.setOpaque(true);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
setHorizontalAlignment(SwingConstants.CENTER);
setText(value.toString());
Color myColor = new Color(255, 253, 117);
setBackground(myColor);
if(value == Integer.valueOf(-1))
{
value = null;
setText("");
return this;
}
for(int i = 0; i < 90; i++) {
if(value == Integer.valueOf(finalClass.done[i])) //this value changes during the program.
{
setBackground(Color.cyan);
}
}
return this;
}
}
I want my table to render everytime that the value in finalClass.done is changed in any other part of the program. any ideas? i tried the revalidate option, but got no results.
EDIT:
Here is a minimal version of finalClass, which when run together with the above mentioned renderer code, can reproduce the same error I'm facing.
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class finalClass {
JFrame frame = new JFrame();
static int[] done = new int[90];
Integer[][] slip = new Integer[9][5];
String colHeader[] = {"1","2","3","4","5"};
JTable table;
finalClass() {
for(int i = 0; i<90; i++)
done[i] = -1;
int cnt = 0;
for(int x = 0; x<9; x++ ) {
for(int y = 0; y <5; y++) {
slip[x][y] = cnt++;
}
}
DefaultTableModel tableModel = new DefaultTableModel(slip, colHeader) {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
};
table = new JTable(slip, colHeader);
table.setDefaultRenderer(Object.class, new myRenderer());
table.setModel(tableModel);
frame.add(table);
frame.setVisible(true);
frame.pack();
}
public static void main(String[] args) {
new finalClass();
try {
Thread.sleep(5000);
done[5] = 10;
} catch(Exception e) {
e.printStackTrace();
}
}
}
Thank you all in advance for bearing with me. I'm new here so it might take a little time for me to understand how things are done around here. sorry to waste your time and thanks for the help in advance.

The reason why the value shows only after you move the table or click on it, is that by doing so you force a repaint.
You can verify it by invoking frame.repaint() after done[5] = 10;
The following is a one-file MRE (copy paste the entire code into FinalClass.java and run):
import java.awt.Color;
import java.awt.Component;
import java.util.Arrays;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class FinalClass {
private final JFrame frame = new JFrame();
private final int[] done = new int[90]; //better avoid static
private final Integer[][] slip = new Integer[9][5];
private final String colHeader[] = {"1","2","3","4","5"};
private JTable table;
FinalClass() {
Arrays.fill(done, -1);
int cnt = 0;
for(int x = 0; x<9; x++ ) {
for(int y = 0; y <5; y++) {
slip[x][y] = cnt++;
}
}
DefaultTableModel tableModel = new DefaultTableModel(slip, colHeader) {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
};
table = new JTable(slip, colHeader);
table.setDefaultRenderer(Object.class, new MyRenderer());
table.setModel(tableModel);
frame.add(table);
frame.pack();
frame.setVisible(true);
}
private void refresh(){
frame.repaint();
}
void done(int index, int value){
done[index] = value;
refresh();
}
public static void main(String[] args) {
FinalClass f = new FinalClass();
try {
Thread.sleep(3000);
f.done(5, 10);
} catch(Exception e) { e.printStackTrace(); }
}
//follow java naming conventions
class MyRenderer extends JLabel implements TableCellRenderer {
private static final long serialVersionUID = 1L;
public MyRenderer()
{
super.setOpaque(true);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
setHorizontalAlignment(SwingConstants.CENTER);
setText(value.toString());
Color myColor = new Color(255, 253, 117);
setBackground(myColor);
if((int)value == -1)
{
value = null;
setText("");
return this;
}
for(int i = 0; i < 90; i++) {
if((int)value == done[i]) //this value changes during the program.
{
setBackground(Color.cyan);
}
}
return this;
}
}
}
Side notes:
1. If you want the table to respond automatically to change in the undelying data, you need to apply the change to its model as demonstrated in this answer to your previous question.
2.Modifying done from more than one thread needs to be synchronized.
3.It is recommended to follow Java Naming Conventions

Related

Change color of column in swing application

The program is about patient and their vital signs. In case the patient has abnormal vital signs(outside the range specified) i need to highlight that column in red. I have written an isNormal function mentioned below. But I am unsure how to highlight the column in red using this function. Can somebody please suggest a way to do this?
private void refresh()
{
int rowCount = vitalSignTable.getRowCount();
int i;
for (i= rowCount-1; i>=0; i--)
{
((DefaultTableModel)vitalSignTable.getModel()).removeRow(i);
}
for(vitalSigns vs :vitalSign)
{
Object[] vital_row = new Object[6];
vital_row [0] = vs.getRespRate();
vital_row [1] = vs.getHeartRate();
vital_row [2] =vs.getBloodPressure();
vital_row [3] = vs.getWeightPound();
vital_row[4] = vs.getWeightKilos();
vital_row[5]= vs.getTimeStamp();
((DefaultTableModel)vitalSignTable.getModel()).addRow(vital_row);
}
}
private String isNormal( vitalSigns vitalSign) {
String isNormal = "Normal";
int respirationRate = vitalSign.getRespRate();
int heartRate = vitalSign.getHeartRate();
double bloodPressure = vitalSign.getBloodPressure();
int weightPound = vitalSign.getWeightPound();
int weightKilos = vitalSign.getWeightKilos();
{
if ((respirationRate < 20 || respirationRate > 30) /*Respiration Rate*/
|| (heartRate < 80 || heartRate > 130) /*Heart Rate*/
|| (bloodPressure < 80 || bloodPressure > 110) /*Blood Pressure*/
|| (weightPound <80 || weightPound > 160)
|| (weightKilos <40 || weightKilos > 80))
{
isNormal = "Abnormal";
}
}
return isNormal;
}
Here is a little example, how to color cells in a table. To do it, you need to implement your own TableCellRenderer and set it for a column. For more information see the article about JTable.
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.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
* <code>TableRendererTest</code>.
*/
public class TableColumnsTest implements Runnable {
#Override
public void run() {
JFrame frm = new JFrame("Renderer test");
DefaultTableModel model = new DefaultTableModel(20, 20);
for (int i = 0; i < 20; i++) {
model.setValueAt("Test " + i, i, 3);
}
JTable table = new JTable(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JScrollPane scroller = new JScrollPane(table);
frm.add(scroller);
// set renderer for the column 3
table.getColumnModel().getColumn(3).setCellRenderer(
new ColoredRenderer(new DefaultTableCellRenderer(), Color.RED, Color.WHITE));
frm.pack();
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new TableColumnsTest());
}
private static class ColoredRenderer implements TableCellRenderer {
private final TableCellRenderer delegate;
private final Color differentBackground;
private final Color differentForeground;
public ColoredRenderer(TableCellRenderer delegate, Color differentBackground, Color differentForeground) {
this.delegate = delegate;
this.differentBackground = differentBackground;
this.differentForeground = differentForeground;
}
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component result = delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
// probably check for null values and whether the cell is selected (isSelected).
result.setBackground(differentBackground);
result.setForeground(differentForeground);
return result;
}
}
}

How to set color of particular cell in JTable using row and column indexes (TableCellRenderer)

I created the following TableCellRenderer to set colors of particular cells in JTable. The problem is that it sets the color of the whole column. How do I define the row?
package run;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
public class test4 {
/**
* #param args
*/
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
gtest t = new gtest("");
t.pack();
t.setVisible(true);
t.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
t.setLocationRelativeTo(null);
}
}
class gtest extends JFrame
{
private static JTable table;
private int index;
public gtest(String title)
{
Object cols[] = {"A","B"};
double data[][] = {{2,10},{5,20},{20,11}};
table = new JTable(3,2);
for (int i = 0; i< data.length; i++)
{
for (int j=1; j<cols.length; i++)
{
double val = data[i][j] + 5*data[i][j]-1;
table.getColumnModel().getColumn(j).setCellRenderer(new ColorRenderer());
// here I want to put a Thread.sleep or something similar to
// visualize the filling out of a table
}
}
add(table);
}
}
class ColorRenderer extends JLabel implements TableCellRenderer {
/**
*
*/
private static final long serialVersionUID = 1L;
public ColorRenderer() {
setOpaque(true);
}
public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
setText(value.toString());
setFont(new Font("SansSerif", Font.PLAIN, 10));
setBackground(Color.lightGray);
return this;
}
}
TableCellRenderer set to whole column, to change just some rows, you need to implement validation of row numbers inside getTableCellRendererComponent() method.
For example chage color of rowIndex = 1:
setBackground(row == 1 ? Color.lightGray : table.getBackground());
Read doc for TableCellRenderer.

How to implement checkbox list java

Probably a noob question, but im new to java. I have a need for a checkbox list which I found is not supported in swing, but I found this custom control here
http://www.devx.com/tips/Tip/5342
So I created a class file named CheckBoxList, and copied the code from the link into it:
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class CheckBoxList extends JList
{
protected static Border noFocusBorder =
new EmptyBorder(1, 1, 1, 1);
public CheckBoxList()
{
setCellRenderer(new CellRenderer());
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
int index = locationToIndex(e.getPoint());
if (index != -1) {
JCheckBox checkbox = (JCheckBox)
getModel().getElementAt(index);
checkbox.setSelected(
!checkbox.isSelected());
repaint();
}
}
}
);
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
protected class CellRenderer implements ListCellRenderer
{
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus)
{
JCheckBox checkbox = (JCheckBox) value;
checkbox.setBackground(isSelected ?
getSelectionBackground() : getBackground());
checkbox.setForeground(isSelected ?
getSelectionForeground() : getForeground());
checkbox.setEnabled(isEnabled());
checkbox.setFont(getFont());
checkbox.setFocusPainted(false);
checkbox.setBorderPainted(true);
checkbox.setBorder(isSelected ?
UIManager.getBorder(
"List.focusCellHighlightBorder") : noFocusBorder);
return checkbox;
}
}
}
The problem is I don't know how to implement it in my GUI file. I tried a lot of code, but they never showed an example. Just
To use the class, simply instantiate it, then pass it an array of
JCheckBox objects (or subclasses of JCheckBox objects) by calling
setListData
So does that mean that I will not see the control in the Graphical Design view? My client wants to be able to edit it himself and add stuff so I want it to be easy and graphical if possible. If someone could show an example of instantiating it or give a good hint I would appreciate it. Thanks!
Can you just tell me how?
Use a one column JTable and an appropriate renderer and editor. Based on this example, the code below relies on the default renderer for a data value of type Boolean.Class. A more general example is cited here.
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
/** #see https://stackoverflow.com/a/13919878/230513 */
public class CheckTable {
private static final CheckModel model = new CheckModel(5000);
private static final JTable table = new JTable(model) {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(150, 300);
}
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
JCheckBox jcb = (JCheckBox) super.prepareRenderer(renderer, row, column);
jcb.setHorizontalTextPosition(JCheckBox.LEADING);
jcb.setText(String.valueOf(row));
return jcb;
}
};
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame("CheckTable");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridLayout(1, 0));
f.add(new JScrollPane(table));
f.add(new DisplayPanel(model));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
private static class DisplayPanel extends JPanel {
private DefaultListModel dlm = new DefaultListModel();
private JList list = new JList(dlm);
public DisplayPanel(final CheckModel model) {
super(new GridLayout());
this.setBorder(BorderFactory.createTitledBorder("Checked"));
this.add(new JScrollPane(list));
model.addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent e) {
dlm.removeAllElements();
for (Integer integer : model.checked) {
dlm.addElement(integer);
}
}
});
}
}
private static class CheckModel extends AbstractTableModel {
private final int rows;
private List<Boolean> rowList;
private Set<Integer> checked = new TreeSet<Integer>();
public CheckModel(int rows) {
this.rows = rows;
rowList = new ArrayList<Boolean>(rows);
for (int i = 0; i < rows; i++) {
rowList.add(Boolean.FALSE);
}
}
#Override
public int getRowCount() {
return rows;
}
#Override
public int getColumnCount() {
return 1;
}
#Override
public String getColumnName(int col) {
return "Column " + col;
}
#Override
public Object getValueAt(int row, int col) {
return rowList.get(row);
}
#Override
public void setValueAt(Object aValue, int row, int col) {
boolean b = (Boolean) aValue;
rowList.set(row, b);
if (b) {
checked.add(row);
} else {
checked.remove(row);
}
fireTableRowsUpdated(row, row);
}
#Override
public Class<?> getColumnClass(int col) {
return getValueAt(0, col).getClass();
}
#Override
public boolean isCellEditable(int row, int col) {
return true;
}
}
}
The code is expecting a list of JCheckBox objects - so this works
CheckBoxList cbList = new CheckBoxList(); // the class you have
JCheckBox check1 = new JCheckBox("One");
JCheckBox check2 = new JCheckBox("two");
JCheckBox[] myList = { check1, check2}; list of checkbox object
cbList.setListData(myList); // set the list data for the object
Small Swing program using your class below
util;
import javax.swing.*;
public class HelloWorldSwing {
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CheckBoxList cbList = new CheckBoxList();
JCheckBox check1 = new JCheckBox("One");
JCheckBox check2 = new JCheckBox("two");
JCheckBox[] myList = { check1, check2};
cbList.setListData(myList);
frame.getContentPane().add(cbList);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

Set row height depend on JTextArea height

I have a problem and really don't know how to solve it.
I used some solutions from this forum but they don't work.
This is the piece of code:
package own_components.custom_components;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import own_components.localizable_components.LocalizableComponent;
import localization.GUILocalizationTags;
import localization.LocalizationManager;
public class OutputJTable extends JTable implements CustomComponent
{
private CustomTableModel dataModel = new CustomTableModel();
private List<String[]> data = new ArrayList<String[]>();
private final int COLUMNS_AMOUNT = 3;
private final int _1ST_COL_WIDTH = 25;
private final int _2ST_COL_WIDTH = 45;
private final int _3ND_COL_WIDTH = 505;
public OutputJTable()
{
setModel(dataModel);
setTableProperties();
dataModel.addTableModelListener(new TableModelListener(){
#Override
public void tableChanged(TableModelEvent paramTableModelEvent)
{
fitRowsHeight();
}
});
}
private void setTableProperties()
{
//some properties of table
}
public void setResultOutput(List<String[]> result)
{
data = new ArrayList<String[]>();
data.add(new String[] { "l", "code", "222222222222222222222222222 22ddddddddddddddddddddddddddd22222222222222222222222222222222" });
data.add(new String[] { "l", "code", "sssssssssssssssssssssssssssssss sssssssssssssssssssssssssssssssssssssssssssssssssss222222222" });
dataModel.fireTableDataChanged();
}
private void fitRowsHeight()
{
for (int row = 0; row < getRowCount(); row++)
{
int rowHeight = getRowHeight();
Component comp = prepareRenderer(getCellRenderer(row, 2), row, 2);
rowHeight = Math.max(rowHeight, comp.getSize().height);
setRowHeight(row, rowHeight);
}
}
public int getSelectedRow()
{
return selectedRow;
}
private class CustomTableModel extends AbstractTableModel implements LocalizableComponent
{
private static final long serialVersionUID = -992340559233338699L;
private String[] columnsNames = { "a", "b", "c" };
#Override
public String getColumnName(int paramInt)
{
return columnsNames[paramInt];
}
#Override
public boolean isCellEditable(int paramInt1, int paramInt2)
{
return false;
}
#Override
public int getColumnCount()
{
return COLUMNS_AMOUNT;
}
#Override
public int getRowCount()
{
return data.size();
}
#Override
public String getValueAt(int arg0, int arg1)
{
return data.get(arg0)[arg1];
}
#Override
public void useTranslatedText(String tag)
{
columnsNames[1] = tag;
getColumnModel().getColumn(2).setHeaderValue(tag);
repaint();
}
#Override
public void registerToLocalization(LocalizationManager lm, String key)
{
lm.registerToTranslationList(this, GUILocalizationTags.OUT_TAB_DESCRIPTION);
}
}
private class CustomTableRenderer extends DefaultTableCellRenderer
{
JTextArea cellTemp = new JTextArea();
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
cellTemp = new JTextArea(data.get(row)[column]);
cellTemp.setLineWrap(true);
return cellTemp;
}
}
}
This is little bit long but rather simple: my table uses custom cell renderer which contains JTextArea. I use JTA because I need Strings wrapping. After put such JTextAreas I expect to set row heights to highest JTA in a row.
And here is the problem. In code above I expect to receive JTA.height but I still receive "0". The same situation with JTA.getRows().
I really don't understand why. Can anybody explain me what is wrong with this code?
This is working JTable with wrapped strings.
(I used solutions introduced by mKorbel in this thread How to make a JTable column to contain not JTextFields, but JTextAreas)
package own_components.custom_components;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.text.View;
public class OutputJTable extends JTable
{
private static final long serialVersionUID = 1L;
private List<String[]> data = new ArrayList<String[]>();
private CustomTableModel dataModel = new CustomTableModel();
private final int COLUMNS_AMOUNT = 3;
private final int _1ST_COL_WIDTH = 25;
private final int _2ST_COL_WIDTH = 45;
private final int _3ND_COL_WIDTH = 505;
private int selectedRow = -1;
public OutputJTable()
{
setModel(dataModel);
setDefaultRenderer(Object.class, new CustomTableRenderer());
setTableProperties();
}
/**
* Sets basic table properties.
*/
private void setTableProperties()
{
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
getColumnModel().getColumn(0).setMaxWidth(_1ST_COL_WIDTH);
getColumnModel().getColumn(0).setMinWidth(_1ST_COL_WIDTH);
getColumnModel().getColumn(1).setMaxWidth(_2ST_COL_WIDTH);
getColumnModel().getColumn(1).setMinWidth(_2ST_COL_WIDTH);
getColumnModel().getColumn(2).setMaxWidth(_3ND_COL_WIDTH);
getColumnModel().getColumn(2).setMinWidth(_3ND_COL_WIDTH);
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
setIntercellSpacing(new Dimension(0, 0));
setShowGrid(false);
}
/**
* Receives data used to modified data showned in table.
* This should be only access point to add data used by data model (which is used by jtable).
*
* #param result
*/
public void setResultOutput(List<String[]> result)
{
data = new ArrayList<String[]>();
data = result;
dataModel.fireTableDataChanged();
}
#Override
public void doLayout()
{
super.doLayout();
for (int row = 0; row < getRowCount(); row++)
{
JTextArea a = (JTextArea) prepareRenderer(getDefaultRenderer(Object.class), row, 2);
int rowHeight = (int) a.getUI().getRootView(a).getView(0).getPreferredSpan(View.Y_AXIS) + getIntercellSpacing().height;
setRowHeight(row, rowHeight);
}
}
/**
* Returns which row is selected. Main purpose of this method is provide data to PrintManager what should be printed.
*/
public int getSelectedRow()
{
return selectedRow;
}
#Override
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend)
{
if (rowIndex != selectedRow)
{
selectedRow = rowIndex;
}
else
{
selectedRow = -1;
}
super.changeSelection(rowIndex, columnIndex, true, false);
}
/**
* This is model used to fill this table with data.
*/
private class CustomTableModel extends DefaultTableModel implements LocalizableComponent
{
private static final long serialVersionUID = -992340559233338699L;
private String[] columnsNames = { "a", "b", "c" };
#Override
public String getColumnName(int paramInt)
{
return columnsNames[paramInt];
}
#Override
public boolean isCellEditable(int paramInt1, int paramInt2)
{
return false;
}
#Override
public int getColumnCount()
{
return COLUMNS_AMOUNT;
}
#Override
public int getRowCount()
{
return data.size();
}
#Override
public String getValueAt(int arg0, int arg1)
{
return data.get(arg0)[arg1];
}
}
/**
* This class is used to render single cell.
*/
private class CustomTableRenderer extends JTextArea implements TableCellRenderer
{
private final Color SELECTION_BORDER = new Color(200, 200, 200);
private final Color ODD_BACKGR_COLOR = new Color(240, 240, 240);
private final Color EVEN_BACKGR_COLOR = Color.WHITE;
CustomTableRenderer()
{
setLineWrap(true);
setWrapStyleWord(true);
setEditable(false);
setFont(getFont());
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
setText((String) value);
setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
if (isSelected)
{
setBackground(SELECTION_BORDER);
}
else if (row % 2 != 0)
{
setBackground(ODD_BACKGR_COLOR);
}
else
{
setBackground(EVEN_BACKGR_COLOR);
}
return this;
}
}
}
Remarks:
formating of row height is based on third column, if you want to take under consideration all columns, you have to use additional "for" loop in doLayout(),
'dataModel' of this JTable is based on the List 'model',
setResultOutput() expect String[3]
Thanks for everybodys help.
Regards.

row selection not moving with row moves in JTable

I have following code:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import javax.swing.table.DefaultTableModel;
public class NewClass1 extends JFrame {
private JTable table;
private JScrollPane scrollPane;
private DefaultTableModel defaultTableModel;
public NewClass1() {
setLocationByPlatform(true);
setLayout(new BorderLayout());
setPreferredSize(new Dimension(600, 400));
setTitle("Table Issues");
setDefaultCloseOperation(EXIT_ON_CLOSE);
createTableModel();
table = new JTable(defaultTableModel);
scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane, BorderLayout.CENTER);
pack();
}
private void createTableModel() {
Vector cols = new Vector();
cols.add("A");
Vector rows = new Vector();
for (int i = 0; i < 50; i++) {
Vector row = new Vector();
row.add((i + 1) + "");
rows.add(row);
}
defaultTableModel = new DefaultTableModel(rows, cols) {
Class[] types = new Class[]{
String.class
};
#Override
public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(new NimbusLookAndFeel());
} catch (Exception e) {
}
final NewClass1 nc = new NewClass1();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
nc.setVisible(true);
}
});
while (true) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int row = (int) (Math.random() * 50);
int move = (int) (Math.random() * 50);
nc.defaultTableModel.moveRow(row, row, move);
}
});
try{
Thread.sleep(1000);
}catch(Exception e){
}
}
}
}
Please run the above code and select row.
My problem is with row movement, row selection is not moving. It is staying at fixed position. Suppose I selected row with column value 25, selected row must be of column value 25 after row movements.
Please help me on this.
My real problem is, user will select row and clicks menu to perform action, meanwhile other threads may have moved rows, and performed action will be on other row than actual one.
The easiest way is to remember the selected row somewhere outside of the ListSelectionModel and adjust the selection whenever the TableModel changes. For example you could do this:
public class NewClass1 extends JFrame {
private JTable table;
private DefaultTableModel defaultTableModel;
private JScrollPane scrollPane;
private class SelectionHelper implements ListSelectionListener, TableModelListener {
private Object selectedRow;
#Override
public void valueChanged(ListSelectionEvent event) {
if (!event.getValueIsAdjusting()) return;
int selectedIndex = table.getSelectedRow();
if (selectedIndex >= 0) {
selectedRow = defaultTableModel.getDataVector().get(selectedIndex);
} else {
selectedRow = null;
}
}
#Override
public void tableChanged(TableModelEvent event) {
if (selectedRow == null) return;
int selectedIndex = defaultTableModel.getDataVector().indexOf(selectedRow);
table.getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex);
}
}
public NewClass1() {
// ...
createTableModel();
table = new JTable(defaultTableModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
SelectionHelper helper = new SelectionHelper();
table.getModel().addTableModelListener(helper);
table.getSelectionModel().addListSelectionListener(helper);
// ...
}
// ...
}
Note however, that you should adjust this code for production use, for example in regards to thread safety or portability (using the table and defaultTableModel attributes in the inner class is bad style).

Categories