Saving JTable Values in an ArrayList - java

I'm currently programming Yahtzee and I'm in the process of changing the player names. For this I use an extra form in which there is a JTable and a JButton.
Depending on the variable number of players in the table, an entry will be created where you can change the name. Only the second column should be editable - this also works.
However, I have no idea how to make it possible to add the contents from the second column to an ArrayList at the push of a button so that I can continue to use them.
Here is the implementation of my custom TableModel
public class SpielerBenennungTableModel implements TableModel {
private int spielerAnzahl = 0;
private ArrayList<TableModelListener> Listener = new ArrayList<TableModelListener>();
public SpielerBenennungTableModel(int spielerAnzahl){
this.spielerAnzahl = spielerAnzahl;
}
#Override
public int getRowCount() {
return spielerAnzahl;
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public String getColumnName(int arg0) {
if(arg0 == 0){
return "Spieler";
}else{
return "Eigener Name";
}
}
#Override
public Class<?> getColumnClass(int arg0) {
return String.class;
}
#Override
public boolean isCellEditable(int arg0, int arg1) {
if(arg1 == 1){
return true;
}else{
return false;
}
}
#Override
public Object getValueAt(int arg0, int arg1) {
if(arg1 == 0){
return "Spieler: " + (arg0+1);
}else{
return rowData[arg0][arg1];
}
}
#Override
public void setValueAt(Object arg0, int arg1, int arg2) {
}
#Override
public void addTableModelListener(TableModelListener arg0) {
Listener.add(arg0);
}
#Override
public void removeTableModelListener(TableModelListener arg0) {
Listener.remove(arg0);
}
}

Try this out:
In your SpielerBenennungTableModel you need an object to hold the data you display. We will be using a List<String[]> that should look like this (I named it rows):
[
["Spieler: 1", "Bob"],
["Spieler: 2", "John"]
]
every time you change a value, the setValueAt method is called and will update the List<String[]> with the correct value.
Then when you use the getValueAt method, it will read from this same List<String[]>
class SpielerBenennungTableModel implements TableModel {
private int spielerAnzahl = 0;
private ArrayList<TableModelListener> Listener = new ArrayList<TableModelListener>();
// this will hold the data for every rows
private List<String[]> rows;
public SpielerBenennungTableModel(int spielerAnzahl){
this.spielerAnzahl = spielerAnzahl;
// initialize the list so that all rows are
// ["Spieler: n", ""]
rows = new ArrayList<>();
for(int i = 0; i<spielerAnzahl; i++) {
this.rows.add(new String[] { "Spieler: " + (i+1), "" });
}
}
#Override
public int getRowCount() {
return spielerAnzahl;
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public String getColumnName(int col) {
return col == 0 ? "Spieler" : "Eigener Name";
}
#Override
public Class<?> getColumnClass(int col) {
return String.class;
}
#Override
public boolean isCellEditable(int row, int col) {
return col == 1;
}
#Override
public Object getValueAt(int row, int col) {
return rows.get(row)[col];
}
#Override
public void setValueAt(Object value, int row, int col) {
rows.get(row)[col] = value.toString();
}
#Override
public void addTableModelListener(TableModelListener arg0) {
Listener.add(arg0);
}
#Override
public void removeTableModelListener(TableModelListener arg0) {
Listener.remove(arg0);
}
}

Related

Displaying input on JTable

I want to display the data on JTable for every button press. Before that, the button will create and store data to the List and should display the data on the table. But, only the creation and data storing is working and the data is not displayed. What should I do to display the data on the table.
This is the abstract model I made to fill my table.
import javax.swing.JList;
import javax.swing.table.AbstractTableModel;
import com.main.Products;
import java.util.List;
public class CartTableModel extends AbstractTableModel{
List<Products> productList;
private final String[] columnNames = new String[] {
"Product:", "ID:", "Variant:", "Size:","Unit Price:","Quantity:","Unit Total:"
};
private Class[] columnClass = new Class[] {
String.class, Integer.class, String.class, String.class, Double.class, Integer.class, Double.class
};
public CartTableModel(List<ProductInfo> productList)
{
this.productList = productList;
}
public String getColumnName(int column)
{
return columnNames[column];
}
#Override
public Class<?> getColumnClass(int columnIndex)
{
return columnClass[columnIndex];
}
#Override
public int getColumnCount()
{
return columnNames.length;
}
#Override
public int getRowCount()
{
return productList.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex)
{
Products row = productList.get(rowIndex);
if(0 == columnIndex) {
return row.getProductName();
}
else if(1 == columnIndex) {
return row.getProductID();
}
else if(2 == columnIndex) {
return row.getVariant();
}
else if(3 == columnIndex) {
return row.getSize();
}
else if(4 == columnIndex){
return row.getUnitPrice();
}
else if(5 == columnIndex){
return row.getQuantity();
}
else if(6 == columnIndex){
return row.getTotal();
}
return null;
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return true;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex)
{
Products row = productList.get(rowIndex);
if(0 == columnIndex) {
row.setProductName((String) aValue);
}
else if(1 == columnIndex) {
row.setProductID((int) aValue);
}
else if(2 == columnIndex) {
row.setVariant((String) aValue);
}
else if(3 == columnIndex) {
row.setSize((String) aValue);
}
else if(4 == columnIndex){
row.setUnitPrice((double) aValue);
}
else if(5 == columnIndex){
row.setQuantity((int) aValue);
}
}
}
This is how the JTable is created:
CartTableModel model = new CartTableModel(productList);
JTable cartTable = new JTable(model);
Also, This is how the data is created:
public void actionPerformed(ActionEvent e) {
if(e.getSource() == coconutPieBtn){
cart.addProduct(new Product("Coconut Creamy Pie", 101,"Pastry","Med",79.99));
}
}
fireTableCellUpdated(productList.size(), columnNames.length)
The row/column values you specify are wrong for two reasons:
you always use the same value no matter what cell you update and
java indexes are 0 based, so you are referring to a row/column that doesn't exist.
Just use:
fireTableCellUpdated(rowIndex, columnIndex)
Also:
cart.addProduct(new Product("Coconut Creamy Pie", 101,"Pastry","Med",79.99));
is wrong. Once the model is created you need to add the new Product to the CartTableModel, NOT the List.
So you need to create a method in your CartTableModel to dynamically add products.
The basic code would be:
public void addProduct(Product product)
{
insertProduct(getRowCount(), product);
}
public void insertProduct(int row, Product product)
{
products.add(row, product);
fireTableRowsInserted(row, row);
}
Check out Row Table Model for a complete example of creating your own custom TableModel with methods for dynamically updating the model.

Recyclerview DiffUtil scrolls my list to top when updated

I've decided to give DiffUtil a try instead of notifyDataSetChanged in my EndlessRecyclerView.
The problem is, after the first or second fling my list is scrolled to top, but the items are added to the list.
Here's my DiffUtil:
public class MovieDiffCallback extends DiffUtil.Callback {
List<Movie> mOldMovieList;
List<Movie> mNewMovieList;
public MovieDiffCallback(List<Movie> oldMovieList, List<Movie> newMovieList) {
this.mOldMovieList = oldMovieList;
this.mNewMovieList = newMovieList;
}
#Override
public int getOldListSize() {
return mOldMovieList != null ? mOldMovieList.size() : 0;
}
#Override
public int getNewListSize() {
return mNewMovieList != null ? mNewMovieList.size() : 0;
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return mOldMovieList.get(oldItemPosition).getId().equals(mNewMovieList.get(newItemPosition).getId());
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return mOldMovieList.get(oldItemPosition).equals(mNewMovieList.get(newItemPosition));
}
#Nullable
#Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
return super.getChangePayload(oldItemPosition, newItemPosition);
}
}
And this is where I use it in my Fragment:
#Override
public void getMovies(List<Movie> moviesList) {
mDiffCallback = new MovieDiffCallback(mMoviesList, moviesList);
mDiffResult = DiffUtil.calculateDiff(mDiffCallback);
mMoviesList.addAll(moviesList);
mDiffResult.dispatchUpdatesTo(mAdapter);
isLoadedLandscape = true;
}
And this is in the EndlessRecyclerScroll:
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
scrollPage++;
populateMap(scrollPage);
mPresenter.getSuggestedMovies(searchParamsMap);
}

Android: detecting removed item in ObservableList

I am using ObservableList in my model for binding. When the item is removed from ObservableList, I want to know about what item has been removed. So I am using ObservableList.OnListChangedCallback.
When the item is removed, it will called onItemRangeRemoved(). But the problem is the item has been removed from the ObservableList in onItemRangeRemoved().
catDatas.addOnListChangedCallback(new ObservableList.OnListChangedCallback<ObservableList<CatData>>()
{
#Override
public void onChanged(ObservableList<CatData> sender)
{
}
#Override
public void onItemRangeChanged(ObservableList<CatData> sender, int positionStart, int itemCount)
{
}
#Override
public void onItemRangeInserted(ObservableList<CatData> sender, int positionStart, int itemCount)
{
}
#Override
public void onItemRangeMoved(ObservableList<XROrderItemData> sender, int fromPosition, int toPosition, int itemCount)
{
}
#Override
public void onItemRangeRemoved(ObservableList<CatData> sender, int positionStart, int itemCount)
{
for (int idx = itemCount - 1; idx >= 0; idx--)
{
CatData data = sender.get(idx + positionStart); //this line will throw index out of bounds exception
...
...
...
uninitData(data);
}
}
});
Any idea how to capture the items that are removed?
Thanks...
The folks at Google overlooked the removeAll() method, so it does not notify observers. To fix this, use this custom class:
class MyObservableArrayList<T>: ObservableArrayList<T>() {
override fun removeAll(elements: Collection<T>): Boolean {
var success = false
elements.forEach { if (super.remove(it)) success = true }
return success
}
}

How to add certain paths in the List?

Code below counts files with certain name. TypeCount is then some number (four for example).
File dir = new File(Environment.getExternalStorageDirectory().toString(), "/AppDir/" );
File[] files=dir.listFiles();
int typeCount = 0;
String type = "dog";
for (int i=0; i<files.length; i++) {
File file = files[i];
String filepath = file.getPath();
if(filepath.contains(type)){
typeCount = typeCount + 1;
}
}
In this code I want to put every path (File) in the List<File>. But when I set typeCount to size of the List I get always zero instead.
File dir = new File(Environment.getExternalStorageDirectory().toString(), "/AppDir/" );
File dir = new File(Environment.getExternalStorageDirectory().toString(), "/AppDir/" );
File[] files=dir.listFiles();
int typeCount = 0;
String typeype = "dog";
List<File> myList;
myList = new List<File>() {
#Override
public void add(int i, File file) {
}
#Override
public boolean add(File file) {
return false;
}
#Override
public boolean addAll(int i, Collection<? extends File> collection) {
return false;
}
#Override
public boolean addAll(Collection<? extends File> collection) {
return false;
}
#Override
public void clear() {
}
#Override
public boolean contains(Object o) {
return false;
}
#Override
public boolean containsAll(Collection<?> collection) {
return false;
}
#Override
public File get(int i) {
return null;
}
#Override
public int indexOf(Object o) {
return 0;
}
#Override
public boolean isEmpty() {
return false;
}
#NonNull
#Override
public Iterator<File> iterator() {
return null;
}
#Override
public int lastIndexOf(Object o) {
return 0;
}
#Override
public ListIterator<File> listIterator() {
return null;
}
#NonNull
#Override
public ListIterator<File> listIterator(int i) {
return null;
}
#Override
public File remove(int i) {
return null;
}
#Override
public boolean remove(Object o) {
return false;
}
#Override
public boolean removeAll(Collection<?> collection) {
return false;
}
#Override
public boolean retainAll(Collection<?> collection) {
return false;
}
#Override
public File set(int i, File file) {
return null;
}
#Override
public int size() {
return 0;
}
#NonNull
#Override
public List<File> subList(int i, int i1) {
return null;
}
#NonNull
#Override
public Object[] toArray() {
return new Object[0];
}
#NonNull
#Override
public <T> T[] toArray(T[] ts) {
return null;
}
};
for (int i=0; i<files.length; i++){
File file = files[i];
String filepath = file.getPath();
if(filepath.contains(type)){
myList.add(file);
}
}
typeCount = myList.size();
What is wrong here?
(And a little off topic - Is path written correctly? I'm not sure about it.)
This method size() will always print 0 because your own List implementation has a wrong returning statement:
#Override
public int size() {
return 0; // Oops!
}
Another thing too, you don't really insert anything in your List because of this:
#Override
public boolean add(File file) {
return false; // Hum...
}
Your methods aren't completed yet to execute the same tasks as a normal List. You better should use ArrayList<File> or List<File> which will have all the right methods and won't require hard work from you. Don't reinvent the wheel ;)
Finally, the path are right declared, but you should test if the files are presents in the folder before executing the code. Something as follows:
File[] files = dir.listFiles();
if (files.length > 0) {
// loop and add to a list
}

presenting string and date data types in a jtable

I have a jtable with columns for both string and date data types.
but for now every information is presented as a string data
I will like to present date data types in the jtable's
date columns.
I also present below codes for the data model
public class MyTableModel extends AbstractTableModel {
private List<List<Object>> dataList = new ArrayList<>();
private String[] header = { "ID","SUBJECT","LETTTER FROM","LETTER DATE","DATE RECEIED",
"REMARKS","DATE DISPATCHED","DESTINATION OFFICE"};
public List<List<Object>> getDataList() {
return dataList;
}
public void setDataList(List<List<Object>> dataList) {
this.dataList = dataList;
fireTableDataChanged();
fireTableStructureChanged();
}
public void setHeader(String[] header) {
this.header = header;
}
public String[] getHeader() {
return header;
}
#Override
public int getRowCount() {
return dataList.size();
}
#Override
public int getColumnCount() {
return header.length;
}
#Override
public String getColumnName(int col) {
return header[col];
}
#Override
public Object getValueAt(int row, int col) {
return dataList.get(row).get(col);
}
}
any suggestion cos am new to jtable
Override getColumnClass method:
#Override
public Class<?> getColumnClass(int columnIndex) {
if (isDate(columnIndex)) {
return Date.class;
}
else {
return String.class;
}
}

Categories