Java JTable -- Custom Row Sorter - java

I have a JTable that loads data from a database and then generates a summary row at the bottom of the table. I want the user to be able to sort the table, but I'd like the summary row to always remain at the bottom of the table.
I've been trying to create a custom TableRowSorter, but I'm having some trouble figuring it out and getting it to do what I want.
Anyone know how to do this?
Thanks

You need a class which holds whether the value is a summary or not.
Something like this
public class SummarizedValue {
public Integer value;
public boolean summarized;
public String toString() {
return null == value? "" : value.toString();
}
}
public class SummaryComparator implements Comparator<SummarizedValue> {
public int compare(SummarizedValue v1, SummarizedValue v2) {
if (v1.summarized) return 1;
if (v2.summarized) return -1;
return v1.value.compareTo(v2.value);
}
}
public class SummaryBackComparator implements Comparator<SummarizedValue> {
public int compare(SummarizedValue v1, SummarizedValue v2) {
if (v1.summarized) return 1;
if (v2.summarized) return -1;
return v2.value.compareTo(v1.value);
}
}
You need to display the objects of class SummarizedValue in your column and your row sorter should return SummaryComparator. Also your need to override toggle behaviour in RowSorter to use SummaryBackComparator.

Related

JComboBox populetd with my object

I have a class called persone (peoples), it's just an arraylist of object persona (person).
I want to use this the object persone for populate a JComboBox.
I've read many post, and I've understood that I've to use DefaultComboBoxModel(E[] items), but, of course, I've missed something. I made some mistake. Can I have an example ? And how to set or get the selected item?
This is my class:
public class Persone {
private ArrayList<Persona> el = new ArrayList<Persona>();
public Persone() {
}
public ArrayList<Persona> getEl() {
return el;
}
public void setEl(ArrayList<Persona> el) {
this.el = el;
}
public boolean delPersonaFromPersone(Persona persona) {
return this.el.remove(persona);
}
public boolean addPersonaToPersone(Persona persona) {
return this.el.add(persona);
}
public boolean substPersonaInPersone(Persona persona, Persona withPersona ) {
if ( !this.el.remove(persona))
return false;
return this.el.add(persona);
}
#Override
public String toString() {
return "Persone [el=" + el + "]";
}
}
You can't add an Object containing an ArrayList to a combo box.
Instead you need to add individual Persona object to the combo box.
Then you would need to provide a custom renderer to display the Persona object.
Check out Combo Box With Custom Renderer for more information and examples on how to do this.
I've found my mistake (some bad assignment).
For use in JComboBox, I've made a new array from ArrayList.
Here my code:
JComboBox<Persona> cbResponsabile = new JComboBox<Persona>();
Persona[] array = persone.getEl().toArray(new Persona[persone.getEl().size()]);
cbResponsabile.setModel(new DefaultComboBoxModel(array));
contentPanel.add(cbResponsabile);
// .....
// assignment
// persona is an element of array
cbResponsabile.setSelectedItem(persona);

CheckBox in jTable?

I've added a checkbox to rows on my table, but unfortunately I'm unable to select/deselect them.
I'm using an own Table Model that I got on internet.
Table Model's code:
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
/**************/
public class ModeloTabela extends AbstractTableModel {
private ArrayList linhas = null;
private String [] colunas = null;
public ModeloTabela(ArrayList lin, String[] col){
setLinhas(lin);
setColunas(col);
}
public ArrayList getLinhas(){
return linhas;
}
public void setLinhas(ArrayList dados){
linhas = dados;
}
public String[] getColunas(){
return colunas;
}
public void setColunas(String [] nomes){
colunas = nomes;
}
public int getColumnCount(){
return colunas.length;
}
public int getRowCount(){
return linhas.size();
}
public String getColumnCount (int numCol){
return colunas[numCol];
}
public Object getValueAt(int numLin, int numCol){
Object[] linha = (Object[])getLinhas().get(numLin);
return linha[numCol];
}
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public boolean isCellEditable(int row, int col) {
return true;
}
}
And this Method will fill the Table:
public void PreencheTabela(String sql, JTable jt1, JTextField j1){
c.conexao();
ArrayList dados = new ArrayList();
String [] Colunas = new String[] {"STATUS", "ID", "FABRICANTE", "FORNECEDOR", "NOME", "CATEGORIA", "DATA DO CADASTRO", " CODIGO DE BARRAS", "QUANTIDADE"};
c.executaSQL(sql);
try {
c.rs.first();
do{
dados.add(new Object[]{c.rs.getInt("prod_id"),c.rs.getString("prod_fabricante"),c.rs.getString("prod_fornecedor"),c.rs.getString("prod_nome"),
c.rs.getString("prod_categoria"),c.rs.getDate("prod_datacadastro"),c.rs.getString("prod_codbarras"), c.rs.getInt("est_quantidade")});
j1.setBorder(BorderFactory.createLineBorder(Color.black));
}while(c.rs.next());
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Erro!\n"+ex.getMessage());
}
ModeloTabela modelo = new ModeloTabela(dados, Colunas);
jt1.setModel(modelo);
}
Which code can I use? Also, where do I put this code??
but unfortunately I'm unable to select/deselect them.
You didn't implement the setValueAt(...) method in your TableModel so the value can never be updated in the model.
I'm using an own Table Model that I got on internet.
Why are you using a custom TableModel? You can use the DefaultTableModel. It implements the setValueAt(...) method correctly. It also has an addRow(..) method that allows you to dynamically update the model.
Are you actually storing Boolean objects in the TableModel? I don't see you using getBoolean() to get the data from your ResultSet. The default renderers/editors for a check box will only be used when you have Boolean data in the column.
Also take a look at: Can't create column with checkboxes in JTable for a better implementation of the getColumnClass() method.
If you insist on using your custom TableModel, then take a look at the Swing tutorial link you were given in your last question. It shows and example of implementing the setValueAt() method.

GXT ValueProvider dynamic value

I need to dinamically add columns to GXT grid. I can do that, but problem occurs, when I want to input data for rows. Thing is, that not all rows have specific column. So what I want to achieve is to check if given row has specific column and return proper value.
Problem is, that ValueProvider for my column doesn't allow to use arguments in it's methods. So I can't pass column name to ValueProvider, so it could check if given column exists in specific row and return proper data.
Here is my column:
ColumnConfig<SomeClass, String> column = new ColumnConfig<SomeClass, String> (props.attributeValue(name), 150, name);
Here is my ValueProvider
ValueProvider<LimitDTO, String> attributeValue(String name);
And here is my implementation (simplified):
public String getAttributeValue(String name) {
if(this.attributes.get(name) == null) {
return "";
} else {
return this.attributes.get(name);
}
}
But I get build error:
Method public abstract com.sencha.gxt.core.client.ValueProvider<com.example.SomeClass, java.lang.String> attributeValue(java.lang.String s) must not have parameters
SOLUTION
Thanks to your answers I was able to do it. This is my implementation of ValueProvider in case someone will look for solution. It wasn't so hard after all :)
public class CustomValueProvider implements ValueProvider<SomeClass, String> {
public String column;
public CustomValueProvider(String column) {
this.column = column;
}
#Override
public String getValue(SomeClass object) {
if(object.getAttributes().get(column) == null) {
return "";
} else {
return object.getAttributes().get(column);
}
}
#Override
public void setValue(SomeClass object, String value) {
}
#Override
public String getPath() {
return column.getName();
}
}
And here is how I used it
LimitsValueProvider lvp = new LimitsValueProvider(name);
ColumnConfig<SomeClass, String> newColumn = new ColumnConfig<>(lvp, 150, name);
Thanks a lot!
I would suggest, do not use
props.attributeValue(name)
Instead, you can follow the post Dynamic charts in GXT 3 and you can create your own dynamic value providers (See the section value providers), which will take columnId (path) as input and peform the same functionality.
Remember ValueProvider is just an interface and using GWT.create you provides its default implementation.

Validating a set of values retrieved from database [duplicate]

I am validating the status of a record retrieved from the DB by defining an ENUM as below
public enum RecordStatusEnum {
CREATED("CREATED"),
INSERTED("INSERTED"),
FAILED("FAILED");
private String recordStatusValue;
RecordStatusEnum (String status) {
recordStatusValue= status;
}
public boolean isSuccess() {
return (this.equals(CREATED) || this.equals(INSERTED));
}
}
The method isSuccess() is being used to check the status of the retrieved record ( column status from employee)
if (!(employee.getStatus().isSuccess())) {
// return error
}
As per the new requirement, there are a set of conditions introduced say A,B and C; and for them there is a column in the Employee table 'condition'.
So I need to retrieve the status as well as the condition and see if it belongs to a set which has the combination of both.
For eg : isSuccess() should check if in the following:
CREATED and A
CREATED and B
INSERTED and C
This must be achieved such that it is easy for me to add a new combination say 'INSERTED and B' into the list easily.
What is the best approach for the above problem?
Note : in the actual business scenario there are a whole lot more statuses and checks (eg isFailed() canBeModified() etc) with many different combinations
And any method can be suggested even if it doesn't use ENUMS. I mentioned ENUMS, because I dont want to deviate much from the existing implementation
There are many possibilities, but you could do like this (I removed the String status, which doesn't add any value since it's equal to the name of the enum):
public enum RecordStatusEnum {
CREATED(Condition.A, Condition.B),
INSERTED(Condition.C),
FAILED();
private Set<Condition> successConditions;
RecordStatusEnum(Condition... successConditions) {
this.successConditions = EnumSet.copyOf(Arrays.asList(successConditions));
}
public boolean isSuccess(Condition c) {
return successConditions.contains(c);
}
}
EDIT:
Example with two sets of conditions:
public enum RecordStatusEnum {
CREATED(EnumSet.of(Condition.A, Condition.B),
EnumSet.of(Condition.C)),
INSERTED(EnumSet.of(Condition.C),
EnumSet.of(Condition.B),
FAILED(EnumSet.noneOf(Condition.class),
EnumSet.noneOf(Condition.class));
private Set<Condition> successConditions;
private Set<Condition> modificationConditions;
RecordStatusEnum(Set<Condition> successConditions,
Set<Condition> modificationConditions) {
this.successConditions = successConditions;
this.modificationConditions = modificationConditions;
}
public boolean isSuccess(Condition c) {
return successConditions.contains(c);
}
public boolean canBeModified(Condition c) {
return modificationConditions.contains(c);
}
}
You could also compare the ordinal values, like so:
public enum RecordStatusEnum {
CREATED,
INSERTED,
UPDATED,
NEW,
FAILED,
FAILED_NO_DB,
FAILED_CONSTRAINT_VIOLATION;
public boolean isPersisted(RecordStatusEnum status) {
return status.ordinal < NEW.ordinal;
}
public boolean isError(RecordStatusEnum status){
return status.ordinal >= FAILED.ordinal;
}
}

Automatic row numbering in javafx table

I have a sample code that we use to dynamic row numbers in Java Swing Table i.e JTable. I new to JavaFX and would like to the same in JavaFX. Is there is any way to set automatic row numbers in JavaFX Table
class LineNumberTable extends JTable {
private JTable mainTable;
public LineNumberTable(JTable table) {
super();
mainTable = table;
setAutoCreateColumnsFromModel(false);
setModel(mainTable.getModel());
setAutoscrolls(false);
addColumn(new TableColumn());
getColumnModel().getColumn(0).setCellRenderer(mainTable.getTableHeader().getDefaultRenderer());
getColumnModel().getColumn(0).setPreferredWidth(40);
setPreferredScrollableViewportSize(getPreferredSize());
}
#Override
public boolean isCellEditable(int row, int col) {
if (col == uneditableColumn) {
return false;
}
return bEdit;
}
#Override
public Object getValueAt(int row, int column) {
return Integer.valueOf(row + 1);
}
#Override
public int getRowHeight(int row) {
return mainTable.getRowHeight();
}
}
In JavaFX, you use TableColumns with CellFactories and CellValueFactories to populate your TableView.
The JavaFX tutorials have an article that might get you started.
In one approach I have used I convert the business objects to display into presentation objects and add all necessary properties (like in your case, the number) to them.
EDIT: In a second, cleaner approach, you could set your CellFactory to create a TableCell that shows its own index property in TableCell#updateItem(S, boolean):
public class NumberedCell extends TableCell{
protected void updateItem(Object object, boolean selected){
setText(String.valueOf(getIndex());
}
}

Categories

Resources