this is my TableModel:
public class ScheduledRecordsTableModel extends AbstractTableModel {
private String[] headers = {"Interpret", "Titel"};
private List<ScheduledRecord> scheduledRecords;
public ScheduledRecordsTableModel(List<ScheduledRecord> recordsList) {
super();
this.scheduledRecords = recordsList;
}
#Override
public int getRowCount() {
return scheduledRecords.size();
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public String getColumnName(int column) {
return headers[column];
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
ScheduledRecord r = scheduledRecords.get(rowIndex);
switch (columnIndex) {
case 0:
return r.getActor();
case 1:
return r.getTitle();
default:
return null;
}
}
public void addRow(ScheduledRecord r) {
ScheduledRecord toAdd = null;
for (Iterator<ScheduledRecord> recordIterator = scheduledRecords.iterator(); recordIterator.hasNext(); ) {
ScheduledRecord record = recordIterator.next();
if (record.equals(r)) {
throw new IllegalArgumentException("Scheduled Record " + r.toString() + " already exists");
} else {
toAdd = record;
}
}
scheduledRecords.add(toAdd);
}
public void removeRow(ScheduledRecord r) {
scheduledRecords.remove(r);
fireTableDataChanged();
}
public ScheduledRecord getScheduledRecordFromIndex(int index) {
return scheduledRecords.get(index);
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
}
here is how i add new entries:
private void saveScheduledRecord() {
if (checkInputValues()) {
WebradioPlayer.addScheduledRecord(new ScheduledRecord(titleField.getText(), artistField.getText()));
this.dispose();
} else {
JOptionPane.showMessageDialog(this, "Please enter a valid artist/title", "Invalid input", JOptionPane.ERROR_MESSAGE);
throw new IllegalArgumentException("artist or title input did not match the specifications");
}
}
and here the addScheduledRecord method:
public static synchronized boolean addScheduledRecord(ScheduledRecord record) {
RecorderController.getInstance().addScheduledRecord(record);
Gui.getInstance().getRecorderTab().getScheduledRecordsWindow().getTable().getScheduledRecordsTableModel().addRow(record);
Gui.getInstance().getRecorderTab().getScheduledRecordsWindow().getTable().getScheduledRecordsTableModel().fireTableDataChanged();
databaseConnector.addScheduledRecord(record);
return true;
}
If i add an entry, the 'previous' one is added to the table, however if i close the table and open it again it is all correct. RecorderController just holds an own list for other purposes (this list is modified in another way)
Does anyone see my mistake here?
This should fix the addRow method (no need to iterate, while there is a contains method):
public void addRow(ScheduledRecord r) {
if (scheduledRecords.contains(r)) {
throw new IllegalArgumentException("Scheduled Record " + r.toString() + " already exists");
}
scheduledRecords.add(r);
}
Related
I'm making a numerical methods algorithms library, one of them is a false position method, where I return a double value. I want to show the iterations in a JTable, but I'm not sure what's the best way to approach this.
public static double falsePosition(String expression, double tolerance) {
double[] initialInterval = incrementalSearch(expression);
ArrayList<FalsePosition> rows = new ArrayList<>();
rows.add(new FalsePosition());
int i = 0;
rows.get(i).setA(initialInterval[0]);
rows.get(i).setB(initialInterval[1]);
do {
rows.get(i).setFa(evaluateExpression(expression, rows.get(i).getA()));
rows.get(i).setFb(evaluateExpression(expression, rows.get(i).getB()));
rows.get(i).setXi(nextSolucionReglaFalsa(
rows.get(i).getA(),
rows.get(i).getB(),
rows.get(i).getFa(),
rows.get(i).getFb()));
if (i == 0) {
rows.get(i).setError(0.0);
} else {
rows.get(i).setError(error(
rows.get(i).getXi(),
rows.get(i - 1).getXi()));
}
rows.get(i).setFxi(evaluateExpression(expression, rows.get(i).getXi()));
i++;
rows.add(new FalsePosition());
if ((rows.get(i - 1).getFa() * (rows.get(i - 1).getFxi()) < 0)) {
rows.get(i).setB(rows.get(i - 1).getXi());
rows.get(i).setA(rows.get(i - 1).getA());
} else {
rows.get(i).setA(rows.get(i - 1).getXi());
rows.get(i).setB(rows.get(i - 1).getB());
}
} while (i <= 1 || absolute(rows.get(i - 1).getError()) > tolerance);
return rows.get(i - 1).getXi();
}
An example of how the table would look:
(CHANGED) I have each "column" in a different ArrayList because I think that's more readable but I don't know if I should change it.
One of my ideas is to send the ArrayList of the rows to a setter method before the return statement, but I think that would mess with the method purpose, which is to just get a solution using the false position method. And then in the class where I want to create the table call the getter method to get the full ArrayList.
Here's my custom table model class
public class FalsePositionModel extends AbstractTableModel {
private String[] columnNames = {
"i",
"a",
"b",
"f(a)",
"f(b)",
"xi",
"error",
"f(xi)"
};
private List<FalsePosition> values;
public FalsePositionModel() {
values = new ArrayList<FalsePosition>();
}
public FalsePositionModel(List<FalsePosition> values) {
this.values = values;
}
#Override
public String getColumnName(int column) {
return columnNames[column];
}
#Override
public int getRowCount() {
return values.size();
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
FalsePosition falsePosition = getFalsePosition(rowIndex);
switch (columnIndex) {
case 0 -> {
return falsePosition.getA();
}
case 1 -> {
return falsePosition.getB();
}
case 2 -> {
return falsePosition.getFa();
}
case 3 -> {
return falsePosition.getFb();
}
case 4 -> {
return falsePosition.getXi();
}
case 5 -> {
return falsePosition.getError();
}
case 6 -> {
return falsePosition.getFxi();
}
default -> {
return null;
}
}
}
#Override
public void setValueAt(Object value, int rowIndex, int columnIndex){
FalsePosition falsePosition = getFalsePosition(rowIndex);
switch (columnIndex) {
case 0 -> falsePosition.setA((Double) value);
case 1 -> falsePosition.setB((Double) value);
case 2 -> falsePosition.setFa((Double) value);
case 3 -> falsePosition.setFb((Double) value);
case 4 -> falsePosition.setXi((Double) value);
case 5 -> falsePosition.setError((Double) value);
case 6 -> falsePosition.setFxi((Double) value);
}
fireTableCellUpdated(rowIndex, columnIndex);
}
public FalsePosition getFalsePosition(int row) {
return values.get(row);
}
}
I've run into a very strange issue. I wrote a model for a table and for the most part it works perfect. When I update the row data via the setValueAt function it works and the data in the ArrayList is updated and complete. But when i run the getTotalPay function the same array is empty and i get a null value exception.
I've rewrote the code a number of different ways and tried a couple of different approaches to the problem but the problem persists. I know i've done something wrong i just cannot figure out what the problem is. After search the net and not finding a solution i'm posting this.
Things i've tried are replacing the variable, putting the data into two different variables.
Here is the model
public class WeeklyWagesModel extends AbstractTableModel {
private String defaultValue = "Click to edit";
private String[] headings = { "Date From", "Date To", "Wages", "Pay Date" };
private ArrayList<String[]> theData = new ArrayList<String[]>();
public WeeklyWagesModel() {
theData.add(createDefaultRow());
}
#Override
public int getColumnCount() {
return headings.length;
}
public String getColumnName(int col) {
return headings[col];
}
#Override
public int getRowCount() {
return theData.size();
}
#Override
public Object getValueAt(int row, int col) {
return theData.get(row)[col];
}
public boolean isCellEditable(int row, int col) {
return true;
}
public void setValueAt(Object value, int row, int col) {
theData.get(row)[col] = String.valueOf(value);
if (row == (theData.size() - 1)) {
theData.add(createDefaultRow());
}
fireTableDataChanged();
}
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
public ArrayList<String[]> getData() {
return theData;
}
public String getTotalPay() {
System.out.println("Total Pay: " + theData.size());
BigDecimal total = BigDecimal.ZERO;
for (String[] eachRow : theData) {
if (StringUtils.isNumeric(eachRow[2])) {
total.add(new BigDecimal(eachRow[2]));
}
}
return NumberFormat.getCurrencyInstance().format(total);
}
public String getTotalWeeks() {
return "";
}
private String[] createDefaultRow() {
String[] newRow = new String[headings.length];
for (int i = 0; i < newRow.length; i++) {
newRow[i] = defaultValue;
}
return newRow;
}
}
I am new to Eclipse RCP/Plug-ins and SWT. I want to reorder table items via drag-and-drop.
I have a TableViewer which contains a table with my custom elements of type ITask (еach of my custom elements is wrapped in TableItem). All tutorials I found are about trees or dragging between different tables which is not what I need.
So I want to know how to reorder the table rows via drag-and-drop.
It's a bit long, but you can make this work in your code with a few changes. I did not included the imports; Eclipse can do it for you automatically.
I used Spring's BeanUtils class but you can use any lib (or write your own) that can deepcopy POJOs. I assume that your ITask has a setOrder(int) method and is Serializable (and it qualifies for a POJO)
You need to create a Transfer-type for your ITask: SimpleObjectTransfer is IBM's code, from Eclipse GEF. You can Google/GrepCode it.
public final class TaskTransfer extends SimpleObjectTransfer {
public static final TaskTransfer INSTANCE = new TaskTransfer();
private TaskTransfer() {
}
#Override
protected String getTypeNamePrefix() {
return "TASK_TRANSFER_FORMAT";
}
}
A ViewerDropAdapter:
public class MyDropAdapter<TM extends ITask> extends ViewerDropAdapter {
private final Class<TM> targetModelClass;
private List<TM> listOfModels;
protected MyDropAdapter(Viewer viewer, Class<TM> targetModelClass, List<TM> listOfModels) {
super(viewer);
this.listOfModels = listOfModels;
this.targetModelClass = targetModelClass;
}
#Override
public boolean performDrop(Object arg0) {
boolean ret = false;
TM targetModel = targetModelClass.cast(determineTarget(getCurrentEvent()));
if (targetModel != null) {
if (List.class.isAssignableFrom(arg0.getClass())) {
ret = processDropToTable(targetModel, arg0);
getViewer().refresh();
}
}
return ret;
}
public final boolean processDropToTable(TM targetModel, Object data) {
List<TM> transferredModels = (List<TM>) data;
List<TM> copyOfTransferredModels = transferredModels;
switch (getCurrentOperation()) {
case DND.DROP_COPY:
copyOfTransferredModels = deepCopyBeanList(transferredModels, new String[]{});
break;
case DND.DROP_MOVE:
// moving
break;
default:
throw new UnsupportedOperationException(getCurrentOperation() + " is not supported!");
}
adjustPosition(transferredModels, copyOfTransferredModels, targetModel);
return true;
}
private void adjustPosition(List<TM> transferredModels, List<TM> copyOfTransferredModels, TM targetModel) {
int transferredObjectPosition = listOfModels.indexOf(transferredModels.get(0));
listOfModels.removeAll(copyOfTransferredModels);
addModelsToNewLocation(copyOfTransferredModels, targetModel, listOfModels, transferredObjectPosition);
for (int i = 0; i < listOfModels.size(); i++) {
int orderPosition = i * 10 + 10;
listOfModels.get(i).setOrder(orderPosition);
}
}
protected void addModelsToNewLocation(List<TM> transferredModels, TM targetModel, List<TM> targetList, int transferredObjectPosition) {
switch (determineLocation(getCurrentEvent())) {
case LOCATION_AFTER:
case LOCATION_ON:
int i;
if (!transferredModels.contains(targetModel)) {
i = targetList.indexOf(targetModel) + 1;
} else {
i = transferredObjectPosition;
}
targetList.addAll(i, transferredModels);
break;
case LOCATION_BEFORE:
if (!transferredModels.contains(targetModel)) {
i = targetList.indexOf(targetModel);
} else {
i = transferredObjectPosition;
}
targetList.addAll(i, transferredModels);
break;
case LOCATION_NONE:
default:
break;
}
}
private List<TM> deepCopyBeanList(List<TM> transferredModels, String[] ignoreProperties) {
List<TM> targetList = new LinkedList<TM>();
for (TM element : transferredModels) {
try {
#SuppressWarnings("unchecked")
TM copy = (TM) element.getClass().newInstance();
BeanUtils.copyProperties(element, copy, ignoreProperties);
targetList.add(copy);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return targetList;
}
#Override
public boolean validateDrop(Object arg0, int arg1, TransferData arg2) {
boolean ret = false;
for (Transfer t : new Transfer[]{TaskTransfer.INSTANCE}) {
if (t.isSupportedType(arg2)) {
ret = true;
break;
}
}
return ret;
}
}
A DragSourceListener
public class MyDragSourceListener implements DragSourceListener {
private final Viewer dragSourceViewer;
private final boolean multiObjectsEnabled;
private final Class<?> transferrableElementClass;
private Object[] draggedObjects;
public MyDragSourceListener(Viewer dragSourceViewer, boolean multiObjectsEnabled, Class<?> transferrableElementClass) {
this.dragSourceViewer = dragSourceViewer;
this.multiObjectsEnabled = multiObjectsEnabled;
this.transferrableElementClass = transferrableElementClass;
}
#Override
public void dragStart(DragSourceEvent event) {
Control source = ((DragSource) event.getSource()).getControl();
draggedObjects = null;
if (dragSourceViewer.getControl().equals(source)) {
if (multiObjectsEnabled) {
draggedObjects = ((StructuredSelection) dragSourceViewer.getSelection()).toArray();
} else {
draggedObjects = new Object[]{((StructuredSelection) dragSourceViewer.getSelection()).getFirstElement()};
}
}
event.doit = draggedObjects.length > 0 && transferredDataIsSupported();
}
private boolean transferredDataIsSupported() {
boolean ret = true;
for (Object o : draggedObjects) {
if (o == null || !transferrableElementClass.isAssignableFrom(o.getClass())) {
ret = false;
break;
}
}
return ret;
}
#Override
public void dragSetData(DragSourceEvent event) {
event.data = Arrays.asList(draggedObjects);
}
#Override
public void dragFinished(DragSourceEvent event) {
if (event.detail != DND.DROP_NONE) {
dragSourceViewer.refresh();
}
draggedObjects = null;
}
}
And place a code somewhat like this in your View:
List<ITask> tasks = new WritableList(new ArrayList<ITask>(), ITask.class);
// Let's say tableViewerTasks is your TableViewer's name
DragSource sourceTasks = new DragSource(tblTasks, DND.DROP_MOVE);
sourceTasks.setTransfer(new Transfer[]{TaskTransfer.INSTANCE});
sourceTasks.addDragListener(new MyDragSourceListener(tableViewerTasks, true, ITask.class));
DropTarget targetTasks = new DropTarget(tblTasks, DND.DROP_MOVE);
targetTasks.setTransfer(new Transfer[]{TaskTransfer.INSTANCE});
targetTasks.addDropListener(new MyDropAdapter<ITask>(tableViewerTasks, ITask.class, tasks));
I got an AbstractTableModel, like this:
public class TableModelClienteFornecedor extends AbstractTableModel {
private List<ClienteFornecedorDTO> linhas;
private String[] colunas = new String[]{"Nome", "Conta"};
public TableModelClienteFornecedor() {
linhas = new ArrayList<>();
}
#Override
public int getRowCount() {
return linhas.size();
}
#Override
public int getColumnCount() {
return colunas.length;
}
#Override
public String getColumnName(int column) {
return colunas[column];
}
#Override
public Class getColumnClass(int column) {
return (getValueAt(0, column).getClass());
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
ClienteFornecedorDTO cf = linhas.get(rowIndex);
switch (columnIndex) {
case 0:
return cf.getNome();
case 1:
return cf.getConta();
default:
throw new IndexOutOfBoundsException("Coluna incorreta");
}
}
public void clear(JTable table) {
table.setRowSorter(null);
int indiceAntigo = this.getRowCount();
linhas.clear();
int indiceNovo = this.getRowCount();
this.fireTableRowsDeleted(indiceAntigo, indiceNovo);
}
public boolean isEmpty() {
return linhas.isEmpty();
}
public void add(ClienteFornecedorDTO cf) {
linhas.add(cf);
int index = this.getRowCount();
fireTableRowsInserted(index, index);
}
public void addList(List<ClienteFornecedorDTO> list, JTable table) {
int tamanhoAntigo = this.getRowCount();
linhas.addAll(list);
int tamanhoNovo = this.getRowCount() - 1;
this.fireTableRowsInserted(tamanhoAntigo, tamanhoNovo);
table.setAutoCreateRowSorter(true);
}
public ClienteFornecedorDTO get(int i) {
return linhas.get(i);
}
}
And the code below works ok to fill the my Jtable with data:
private void realizarBusca(String nome) {
IContaDAO dao = new ContaDAO();
boolean isFornecedor = radioFornecedor.isSelected();
List<ClienteFornecedorDTO> retorno =
dao.retornaContaClienteFornecedor(isFornecedor, nome);
tableModelClienteFornecedor.clear();
tableModelClienteFornecedor.addList(retorno, tableClienteFornecedor);
tableClienteFornecedor.updateUI();
}
Everything's working fine to me, and when I sort my Jtable visibily it's ok too, the problem is when I click on a specific row from my Jtable after I sorted it, the row it's not updated.
Anyone can help me with that?
I would appreciate, 'cause I'm on it since yesterday and still wasn't able to find a way to solve it.
Look at the methods convertRowIndexToModel() and convertRowIndexToView() in JTable.
When the table is sorted, the indices of the rows in the view don't match with the indices in the model anymore, and you have to use the above methods to convert from index to view and vice-versa.
For example, if you call JTable.getSelectedRow(), you'll get the view index of the selected row. You'll have to convert it to the model index (using convertRowIndexToModel()) to be able to get the selected object from the list in your model.
coding in Java Eclipse here. Making a booking system. The idea is to take the info from the database ,store it in the ArrayList and from the ArrayList show it in the GUI through JTable. Having some problems with the last part and just can't figure it out..
ArrayList:
import java.util.ArrayList;
public class CarList
{
private ArrayList<Car> cars;
public CarList()
{
cars = new ArrayList<Car>();
}
public int getNumberOfCars()
{
return cars.size();
}
public Car getCar(String CarMake)
{
for (int i = 0; i < cars.size(); i++)
{
if (cars.get(i).getMake() == CarMake)
{
return cars.get(i);
}
}
return null;
}
public int size()
{
return cars.size();
}
public void add(Car car)
{
if (!this.ModelExists(car.getModel()))
{
cars.add(car);
}
}
public Boolean ModelExists(String Model)
{
for (Car c : cars)
{
if (c.getModel().equals(Model))
{
return true;
}
}
return false;
}
public void remove(String CarMake)
{
for (int i = 0; i < cars.size(); i++)
{
if (cars.get(i).getMake() == CarMake)
{
cars.remove(i);
}
}
}
public String toString()
{
String returnStr = "";
for (int i = 0; i < cars.size(); i++)
{
Car temp = cars.get(i);
returnStr += temp + "\n";
}
return returnStr;
}
}
Adapter to get the data from the db to the arraylist:
public CarList getAllCars()
{
MyDatabase myDB = new MyDatabase();
CarList cars = new CarList();
try
{
myDB.openMySQLDatabase("db", "root", "");
String sql = "SELECT Make, Model, LicenseNumber, Color, Year," +
"HorsePower, TimeUntilService, ConsumptionPerKm," +
"NumberOfSeats, NumberOfDoors, Transmission, ClimateControl,Price "
+ "FROM cars";
System.out.println(sql);
Object[][] result = myDB.returnSQLQueryResult(sql);
for (int rows = 0; rows < result.length; rows++)
{
System.out.println("result row");
String make = (String) result[rows][0];
String model = (String) result[rows][1];
String licenseNumber = (String) result[rows][2];
String color = (String) result[rows][3];
int year = (int) result[rows][4];
String horsePower = (String) result[rows][5];
String timeUntilService = (String) result[rows][6];
String consumptionPerKm = (String) result[rows][7];
int numberOfSeats = (int) result[rows][8];
int numberOfDoors = (int) result[rows][9];
String transmission = (String) result[rows][10];
String climateControl = (String) result[rows][11];
int price = (int) result[rows][12];
cars.add(new Car(make, model, licenseNumber, color, year, horsePower,
timeUntilService, consumptionPerKm, climateControl, numberOfSeats, numberOfDoors, transmission, climateControl, price));
}
}
catch (SQLException e)
{
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
finally
{
try
{
myDB.closeDatabase();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
System.out.println(cars.size());
return cars;
}
JTable:
panelBottomRight = new JPanel();
panelBottomRight.setLayout(new BorderLayout());
panelBottomRight.setBorder(new TitledBorder(BorderFactory
.createLineBorder(Color.black), "[Cars]", 2, 0));
tableBottomRightCenter = new JPanel();
tableBottomRightCenter.setLayout(new BorderLayout());
String[] columnNames = { "Make", "Model", "LicenseNumber", "Color",
"Year", "HorsePower", "TimeUntilService",
"ConsumptionPerKm", "NumberOfSeats", "NumberOfDoors",
"ClimateControl" };
CarList cars= new CarList();
String[][] data = {};
// Create table with database data
tableBottomR = new JTable(data, columnNames);
tableBottomR.setAutoCreateRowSorter(true);
tableBottomR.getTableHeader().setReorderingAllowed(false);
tableBottomR.setModel(new DefaultTableModel(data, columnNames)
{
#Override
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return false;
}
});
tableBottomRightCenter.add(tableBottomR, BorderLayout.CENTER);
scrollPane2 = new JScrollPane(tableBottomR);
scrollPane2
.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
tableBottomRightCenter.add(scrollPane2);
panelBottomRight.add(tableBottomRightCenter, BorderLayout.CENTER);
There are a few things that jump out.
In you CarList, the getCar method is comparing object references instead of comparing the contents of the String
For String comparison, you should be using String#equals, for example...
public Car getCar(String CarMake) {
for (int i = 0; i < cars.size(); i++) {
//if (cars.get(i).getMake() == CarMake) {
if (cars.get(i).getMake().equals(CarMake)) {
return cars.get(i);
}
}
return null;
}
You don't seem to be using the getAllCars method to populate the table model, but are simply creating a series of empty table models.
Personally, I'm not a fan of DefaultTableModel, especially given the fact that you have a Car object and CarList object, i would require you to undo all this work to use it, instead, I prefer to create my own, specialised, implementation, which allows me to provide greater control, for example...
public class CarModel extends AbstractTableModel {
private String[] columnNames = { "Make", "Model", "LicenseNumber", "Color",
"Year", "HorsePower", "TimeUntilService",
"ConsumptionPerKm", "NumberOfSeats", "NumberOfDoors",
"ClimateControl" };
private CarList carList;
public CarModel(CarList list) {
carList = list;
}
public CarList getCarList() {
return carList;
}
#Override
public int getRowCount() {
return getCarList().getNumberOfCars();
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public String getColumnName(int column) {
return columnNames[column];
}
#Override
public Class<?> getColumnClass(int columnIndex) {
Class type = String.class;
switch (columnIndex) {
case 0:
type = String.class;
break;
// ...etc...
}
return type;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Car car = getCarList().getCarAt(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = car.getMake();
break;
//...etc...
}
return value;
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
}
This, obviously, will require you to add a getCarAt(int) method to your CarList to return the Car at the given index.
Then, you simply need to extract the data from the database and apply the resulting CarList to the table model, for example...
CarList carList = getAllCars();
CarTableModel model = new CarTableModel(carList);
Then, you just need to add it to your UI, for example...
JTable table = new JTable(model);
add(new JScrollPane(table));
Take a look at How to use tables for more details and examples...