public class AdminControlPanel extends javax.swing.JFrame
I'm using the JFrame class...so it will automatically inherit the JFrame class...
But problem now is I want to disable the cell editing in the JTable...How to do it even I'm not inherit the AbstractTableModel???
If you want to use a custom table model:
//instance table model
DefaultTableModel tableModel = new DefaultTableModel() {
#Override
public boolean isCellEditable(int row, int column) {
return false; // or a condition at your choice with row and column
}
};
table.setModel(tableModel);
Or in a quick and dirty way:
table.setEnabled(false);
This second approach is inconsistent with some L&F (it looks grayed out).
Related
I am currently reading an excel sheet (.xls) and placing it in a JTable. The excel sheet consists of 3 columns. I am successfully able to read it. However, when reading the excel sheet, I want to add an extra fourth column in the JTable that includes JButtons (One button for each row). When JButton is clicked in a row, I want to take the content of the third column and perform some action.
I am currently using the code from here.
What is the best way to add JButtons in a JTable column?
You can create a class extending JButton. Then add property to that class.(field with getter and setter) when you adding data to the table, add JButton instance for each row using your custom JButton class and set value in the third column using setter method. So you can use that value in processing in the click event. Hope it helps :)
You can add your button this way.
class MyRenderer implements TableCellRenderer {
JButton button = new JButton();
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row, int column) {
button.setText(value.toString());
return button;
}
and to add action listener do this
class mybutttoneditor extends AbstractCellEditor implements TableCellEditor,
ActionListener {
JTable table;
JButton button = new JButton();
public mybutttoneditor(JTable table) {
this.table = table;
button.setFont(new Font("Serif", Font.BOLD, 14));
button.setForeground(Color.blue);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
final int row = table.getEditingRow();
String column3data=table.getValueAt(row, 2);
//do what you want with the data here
//hopefully this helps and if so accept the answer
}
//other abstract methods are here
}
}
DefaultTableModel md=(DefaultTableModel)mytable.getModel();
//do this while reading your excel sheet
Object row[]={"dataone","datatwo","data3","Open Button"};
md.addRow(row);
TableColumnModel colModel = mytable.getColumnModel();
colModel.getColumn(3).setCellRenderer(new MyRenderer());
colModel.getColumn(3).setCellEditor(new mybutttoneditor(mytable));
I'm attempting to create a JTable that looks like the mockup below:
The green corner is basically buffer-space for the red column and row headers. The cells don't need to be rendered in the colours pictured; however they need to be distinguishable from the rest of the 'white' cells in the table.
This table also is not editable or selectable; it's merely viewed by a user whilst it is updated.
I know this can be achieved using a DefaultTableModel with custom renders for rows 1,2 && cols 1,2 and adding +2 when setting and getting table values (accounting for the rows and columns that are being used as headers).
My questions are as follows:
Is there a cleaner way of doing this without polluting my table model with these static values used in headers?
I've read about extending table models but I'm not sure which class should I extend (DefaultTableModel, AbstractTableModel) and what methods I should override.
Input is limited to 20x20 so including the headers that's 22x22.
Also consider a JScrollPane containing a JPanel having GridLayout and containing 22x22 instances JLabel, or a suitable subclass. This scales easily to several thousand cells.
Addendum: If the need arises, CellRendererPane makes a good flyweight renderer, as suggested here.
If you go with JTable for rendering scalability,
This is no abuse; it is exactly how TableModel is intended to be used. TableModel models a rectangular matrix of whatever you decide. JTable is just an (efficiently rendered) view of that model.
I prefer AbstractTableModel, shown here, because Vector is rarely the desired data structure. Use whatever container makes your indexing most convenient. DefaultTableModel is handy and serves as a guide to extending AbstractTableModel. In particular, you'll need a setValueAt().
#Override
public void setValueAt(Object aValue, int row, int col) {
... // update your data structure
this.fireTableCellUpdated(row, col); // notify the view
}
longer comment, everything depends
1) if is possible for Columns
resize
reordering
2) if is possible for Columns
filtering
sorting
a. then you have look at two JTables, first JTable only with TableHeader, simple with removed rows and second full sized JTable with TableHeader and Columns and rows,
b. for interactions betweens two JTableHeader is there
TableColumnModelListener#columnMarginChanged(ChangeEvent e) and columnMoved(TableColumnModelEvent e)
c. everyting put to one JPanel inside JScrollPane
d. if you'll change numbers of rows or colums (or filtering / sorting) then you have to notified JPanel for rezize JTable#getPreferredScrollableViewportSize() + Dimension for ontop JTable only with TableHeader
very similair way as there (is everything that you needed)
(endless kudos for Rob)
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableFilterRow extends JFrame implements TableColumnModelListener {
private static final long serialVersionUID = 1L;
private JTable table;
private JPanel filterRow;
public TableFilterRow() {
table = new JTable(3, 5);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
table.getColumnModel().addColumnModelListener(this);
// Panel for text fields
filterRow = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
for (int i = 0; i < table.getColumnCount(); i++) {
filterRow.add(new JTextField(" Sum at - " + i));
}
columnMarginChanged(new ChangeEvent(table.getColumnModel()));
getContentPane().add(filterRow, BorderLayout.SOUTH);
}
// Implement TableColumnModelListener methods
// (Note: instead of implementing a listener you should be able to
// override the columnMarginChanged and columMoved methods of JTable)
#Override
public void columnMarginChanged(ChangeEvent e) {
TableColumnModel tcm = table.getColumnModel();
int columns = tcm.getColumnCount();
for (int i = 0; i < columns; i++) {
JTextField textField = (JTextField) filterRow.getComponent(i);
Dimension d = textField.getPreferredSize();
d.width = tcm.getColumn(i).getWidth();
textField.setPreferredSize(d);
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
filterRow.revalidate();
}
});
}
#Override
public void columnMoved(TableColumnModelEvent e) {
Component moved = filterRow.getComponent(e.getFromIndex());
filterRow.remove(e.getFromIndex());
filterRow.add(moved, e.getToIndex());
filterRow.validate();
}
#Override
public void columnAdded(TableColumnModelEvent e) {
}
#Override
public void columnRemoved(TableColumnModelEvent e) {
}
#Override
public void columnSelectionChanged(ListSelectionEvent e) {
}
public static void main(String[] args) {
JFrame frame = new TableFilterRow();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
3) otherwise look How to Use Raised Borders in the prepareRederer
4) this question has nothing to do with type of TableModel
I'm trying to add scrolling capabilities to a certain column in my JTable. I've implemented a custom TableCellRenderer component and I can see the scroll pane inside the table just fine, but I am not able to scroll it. I've tried implementing TableCellEditor as well and didn't have any luck.
public Component getTableCellEditorComponent(JTable arg0, Object arg1,
boolean arg2, int arg3, int arg4) {
return scrollPane;
}
Does anyone have any ideas how to make those cells which contain a scrollPane scrollable?
With TableCellRenderer it's not possible to add any scrolling behaviour, as it does not receive any events and only draws the component.
It is possible - however - to accomplish this by using a custom TableCellEditor with getTableCellEditor being:
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
JTextArea area = new JTextArea();
area.setLineWrap(true);
area.setText((String) value);
JScrollPane pane = new JScrollPane(area);
return pane;
}
Additionally, you have to control the editing behaviour of your CellEditor. To make the cell editable and scrollable always, isCellEditable should look like this:
public boolean isCellEditable(EventObject anEvent) {
return true;
}
Personally, I find this solution to be more of a hack than anything, though.
Also, this should only be for testing. You really do have to implement a better editing behaviour in my opinion.
A Renderer just paints the cells. I believe you need to implement a TableCellEditor to scroll.
As an alternative, consider placing a single scroll pane in a separate container and updating it's view in your selection listener.
I have a Jtable allow editing and inserting.
When editing a column, lets say "ID", I want to have a check, if the inserted record or the record after editing have duplicat "ID" column value with the other records. it is not allowed.
actually, to be specific, if someone is editing the ID column, when he hit the "Enter" or move the focus to another cell, perform a check, if the ID is duplicate, then disallow the edition.
how can I do this?
if someone is editing the ID column, when he hit the "Enter" or move the focus to another cell, perform a check, if the ID is duplicate, then disallow the edition.
Create a custom editor to validate the id before it is saved to the model. Here is a simple example to get your started:
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);
}
}
Extend DefaultTableModel and override the add and update methods checking for duplication and use this class for your JTable.
Extend AbstractTableModel and arrange for it to contain a Set, which precludes duplicate elements. As suggested by #camickr, you'll want a custom cell editor to communicate the results failed additions.
I'm trying to render an specific row of my jtable (it should have a different background color and it should have bold characters).
I found several questions regarding how to implement a custom TableCellRenderer (here and here) and the tutorial How to Use Tables and this one (Table Row Rendering).
I'm using a JInternalFrame to display the JTable. I tried to implement both solutions but neither getCellRenderer nor prepareRenderer are being called. When debugging, I can see my new jtable being created, but, my breakpoint inside the methods aren't called.
My code looks like:
this.add(createData(model));
private JComponent createData(ProfitLossTableModel model) {
JTable table = new JTable(model) {
public TableCellRenderer getCellRenderer(int row, int column) {
if ((row == 0) && (column == 0)) {
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setHorizontalAlignment(JLabel.RIGHT);
renderer.setBackground(Color.red);
return renderer;
} else {
return super.getCellRenderer(row, column);
}
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.changeSelection(0, 0, false, false);
table.setAutoCreateRowSorter(true);
return new JScrollPane(table);
}
As you can see, model is my implementation of a AbstractTableModel.
Of course that I'm missing something. I tried to call repaint() to see if something happened, but nothing occurred.
I also tried to put a JPane inside my JInternalFrame and them add the JScrollPane into it, but nothing occurred also.
Any help?
TIA,
Bob
As discussed in Concepts: Editors and Renderers, "the table invokes the table model's getColumnClass method, which gets the data type of the column's cells." You should verify that your implementation of AbstractTableModel returns a suitable value, as suggested in this example.
Addendum:
I'm trying to render a row, not a column.
Rob Camick's Table Row Rendering approach that overrides prepareRenderer() seems apropos.
tabbedPane.addTab("FirstRow", createFirstRow(model));
...
private JComponent createFirstRow(DefaultTableModel model) {
final Font font = new Font("Serif", Font.BOLD, 14);
JTable table = new JTable(model) {
public Component prepareRenderer(
TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if (!isRowSelected(row)) {
c.setBackground(row == 0 ? Color.yellow: getBackground());
c.setFont(row == 0 ? font : getFont());
}
return c;
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.changeSelection(1, 1, false, false);
return new JScrollPane(table);
}