So I am creating a project which has three columns; one is a check box column the second one is string (words form a neo4j database) and the third for progress bars.
All the columns are displayed and work fine but the progress bar column is invisible as it seems. Here is some code:
//CONSTRUCTOR
public BiogramTableJSedit2Jan9()
{
//*************************************************
//* SETTING UP THE FORM *
//*************************************************
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(200,200,800,300);
setTitle("Netword Data Table");
getContentPane().setLayout(null);
//*************************************************
//********************************************
//CREATING TABLE BLOCK *
//********************************************
//ADD SCROLLPANE
JScrollPane scroll=new JScrollPane();
scroll.setBounds(70,80,600,200);
getContentPane().add(scroll);
//THE TABLE
final JTable table=new JTable();
scroll.setViewportView(table);
//THE MODEL OF THE TABLE
DefaultTableModel model=new DefaultTableModel()
{
//****************************************
//* SETTING TABLE COLUMNS BLOCK *
//****************************************
public Class<?> getColumnClass(int column)
{
switch(column)
{
case 0: // |This is the first column
return Boolean.class; // |First column is set to Boolean as it will contain check boxes
case 1: // |This is the second column
return String.class; // |Second column set to String as it will contain strings
case 2:
return JProgressBar.class; // |This is for the progress bar column (IN PROGRESS - NOT DISPLAYED YET...)
default:
return String.class; // |The table is set to String as default
}
}
};
//Create and run the query in the table
neoQuery= Q1();
resultVariable = session.run(neoQuery.get());
//ASSIGN THE MODEL TO TABLE
table.setModel(model);
model.addColumn("Select"); // |Column for check boxes
model.addColumn("Bigrams"); // |Column for Bigrams
table.getColumn("Status").setCellRenderer(new ProgressCellRender());
//**********************************************
ProgressWorker worker = new ProgressWorker(model); //HAVE AN ERROR HERE
worker.execute();
This is the progress renderer class:
//a table cell renderer that displays a JProgressBar
public class ProgressCellRender extends JProgressBar implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
int progress = 0;
if (value instanceof Float) {
progress = Math.round(((Float) value) * 100f);
} else if (value instanceof Integer) {
progress = (int) value;
}
setValue(progress);
return this;
}
}
Now you can see that I am using getColumn in order to display this column but when I run it you can see the first and second but not the progress bar column. I want it to look similar to this:
I also has a progress worker class that is not fully implemented.
private static class ProgressWorker extends SwingWorker<Void, Integer>
{ //Swing worker class for updating the progress bar
private BiogramTableJSedit2Jan9 model;
private final JProgressBar progress; //declaration for progress bar
public ProgressWorker(JProgressBar model)
{
this.progress = model;
}
#Override
protected Void doInBackground() throws Exception {
return null;
}
I would appreciate if anyone can explain to me why the thirst column is not being displayed. Thanks for any replies in advance.
Because your posted code was not self-contained I set up a minimal test together
with your already posted ProgressCellRender class.
The important bugfix is in method getColumnClass of the DefaultTableModel.
It needs to return Integer.class or Float.class because only those can be
handled by your ProgressCellRender.
And of course, the actual data in that column need to be Integer or Float.
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(Main::initGUI);
}
private static void initGUI() {
JFrame frame = new JFrame("TableModel JProgressBar Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scroll = new JScrollPane();
frame.getContentPane().add(scroll);
final JTable table = new JTable();
scroll.setViewportView(table);
DefaultTableModel model = new DefaultTableModel() {
public Class<?> getColumnClass(int column) {
switch (column) {
case 0:
return Boolean.class;
case 1:
return String.class;
case 2:
return Integer.class; // !!!!
default:
return String.class;
}
}
};
table.setModel(model);
model.addColumn("Active");
model.addColumn("Name");
model.addColumn("Progress");
table.getColumn("Progress").setCellRenderer(new ProgressCellRender());
model.addRow(new Object[] { true, "aaaa", 14 });
model.addRow(new Object[] { false, "bbbbbbbb", 0 });
model.addRow(new Object[] { true, "ccccc", 2 });
frame.pack();
frame.setVisible(true);
}
}
Then the JProgressBars are rendered correctly in the table:
In your ProgessCellRender you may want to add setStringPainted(true); to get the percentage also rendered as text.
Related
I am able to set the column's header but not able to set icon in all the rows of first column of JTable.
public class iconRenderer extends DefaultTableCellRenderer{
public Component getTableCellRendererComponent(JTable table,Object obj,boolean isSelected,boolean hasFocus,int row,int column){
imageicon i=(imageicon)obj;
if(obj==i)
setIcon(i.imageIcon);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setHorizontalAlignment(JLabel.CENTER);
return this;
}
}
public class imageicon{
ImageIcon imageIcon;
imageicon(ImageIcon icon){
imageIcon=icon;
}
}
and below lines in my BuildTable() method.
public void SetIcon(JTable table, int col_index, ImageIcon icon){
table.getTableHeader().getColumnModel().getColumn(col_index).setHeaderRenderer(new iconRenderer());
table.getColumnModel().getColumn(col_index).setHeaderValue(new imageicon(icon));
}
How can we set it for all rows of first columns? I have tried with for loop but didnt get yet for rows to iterate to set icon. Or is there any other way?
There is no need to create a custom render. JTable already supports an Icon renderer. YOu just need to tell the table to use this renderer. This is done by overriding the getColumnClass(...) method of the table model:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableIcon extends JPanel
{
public TableIcon()
{
Icon aboutIcon = new ImageIcon("about16.gif");
Icon addIcon = new ImageIcon("add16.gif");
Icon copyIcon = new ImageIcon("copy16.gif");
String[] columnNames = {"Picture", "Description"};
Object[][] data =
{
{aboutIcon, "About"},
{addIcon, "Add"},
{copyIcon, "Copy"},
};
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
public Class getColumnClass(int column)
{
switch (column)
{
case 0: return Icon.class;
default: return super.getColumnClass(column);
}
}
};
JTable table = new JTable( model );
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
add( scrollPane );
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Table Icon");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TableIcon());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
You are just using iconRenderer for the render of your header. Also set the Column's Cell Reneder to be an instance of iconRenderer as well. Call setCellRenderer on the column.
http://download.oracle.com/javase/6/docs/api/javax/swing/table/TableColumn.html#setCellRenderer(javax.swing.table.TableCellRenderer)
Side note: Java coding standards specify that class names should start with capital letters, so iconRenderer should be IconRenderer instead.
I know the post is a little old but it's never too late ...
I will post here how to insert an icon without using a DefaultTableCellRenderer class, I use this for when I will only show an icon on the screen in a simple way not very elaborate.
I do it in a simple way ... I always create some tablemodel creators in the classes that I inherit. I usually pass by parameter the list of titles and types of objects.
Method that creates the tablemodel in the upper class:
protected void createTableModel(String[] columns, Class[] types){
String[] vetStr = new String[columns.length];
boolean[] vetBoo = new boolean[columns.length];
Arrays.fill(vetStr, null);
Arrays.fill(vetBoo, false);
table.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] { vetStr },
columns
) {
boolean[] canEdit = vetBoo;
public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
table.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
}
Inherited class constructor:
"See that here I set the type as ImageIcon.class for the column"
.... constructor....
super("Balança");
String[] columns = {"#", "Nome", "Porta", "Padrão"};
Class[] types = {Long.class, String.class, String.class, ImageIcon.class};
**strong text**super.createTableModel(columns, types);
When I list the items on the tablemodel there I show the image.
list.forEach( obj -> {
tableModel.addRow(new Object[]{
obj.getId(),
obj.getName(),
obj.getPort(),
(obj.getId() == Global.standardScale)?
new ImageIcon(getClass().getResource("./br/com/valentin/img/accept.png")): ""
});
});
How can I prevent strings in a JTable and allow and show only numbers?
like for example I press "a" on my keyboard I won't not even that "a" will be displayed in the JTable cell. literally nothing should happen unless a user types in a number. so how can I prevent even not showing "a" ?
I had a similar issue some time ago and solved by validating with an KeyListener. This is a dirty way of doing it, but it works. The only weakness is if you're trying to edit a lot of cells quickly if you're a fast writer. Anyhow, here's the code that worked for me. I've added some commentary, but in short; we're overriding the normal validation and check with a TextField KeyListener if the given key is the one we allow in the TextField. If we allow the key, we enable TextField editing, if not, we turn it off to prevent the character being printed in the TextField. I hope this helps you.
UPDATE 1:
adding a celleditor on the TestField to prevent premature data insertion.
public class TableValidation extends JFrame
{
public static void main(String args[])
{
TableValidation x = new TableValidation();
x.setVisible(true);
}
JPanel topPanel;
JTable table = new JTable();
JScrollPane scrollPane;
String[] columnNames;
String[][] dataValues;
public TableValidation()
{
this.setTitle("JTable Cell Validation");
this.setDefaultCloseOperation (EXIT_ON_CLOSE);
this.setSize(300,112);
// make our panel to tin the table to
topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
this.getContentPane().add(topPanel);
// set some initial data for the table
columnNames = new String[] {"Anything" ,"Numbers only"};
dataValues = new String[][] { {"h4x0r","1337"} };
table.setRowHeight(50);
table.setModel( new CustomTableModel(dataValues, columnNames) );
TableColumn tableColumn = table.getColumnModel().getColumn(1); // apply our validation to the 2nd column
JTextField textfield = new JTextField(); // the textbox to which we test our validation
// setup our validation system. were passing the textfield as out celleditor source
tableColumn.setCellEditor(new MyCellEditor(textfield));
table.setCellSelectionEnabled(true);
scrollPane = new JScrollPane(table);
topPanel.add(scrollPane,BorderLayout.CENTER);
textfield.addKeyListener(new KeyAdapter()
{
public void keyTyped(KeyEvent e)
{
// check what keys can pass our test
if (textfield.isFocusOwner())
if (e.getKeyChar() != KeyEvent.VK_BACK_SPACE) // we allow backspace, obviously
if (!Character.isDigit(e.getKeyChar())) // if key is not a digit.. cancel editing
{
// when it detects an invalid input, set editable to false. this prevents the input to register
textfield.setEditable(false);
textfield.setBackground(Color.WHITE);
return;
}
textfield.setEditable(true);
}
});
}
}
class MyCellEditor extends AbstractCellEditor implements TableCellEditor
{
private static final long serialVersionUID = 1L;
private JTextField textField;
public MyCellEditor(JTextField textField)
{
this.textField=textField;
}
#Override
public boolean isCellEditable(EventObject e)
{
if (super.isCellEditable(e)) {
if (e instanceof MouseEvent) {
MouseEvent me = (MouseEvent) e;
return me.getClickCount() >= 2;
}
if (e instanceof KeyEvent) {
KeyEvent ke = (KeyEvent) e;
return ke.getKeyCode() == KeyEvent.VK_F2;
}
}
return false;
}
#Override
public Object getCellEditorValue()
{
return this.textField.getText();
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
this.textField.setFont(table.getFont());
this.textField.setText(value.toString());
return this.textField;
}
}
class CustomTableModel extends DefaultTableModel
{
CustomTableModel(String[][] data,String[] names)
{
super(data, names);
}
// we always pass true in our tablemodel so we can validate somewhere else
public boolean isCellEditable(int row,int cols)
{
return true;
}
}
I am able to set the column's header but not able to set icon in all the rows of first column of JTable.
public class iconRenderer extends DefaultTableCellRenderer{
public Component getTableCellRendererComponent(JTable table,Object obj,boolean isSelected,boolean hasFocus,int row,int column){
imageicon i=(imageicon)obj;
if(obj==i)
setIcon(i.imageIcon);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setHorizontalAlignment(JLabel.CENTER);
return this;
}
}
public class imageicon{
ImageIcon imageIcon;
imageicon(ImageIcon icon){
imageIcon=icon;
}
}
and below lines in my BuildTable() method.
public void SetIcon(JTable table, int col_index, ImageIcon icon){
table.getTableHeader().getColumnModel().getColumn(col_index).setHeaderRenderer(new iconRenderer());
table.getColumnModel().getColumn(col_index).setHeaderValue(new imageicon(icon));
}
How can we set it for all rows of first columns? I have tried with for loop but didnt get yet for rows to iterate to set icon. Or is there any other way?
There is no need to create a custom render. JTable already supports an Icon renderer. YOu just need to tell the table to use this renderer. This is done by overriding the getColumnClass(...) method of the table model:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableIcon extends JPanel
{
public TableIcon()
{
Icon aboutIcon = new ImageIcon("about16.gif");
Icon addIcon = new ImageIcon("add16.gif");
Icon copyIcon = new ImageIcon("copy16.gif");
String[] columnNames = {"Picture", "Description"};
Object[][] data =
{
{aboutIcon, "About"},
{addIcon, "Add"},
{copyIcon, "Copy"},
};
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
public Class getColumnClass(int column)
{
switch (column)
{
case 0: return Icon.class;
default: return super.getColumnClass(column);
}
}
};
JTable table = new JTable( model );
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
add( scrollPane );
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Table Icon");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TableIcon());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
You are just using iconRenderer for the render of your header. Also set the Column's Cell Reneder to be an instance of iconRenderer as well. Call setCellRenderer on the column.
http://download.oracle.com/javase/6/docs/api/javax/swing/table/TableColumn.html#setCellRenderer(javax.swing.table.TableCellRenderer)
Side note: Java coding standards specify that class names should start with capital letters, so iconRenderer should be IconRenderer instead.
I know the post is a little old but it's never too late ...
I will post here how to insert an icon without using a DefaultTableCellRenderer class, I use this for when I will only show an icon on the screen in a simple way not very elaborate.
I do it in a simple way ... I always create some tablemodel creators in the classes that I inherit. I usually pass by parameter the list of titles and types of objects.
Method that creates the tablemodel in the upper class:
protected void createTableModel(String[] columns, Class[] types){
String[] vetStr = new String[columns.length];
boolean[] vetBoo = new boolean[columns.length];
Arrays.fill(vetStr, null);
Arrays.fill(vetBoo, false);
table.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] { vetStr },
columns
) {
boolean[] canEdit = vetBoo;
public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
table.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
}
Inherited class constructor:
"See that here I set the type as ImageIcon.class for the column"
.... constructor....
super("Balança");
String[] columns = {"#", "Nome", "Porta", "Padrão"};
Class[] types = {Long.class, String.class, String.class, ImageIcon.class};
**strong text**super.createTableModel(columns, types);
When I list the items on the tablemodel there I show the image.
list.forEach( obj -> {
tableModel.addRow(new Object[]{
obj.getId(),
obj.getName(),
obj.getPort(),
(obj.getId() == Global.standardScale)?
new ImageIcon(getClass().getResource("./br/com/valentin/img/accept.png")): ""
});
});
How can I put a JCheckbox or a JButton on a specific row and column of a JTable?
Not sure about a button, but here is a working example to put a checkbox:
import javax.swing.*;
import javax.swing.table.*;
public class Test {
public static void main(String [] args) throws Exception {
DefaultTableModel model = new DefaultTableModel(null, new String [] {"CheckMe", "Value"}) {
public Class getColumnClass(int c) {
switch (c) {
case 0: return Boolean.class;
default: return String.class;
}
} };
JTable table = new JTable(model);
JFrame frame = new JFrame("CheckBox Test");
frame.add(table);
model.addRow(new Object [] {true, "This is true"});
model.addRow(new Object [] {false, "This is false"});
frame.pack(); frame.validate();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
As you can tell from khachik's answer support for a check box is provided by a table based on the column class of the column.
However, if you only want a check box on a specific row of a specific column then you need to override the getCellRenderer(...) and getCellEditor(...) methods to return the renderer/editor for the given cell. Something like:
public TableCellEditor getCellEditor(int row, int column)
{
int modelColumn = convertColumnIndexToModel( column );
if (modelColumn == 1 && row < 3)
return getDefaultEditor(Boolean.class);
else
return super.getCellEditor(row, column);
}
For that, you'll have to write a TableCellRenderer and a TableCellEditor.
You can derive from default swing implementations to make it easier.
In each class, you'll have to override the one method of these interfaces, and in it, check the passed row and column arguments; if both row and column match your criteria, then return a JCheckBox or a JButton, otherwise return the JComponent returned by the super implementation (when using default swing implementations of these interfaces).
Can someone point me in the right direction on how to add an image into Java Table cell.
JTable already provides a default renderer for icons. You just need to tell the table what data is stored in a given column so it can choose the appropriate renderer. This is done by overriding the getColumnClass(...) method:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableIcon extends JPanel
{
public TableIcon()
{
Icon aboutIcon = new ImageIcon("about16.gif");
Icon addIcon = new ImageIcon("add16.gif");
Icon copyIcon = new ImageIcon("copy16.gif");
String[] columnNames = {"Picture", "Description"};
Object[][] data =
{
{aboutIcon, "About"},
{addIcon, "Add"},
{copyIcon, "Copy"},
};
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
public Class getColumnClass(int column)
{
return getValueAt(0, column).getClass();
}
};
JTable table = new JTable( model );
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
add( scrollPane );
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Table Icon");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TableIcon());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Either create the imageicon up front:
ImageIcon icon = new ImageIcon("image.gif");
table.setValueAt(icon, row, column);
Or you can try overriding the renderer for your icon field:
static class IconRenderer extends DefaultTableCellRenderer {
public IconRenderer() { super(); }
public void setValue(Object value) {
if (value == null) {
setText("");
}
else
{
setIcon(value);
}
}
1- add label to jtable ( create class for this)
class LabelRendar implements TableCellRenderer{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
return (Component)value;
}
}
2- code jButton to add image
DefaultTableModel m = (DefaultTableModel) jTable1.getModel();
jTable1.getColumn("image").setCellRenderer(new LabelRendar()); // call class
JLabel lebl=new JLabel("hello");
lebl.setIcon(new javax.swing.ImageIcon(getClass().getResource("/main/bslogo120.png"))); // NOI18N
m.addRow(new Object[]{"", "","",lebl});
I created my own class that implements TableCellRenderer. I can extend this class from JLabel, but I have preferred to keep it independent and used JLabel 'label' as a class component.
public class GLabel implements TableCellRenderer{
//The JLabel that is used to display image
private final JLabel label = new JLabel();
/**
*
* #param text
* #param image
*/
public GLabel(String text, ImageIcon image) {
label.setText(text);
label.setIcon(image);
}
public GLabel(){}
public JLabel getLabel() {
return label;
}
/**
*
* #param table the JTable that is asking the renderer to draw; can be null
* #param value the value of the cell to be rendered.
* It is up to the specific renderer to interpret and draw the value.
* For example, if value is the string "true", it could be rendered as a string or it could be rendered as a check box that is checked.
* null is a valid value
* #param isSelected true if the cell is to be rendered with the selection highlighted; otherwise false
* #param hasFocus if true, render cell appropriately. For example, put a special border on the cell, if the cell can be edited, render in the color used to indicate editing
* #param row the row index of the cell being drawn. When drawing the header, the value of row is -1
* #param column the column index of the cell being drawn
* #return
*/
#Override
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
GLabel gLabel = (GLabel)value;
return (Component) gLabel.getLabel();
}
}
I created a new DefaultTableModel object. I overrides getColumnClass() method to pass appropriate Class at runtime.
private final DefaultTableModel tblmodel = new DefaultTableModel() {
/**
* This method is called by table cell renderer.
* The method returns class of the cell data. This helps the renderer to display icons and
* other graphics in the table.
*/
#Override
public Class getColumnClass(int column)
{
for(int i = 0; i < tblmodel.getRowCount(); i++)
{
//The first valid value of a cell of given column is retrieved.
if(getValueAt(i,column) != null)
{
return getValueAt(i, column).getClass();
}
}
//if no valid value is found, default renderer is returned.
return super.getColumnClass(column);
}
};
I created JTable object using DefaultTableModel I created.
JTable jtable = new JTable(tblmodel);
I set default renderer for GLabel class
jtable.setDefaultRenderer(GLabel.class, new GLabel());
I created new GLabel object.
GLabel glabel = new GLabel("testing", new ImageIcon("c://imagepath"));
Finally, I used addRow(Object[] rowData) method of TableModel to add GLabel to the JTable.