Resequence table data after deletion of row in JTable - java

I have a JTable with 3 column of which first column is a button and second column is id. Now when user clicks on the button of specific row that row should be deleted. Up to this point everything wo$rks fine. But another requirement is re-sequencing the table data. I mean the column id should be re-sequence. For example:
First table data:
| id | another-column
b1 | 1 | abc
b2 | 2 | xyz
b3 | 3 | def
b4 | 4 | qwe
Now when user deletes second row which have id=2 then table data should be as follows:
| id | another-column
b1 | 1 | abc
b3 | 2 | def
b4 | 3 | qwe
Here b1/b2/b3/b4 are buttons for deletion of particular row.
How can I do this?

It is fairly easy to set this sequential id value inside the getValueAt(row, col) of your Abstract Table Model.
public Object getValueAt(int row, int col) {
if (col == 1)
return int (row + 1);
.....
}
Set the model again inside the action event of your buttons. The model will repaint the JTable correctly after a button has been pressed.

Related

FlowPane and Positioning

Is it possible to use a flowpane in the following way?
Have two components (img/label) aligned to the left and then multiple buttons on the right. Example:
+----------------------------------------------------------------+
| +------+ +----------+ +-----+ +-----+ |
| | Img | | Text... | | btn | | btn | |
| +------+ +----------+ +-----+ +-----+ |
+----------------------------------------------------------------+
I am adding the buttons for design / ease of use but am running into a brick wall. I would prefer not to have to change the 'holding panel'.
If not can it be simulated in css (float?)
Thanks
A FlowPanecan set margins. Here is an example that shows how to calculate the width of the margin so that the buttons are right aligned.
scene.widthProperty().addListener( ( observable, oldWidth, newWidth ) ->
{
final double spacerMargin = newWidth.doubleValue()
- scene.getRoot().getChildrenUnmodifiable().stream().mapToDouble( node -> node.getLayoutBounds().getWidth() ).sum();
FlowPane.clearConstraints( btn3 );
FlowPane.setMargin( btn3, new Insets( 0, 0, 0, spacerMargin ) );
} );
You basically subtract all the widths of the children of the FlowPane from the width of your scene.
Yes it is!
myFlow.add(griddy); // this gridlayout contains img and text
myFlowcontainer.add(Box.createRigidArea(new Dimension(5,0))); // Creating a space between.
The actual size will be defined by you
myFlow.add(griddy2); // The other element with the btn btn
That should seal the deal ;)

Vertical alignment of label with first row of adjacent control

How can I vertically align a label with a Combo in the first row of an adjacent Composite?
The label and the multi-row control are in a GridLayout with other controls, with left-alignment of the labels and the fields. The multi-row control is re-used elsewhere.
Ideally, the baselines of the text in the label and the Combo would be aligned. In practice, when the label and combo are siblings, vertically centering the two with SWT.CENTER is usually sufficient.
I can't just lower the label by a compile-time constant, because of differences in fonts and look-and-feels.
Ideas that have occurred to me include:
At runtime, while constructing the controls, ask Eclipse for the height of its combo widgets, somehow. Embed the label in a Composite and pad or align appropriately.
Put the label (possibly embedded in a Composite) in a StackLayout with a dummy Combo that's never displayed, to give the label cell the height of the first row in the sibling control. Center align the label within its parent.
Is there a simpler/cleaner approach?
I confirmed that the problem can be solved by the second approach I suggested in the question. If anyone has a better answer, please post.
This approach has these objects:
AbstractLabelWithHeightOfAnotherControl / custom StackLayout
<>-- Other control
Composite / GridLayout
<>-- Label / GridData( SWT.BEGINNING, SWT.CENTER, false, true )
The custom StackLayout has the width of the label, but the height of the other control.
This code provides an abstract class that supports the behavior for a variety of other controls.
public abstract class AbstractLabelWithHeightOfAnotherControl extends Composite {
private Label m_label;
private Control m_otherControl;
/** Constructor.
* #param parent
* #param style
*/
public AbstractLabelWithHeightOfAnotherControl(Composite parent, int style) {
super( parent, style );
StackLayout stackLayout = new MyStackLayout();
this.setLayout( stackLayout );
Composite layerLabel = new Composite( this, SWT.NONE );
GridLayout layerLabelLayout = new GridLayout( 1, false );
layerLabelLayout.marginWidth = 0;
layerLabelLayout.marginHeight = 0;
layerLabel.setLayout( layerLabelLayout );
m_label = new Label( layerLabel, SWT.NONE);
m_label.setLayoutData( new GridData( SWT.BEGINNING, SWT.CENTER, false, true ) );
m_otherControl = makeOtherControl( this );
stackLayout.topControl = layerLabel;
}
protected abstract Control makeOtherControl( #Nonnull Composite parent );
public Label getLabel() {
return m_label;
}
private final class MyStackLayout extends StackLayout {
MyStackLayout() {
this.marginHeight = 0;
this.marginWidth = 0;
}
#Override
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
int width = m_label.computeSize( wHint, hHint, flushCache ).x;
int height = m_otherControl.computeSize( wHint, hHint, flushCache ).y;
if (wHint != SWT.DEFAULT) width = wHint;
if (hHint != SWT.DEFAULT) height = hHint;
return new Point(width, height);
}
}
}
The implementing class can just provide a method like this:
#Override
protected Control makeOtherControl( #Nonnull Composite parent ) {
return new Combo( parent, SWT.NONE );
}
What about creating a component like this:
+-------------------------------+
| +---------------------------+ |
| | +------+ +-------------+ | |
| | |Label | |Combobox | | |
| | +------+ +-------------+ | |
| +---------------------------+ |
| | +------+ +-------------+ | |
| | |Dummy | |Combobox | | |
| | +------+ +-------------+ | |
| +---------------------------+ |
| | +------+ +-------------+ | |
| | |Dummy | |Combobox | | |
| | +------+ +-------------+ | |
| +---------------------------+ |
+-------------------------------+
Have it created by a method that takes the label text as input. The Dummies are empty labels if you want. If the method label text is null you can omit the creation of the labels altogether or make all empty. That way you can reuse the multi combobox component with or without label.

Hidden column but not read the correct value

I create a simple JTable with TableModel, and I hidden the first column.
I set at my JTable also the TableRowSorter
This is the code that I use to create a table
tableModelArticoliVendere = new MyTableModelDescrizioneArticoli();
tableArticoliVendere = new CustomTableArticoliDaVendereBar(tableModelArticoliVendere);
sorter = new TableRowSorter<MyTableModelDescrizioneArticoli>(tableModelArticoliVendere);
tableArticoliVendere.setRowSorter(sorter);
tableArticoliVendere.addMouseListener(new MyMouseAdapterArticoliDaVendere());
tableArticoliVendere.removeColumn(tableArticoliVendere.getColumnModel().getColumn(0));
If the user click on the one row of the table the mouse listenere are called.
This is the method:
public class MyMouseAdapterArticoliDaVendere extends MouseAdapter {
public void mouseClicked(MouseEvent me) {
JTable t = (JTable)me.getSource();
if (me.getClickCount() == 1) {
String codiceArticolo =((JTable)tableArticoliVendere).getModel().getValueAt(t.getSelectedRow(), 0).toString();
inserisciProdotto(codiceArticolo);
}
}
}
The problem is this:
If I see the complete table and I clik on the one of the row table, I read the codiceArticolo right. If I use the row filter, and I try to click on the first row I have an error.
I have the table with 3 row for example:
TABLE
column 0| column 1
------------------
valore1 | 1
valore2 | 2
valore3 | 3
If I use the filter I have this situation:
TABLE
column 0| column 1
------------------
valore2 | 2
valore3 | 3
if I try to click on the first row, the value of codiceArticolo is valore1 and not valore2.
If I not hidden the column 0, I don't have this error.
When you have sorting or filtering enabled in your table, the indexes of table rows and columns stop lining up with indexes of the model rows and columns. You can account for this using convertRowIndexToModel and convertColumnIndexToModel.
For instance, when you use t.getSelectedRow(), you can adjust like this:
int tableRowIndex = t.getSelectedRow();
int modelRowIndex = t.convertRowIndexToModel(tableRowIndex);
It will also help if you indicate in your code when you are using view indexes and when you are using model indexes.

SWT Table only first column selected

I currently have a populated SWT table with the following styles:
SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL
used SWT.FULL_SELECTION to get the whole line selected if clicked.
but using table.getSelection() only returns the first column.
I don't have any tableviewer or something else set.
where did I make a mistake?
edit:
example:
if (table.getSelectionCount() > 0) {
for (TableItem item : table.getSelection()) {
System.out.println(item);
}
}
this returns only the first column
Since you are only calling System.out.println() on the whole TableItem, Java will internally use TableItem#toString() to convert it to a String.
The resulting string however, will not contain all the data of the TableItem.
Instead, you'll need to iterate over the columns to get the data using TableItem#getText(int column):
for(int i = 0; i < table.getColumnCount(); i++)
System.out.println(item.getText(i));

Exclude column from sorting in JTable

I have a simple Swing JTable and a TableRowSorter made by me. However, I would exclude the first column from the sorting, as I want to keep it to show row numbers.
I can't see to find anything, except
sorter.setSortable(0, false);
Which makes the column not clickable, but still sortable when another column is clicked...
So quick question will be: how to keep a column from being sorter by a TableRowSorter?
Thank you!
So, with a JTable (ex below) sorting on column A would produce the following. However, you want the data to sort, but not the row numbers, correct?
|row| column A | |row| column A |
+---+-----------+ +---+-----------+
| 1 | blah blah | --> | 1 | blah blah |
| 2 | something | | 3 | more blah |
| 3 | more blah | | 2 | something |
I would approach this with a TableCellRenderer for column 0. The trick is to ignore the value passed and instead use the row parameter.
public class RowRenderer extends JLabel implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object color,
boolean isSelected, boolean hasFocus, int row, int column) {
setText(Integer.toString(row));
return this;
}
}
Note: if you are paginating your table (ie the model does not contain all of the rows; for example only rows 100-200) you will need to advise the cell renderer of the amount to add to row to obtain the row number to display.
A JTable is designed around displaying rows of data, not cells of data, so it isn't really possible to prevent an individual column from sorting, as you put it. Instead I would try modifying your TableModel to return the row index for the value for that column:
#Override public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) return rowIndex;
else {
// handle other columns
}
}
If that doesn't work you could also try modifying the table cell renderer to use the table row index instead.
If the row number isn't part of the data, then it should not be stored in the model.
Instead I would use a row header that displays a row number. Something like you would see in Excel. You can use the Row Number Table for this.

Categories

Resources