Modify Entire Column(s) in JTable - java

I have a JTable which is formed by importing data from a text file. It is a huge table with about 522 columns and thousands of rows. Many cells in this table are empty as well.
Now, I want to be able to apply some mathematical operations to the data available in certain columns. So right now, I can select multiple columns, but I dont know how to go about getting these values. I know I'll need an array of arrays where I can store the value from the table columns and then modify each value based on my algorithm.
Right now, to start it off simply, I just want to be able to print out the values in the select column (just one to keep it simple) but I cant do that, I get the value of a particular cell printed 2-4 times. My testing code is as follows:
For Selection entire columns, I am using this code:
public static void selectWholeColumn(final JTable table)
{
final JTableHeader header = table.getTableHeader();
header.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
int col = header.columnAtPoint(e.getPoint());
if(header.getCursor().getType() == Cursor.E_RESIZE_CURSOR)
{
e.consume();
}
else
{
table.setColumnSelectionAllowed(true);
table.setRowSelectionAllowed(false);
table.clearSelection();
table.setColumnSelectionInterval(col,col);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
}
}
});
}
In my GUI I have a button which when clicked fires a backend class and this method which takes in a JTable as a parameter is executed to print out the values of all rows in the selected Column:
public void filterData(final JTable table)
{
TableModel model = table.getModel();
table.setCellSelectionEnabled(true);
table.setColumnSelectionAllowed(true);
table.setRowSelectionAllowed(false);
ListSelectionModel cellSelectionModel = table.getSelectionModel();
cellSelectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
cellSelectionModel.addListSelectionListener(new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent e)
{
String selectedData = null;
int[] selectedRow = table.getSelectedRows();
int[] selectedColumns = table.getSelectedColumns();
for (int i = 0; i < selectedColumns.length; i++)
{
for (int j = 0; j < selectedRow.length; j++)
{
selectedData = (String) table.getValueAt(selectedRow[i], selectedColumns[j]);
}
}
System.out.println("Selected: " + selectedData);
}
});
Any suggestions as to how I could print or basically get the values of all rows in a selected Column or columns, so that I can modify the data in them at once?
Thank you!

Looping though the TableModel and using getValueAt() in a ListSelectionListener is a reasonable approach, although your listener will be invoked for each change. It's not clear where you're having trouble; you can
Concatenate the selected values using StringBuilder.
Accumulate the selected values in a List<String>.
Maintain the selection in your TableModel, as shown here using Set<Integer>.
Operate on the selection in the ItemHandler of a TableCellRenderer, as shown here.

Related

JTable change view but not change row selection after filter data

When data filtered table row was change view according to result but when I select row then table select always first row of column not filtered row but I want both things filter row and same row selection please solve me problem.
jTextField2.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent ke){
trs.setRowFilter(RowFilter.regexFilter("(?i)"+jTextField2.getText(),0));
}
});
tm = (TableModel)table.getModel();
trs = new TableRowSorter(tm);
table.setRowSorter(trs);
Thanks!
ANSWER IS FOR FORMATTED CODE PURPOSE
int modelRow = table.convertRowIndexToModel(table.getSelectedRow());
DefaultTableModel model = (DefaultTableModel) table.getModel();
name=model.getValueAt(index,0).toString();
sale.setVisible(true);
sale.pack();
sale.setLocationRelativeTo(null);
sale.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
sale.jTextField5.setText(name);
dispose();
so this code is not working for you in your mouse event? does the mouse event get triggered? could you edit your question and add more code (if possible all)?

Fixed cell size table with Java-FX

I've been fighting with this for some time, and finally figured I needed some help.
I am trying to create a table where each cell displays a particular color. This is dynamically created based on a user selected image.
I got it to work with a TilePane, but because of the size of the table, it was running extremely slow.
Currently, I am trying to make it work using a TableView. The TableView is being created, but not populated. My code to create the TableView, and my custom TableCell class, is below.
My main question is this: Is this the best way to go about this? If so, what am I doing wrong?
Thank you in advance for the awesome assistance I always see here.
Code to create TableView:
private ObservableList<ObservableList<Stitch>> stitchList;
private TableView<Stitch> pattern;
#Override
protected TableView<Stitch> call() throws Exception {
for (int i=0; i< stitchList.size(); i++) {
TableColumn<Stitch, Color> column = new TableColumn<>();
column.setCellValueFactory(new Callback<CellDataFeatures<Stitch, Color>, ObservableValue<Color>>() {
public ObservableValue<Color> call(CellDataFeatures<Stitch, Color> stitch) {
return stitch.getValue().getDisplayColorProperty();
}
});
column.setCellFactory(new Callback<TableColumn<Stitch, Color>, TableCell<Stitch, Color>>() {
#Override public TableCell<Stitch, Color> call(TableColumn<Stitch, Color> list) {
return new StitchCell();
}
});
//Set column sizes
column.setMinWidth(10);
column.setMaxWidth(10);
pattern.getColumns().add(column);
}
return pattern;
} // End Call
Code for custom cell class
public class StitchCell extends TableCell<Stitch, Color> {
#Override
protected void updateItem(Color color, boolean empty) {
super.updateItem(color, empty);
if (empty || color == null) {
this.setStyle("-fx-background-color: white");
} else {
this.setStyle("-fx-background-color: #" + Integer.toHexString(color.hashCode()));
}
}
}
When you create a TableView<S>, S is the type of the object displayed in each row of the table. The items property of the table, which is an ObservableList<S> contains the collection of items, each one of which is displayed in a table row.
If your data is in the form ObservableList<ObservableList<Stitch>> stitchList, then you need a TableView<ObservableList<Stitch>>. (In other words, S is ObservableList<Stitch>.) Each element of stitchList, which is an ObservableList<Stitch> represents a row in the table.
TableView is not designed with ObservableList<ObservableList> as the primary use case for representing data, so you need to do a little bit of work to get the cellValueFactory to work right. If you are certain that every row has the same number of items, you can perhaps minimize this a bit, but you need something like the following:
TableView<ObservableList<Stitch>> pattern = new TableView<>();
ObservableList<ObservableList<Stitch>> stitchList = ... ;
// Set items (i.e. rows) in table:
pattern.setItems(stitchList);
// iterate through all rows:
for (ObservableList<Stitch> row : pattern) {
// if this row contains more elements than columns we have already created,
// (must be true on first row, may be true on subsequent rows if data not rectangular)
// create a new column for each additional element
for (int i = pattern.getColumns().size(); i < row.size() ; i++) {
TableColumn<ObservableList<Stitch>, Color> column = new TableColumn<>();
final int columnIndex = i ;
column.setCellValueFactory(new Callback<CellDataFeatures<ObservableList<Stitch>, Color>, ObservableValue<Color>>() {
#Override
public ObservableValue<Stitch> call(CellDataFeatures<ObservableList<Stitch>, Stitch>> stitch) {
return stitch.getValue() // the row value, i.e. an ObservableList<Stitch>
.get(columnIndex) // the Stitch for this cell
.getDisplayColorProperty();
}
});
column.setCellValueFactory(new Callback<TableColumn<ObservableList<Stitch>, Color>, TableCell<ObservableList<Stitch>, Color>>() {
#Override
public TableCell<ObservableList<Stitch>, Color> call(TableColumn<ObservableList<Stitch>, Color> col) {
return new StitchCell();
}
});
column.setMinWidth(10);
column.setMaxWidth(10);
pattern.getColumns().add(column);
}
}
If you are using Java 8, you can replace the Callbacks with lambda expressions, and get rid of the ugliest parts of the code:
for (ObservableList<Stitch> row : pattern) {
// if this row contains more elements than columns we have already created,
// (must be true on first row, may be true on subsequent rows if data not rectangular)
// create a new column for each additional element
for (int i = pattern.getColumns().size(); i < row.size() ; i++) {
TableColumn<ObservableList<Stitch>, Color> column = new TableColumn<>();
final int columnIndex = i ;
column.setCellValueFactory( rowData ->
rowData.getValue() // the row value, i.e. an ObservableList<Stitch>
.get(columnIndex) // the Stitch for this cell
.getDisplayColorProperty() );
column.setCellValueFactory(col -> new StitchCell());
column.setMinWidth(10);
column.setMaxWidth(10);
pattern.getColumns().add(column);
}
}

How to check if table is made in Jtable and JFrame

Hi I want to check if table is made to add rows.If is not I want to show message :create table first. My problem : I do not know what I should type to if statement to check if is although one row made(which can suggest me that table was created).
I create table via NetBeans JFrame options this way:
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
/*
space is empty here because on start I do not create any rows.
user has to click button create or add rows.
*/
},
new String [] {
"Name", "Surname"
}
));
My if statment:
if(//do not know what type here because new Object [][] will not work){
JOptionPane.showMessageDialog(null, "Create table!");
}else //add row to table because exist {
Object[][] temp = new Object[data.length + 1][2];
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < 2; j++) {
temp[i][j] = data[i][j];
}
}
data = temp;
jTable1.setModel(new DefaultTableModel(data, columns));
}
Looks like you're using NetBeans GUI builder. If you go to the properties pane (the tab to the very right in Netbeans design view) with the jTable highlighted, you will see a property model
Click on the ... button to the right of the property, and a Dialog will pop up
Set the number of rows to 0, and the number of columns to how many columns you want, and set the column title and type and if you want it editable
Then in your actionPerformed, however you get the data for rows, add an array of that data to the model with model.addRow()
public void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// get row data, and put it into an array
Object[] row = {data1, data2, data3 ...};
DefaultTableModel model = (DefaultTableModel)jTable1.getModel();
model.addRow(row);
}
So whenever the button is pressed, a row will be added dynamically to your table. That's the easiest way to do it with GUI Builder
EDIT
If you want to check the number of rows then you check the rowCount
DefaultTableModel model = (DefaultTableModel)jTable1.getModel();
if (model.getRowCount() < 1) {
do something.
}

How can I delete the column and its underlying data without hiding it in jtable

I am having difficulties with deleting the actual data under a particular column which I am trying to delete.
I actually want to delete the column and its underlying data. I am able to insert new columns but when I delete
and insert again, the old columns which I previously deleted pop up again.
Any sort help is appreciated.
Thank you in advancce.
The data is stored in the TableModel.
Deleting the column from the ColumnModel will only prevent the view (the JTable) from showing it.
In order to remove it, you need to tell the TableModel to remove the column data as well.
Depending on you implementation, you could use JTable.setValueAt(value, row, column) or TableModel.setValueAt(value, row, column), which ever is more convenient.
This of course assumes you've implemented the setValueAt method
public void removeColumnAndData(JTable table, int vColIndex) {
MyTableModel model = (MyTableModel)table.getModel();
TableColumn col =table.getColumnModel().getColumn(vColIndex);
int columnModelIndex = col.getModelIndex();
Vector data = model.getDataVector();
Vector colIds = model.getColumnIdentifiers();
// Remove the column from the table
table.removeColumn(col);
// Remove the column header from the table model
colIds.removeElementAt(columnModelIndex);
// Remove the column data
for (int r=0; r<data.size(); r++) {
Vector row = (Vector)data.get(r);
row.removeElementAt(columnModelIndex);
}
model.setDataVector(data, colIds);
// Correct the model indices in the TableColumn objects
// by decrementing those indices that follow the deleted column
Enumeration<TableColumn> enum1 = table.getColumnModel().getColumns();
for (; enum1.hasMoreElements(); ) {
TableColumn c = (TableColumn)enum1.nextElement();
if (c.getModelIndex() >= columnModelIndex) {
c.setModelIndex(c.getModelIndex()-1);
}
}
model.fireTableStructureChanged();
}
/*MyDefaultTableModel class**/
class MyTableModel extends DefaultTableModel
{
String columns[];
int size;
public MyTableModel(String col[],int size)
{
super(col,size);
columns = col;
this.size=size;
}
public Vector getColumnIdentifiers()
{
return columnIdentifiers;
}
}

Invert the Selection in JTable

On clicking a button, I want the selected rows to be inverted (non-selected rows should be selected and selected rows should be non-selected).
Is there a build-in method in JTable to do it?
JTable doesn't seems to have a built-in way of doing this. So I implemented it with the following code. (Hope this is helpful for someone who is facing a similar issue.)
int[] selectedIndexs = jtable.getSelectedRows();
jtable.selectAll();
for (int i = 0; i < jtable.getRowCount(); i++) {
for (int selectedIndex : selectedIndexs) {
if (selectedIndex == i) {
jtable.removeRowSelectionInterval(i, i);
break;
}
}
}
To simplify Sudar's solution:
int[] selectedIndices = table.getSelectedRows();
table.selectAll();
for (int prevSel : selectedIndices) {
table.removeRowSelectionInterval(prevSel, prevSel);
}
JTable does not have that feature
No, You will have to implement a cutsom ListSelectionListener
A refinement to above is to update selection using the selection model object, not the table object. When you update the selection via the table, each update fires a selection change event and it takes few seconds to update a table with just a few hundred rows.
The fastest way for tables with more than few hundred rows is this
/**
* Invert selection in a JTable.
*
* #param table
*/
public static void invertSelection(JTable table) {
ListSelectionModel mdl = table.getSelectionModel();
int[] selected = table.getSelectedRows();
mdl.setValueIsAdjusting(true);
mdl.setSelectionInterval(0, table.getRowCount() - 1);
for (int i : selected) {
mdl.removeSelectionInterval(i, i);
}
mdl.setValueIsAdjusting(false);
}

Categories