I have a TableModel class that extends the AbstrctTableModel class in java swing but when I try to initialise the subclass which is not abstract, the Netbeans 8.0 IDE complains that I am initialising an abstract class.
the code snippets are provide below.
public class TableModel extends AbstractTableModel {
private List<List<Object>> dataList = new ArrayList<>();
private String[] header = { "ID","SUBJECT","LETTTER FROM","LETTER DATE","DATE RECEIVED",
"REMARKS","DATE DISPATCHED","DESTINATION OFFICE"};
private int minRowCount = 5;
public TableModel()
{ }
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 Math.max(minRowCount, 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) {
Object value = null;
if(row < dataList.size())
{value = dataList.get(row).get(col);}
return value;
}
#Override
public Class<?> getColumnClass(int column)
{
for (int row = 0; row < getRowCount(); row++)
{
Object o = getValueAt(row, column);
if (o != null)
{
return o.getClass();
}
}
return Object.class;
}
}
this is the code that initialises the Table Model class.
private TableColumnAdjuster tca;
/**
* Creates new form MyJFrame
*/
private TableModel tableModel ;
public MyJFrame() throws CorruptIndexException, LockObtainFailedException, IOException,
ParseException, java.text.ParseException, SQLException
{
tableModel = new TableModel(); // the Netbeans IDEcomplains about this code
initComponents();
}
You don't provide any info to specify the exact nature of the complaint, but I'm betting that the AbstractTableModel has an abstract method that your TableModel has failed to override. It would be a compilation error in that case.
If that's true, provide a concrete implementation for that method and you'll be able to take the next step.
Related
The SWT control classes Tree and Table have several methods with the same signature and that work in the same way.
For example:
getItems
getSelection
But these methods are defined directly on Tree and Table, there is no common super class or interface where the methods are declared. Because of this it is hard to write code that works for both Tree and Table.
Is there a solution to this that makes it possible to write common code for both of the classes?
One possible solution is to create a class with the common methods, with subclasses that wraps a Tree or a Table and that delegate these methods to their wrapped control.
Using such classes generic code can look like this:
CollectionControl c = CollectionControl.create(treeOrTable);
int nrItems = c.getSelectionCount();
The following is an example of such classes:
/**
* Wrapps a {#link Tree} or {#link Table} to make it possible to work with them
* in a generic way.
*
* This class could be an interface in Java 8, which allows static methods on interfaces.
*/
public abstract class CollectionControl {
public abstract CollectionItem[] getItems();
public abstract CollectionItem[] getSelection();
public abstract int getSelectionCount();
public abstract Control getControl();
public abstract int getColumnCount();
interface CollectionItem {
String getText(int columnIx);
}
/**
* #param control Either a {#link Tree} or {#link Table}..
* #return A collection which wraps the argument an delegate method calls to it.
* #throws IllegalArgumentException if the argument is not a Tree or a Table.
*/
public static CollectionControl create(Control control) {
if (control instanceof Tree) {
return new TreeControl((Tree) control);
} else if (control instanceof Table) {
return new TableControl((Table) control);
}
throw new IllegalArgumentException();
}
private static class TreeControl extends CollectionControl {
private Tree tree;
public TreeControl(Tree tree) {
this.tree = tree;
}
#Override
public CollectionItem[] getSelection() {
CollectionItem[] items = new CollectionItem[tree.getSelectionCount()];
int ix = 0;
for (TreeItem item : tree.getSelection()) {
items[ix++] = new TreeCollectionItem(item);
}
return items;
}
#Override
public int getSelectionCount() {
return tree.getSelectionCount();
}
#Override
public Tree getControl() {
return tree;
}
#Override
public CollectionItem[] getItems() {
CollectionItem[] items = new CollectionItem[tree.getItemCount()];
int ix = 0;
for (TreeItem item : tree.getItems()) {
items[ix++] = new TreeCollectionItem(item);
}
return items;
}
#Override
public int getColumnCount() {
return tree.getColumnCount();
}
private static class TreeCollectionItem implements CollectionItem {
private TreeItem item;
public TreeCollectionItem(TreeItem item) {
this.item = item;
}
#Override
public String getText(int columnIx) {
return item.getText(columnIx);
}
}
}
private static class TableControl extends CollectionControl {
private Table table;
public TableControl(Table table) {
this.table = table;
}
#Override
public CollectionItem[] getSelection() {
CollectionItem[] items = new CollectionItem[table.getSelectionCount()];
int ix = 0;
for (TableItem item : table.getSelection()) {
items[ix++] = new TableCollectionItem(item);
}
return items;
}
#Override
public int getSelectionCount() {
return table.getSelectionCount();
}
#Override
public Table getControl() {
return table;
}
#Override
public CollectionItem[] getItems() {
CollectionItem[] items = new CollectionItem[table.getItemCount()];
int ix = 0;
for (TableItem item : table.getItems()) {
items[ix++] = new TableCollectionItem(item);
}
return items;
}
#Override
public int getColumnCount() {
return table.getColumnCount();
}
private static class TableCollectionItem implements CollectionItem {
private TableItem item;
public TableCollectionItem(TableItem item) {
this.item = item;
}
#Override
public String getText(int columnIx) {
return item.getText(columnIx);
}
}
}
}
What is the proper relationship, in code, between a table model and the actual database queries?
Inside the addRow() method in the table model, should I place a further call to my database class, which in turn inserts the row into the database? I've illustrated this in the below code snippets.
public class MainPanel extends JPanel
{
...
public MainPanel()
{
personTableModel = new PersonTableModel();
personTable = new JTable(personTableModel);
...
insertButton = new JButton("Insert");
insertButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
String name = nameTextBox.getText();
String address = addressTextBox.getText();
Object[] row = { name, address };
personTableModel.addRow(row); // <--- Add row to model
}
});
}
}
public class PersonTableModel extends AbstractTableModel
{
private List<Object[]> data;
private List<String> columnNames;
PersonDB personDB = new PersonDB();
...
public void addRow(Object[] row)
{
// insert row into 'data'
personDB.addPerson(row); // <---- Call the personDB database class
}
...
}
public class PersonDB
{
public PersonDB()
{
// establish database connection
}
public addPerson(Object[] row)
{
// code that creates a SQL statement based on row data
// and inserts new row into database.
}
...
}
Whether or not you should directly make an insert call depends on some aspects:
Do you want other processes to access the data immediately?
Do you fear that your program crashes and you lose important information?
Can you ensure that any data persisted during addRow is meaningful (the program could terminate directly after the insert)?
Than of course it may be a good idea to directly insert the data into the backing Database.
You should however watch out, that there are two variants of addRow and two variants of insertRow. DefaultTableModel directs calls internally through insertRow(int, Vector), which would probably be the only function to overwrite, if you want to immediately persist data.
If you like the proposed idea of DTOs the examples below may help you.
The Idea is to represent "Entities" or table rows as classes in Java. A DTO is the simplest representation and normally only contains fields with respective getter and setter.
Entities can generically be persisted and loaded through ORM libraries like EclipseLink or Hibernate. Additionally for this table-application the use of DTOs provide a way of storing data not shown to the user in a clean and typed way.
DTO:
public class PersonDto {
private Long id;
private String name;
private String street;
public PersonDto() {
}
public PersonDto(Long id, String name, String street) {
this.id = id;
this.name = name;
this.street = street;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public static class NameColumn extends DtoTableModel.ColumnProvider<PersonDto, String> {
public NameColumn() {
super("Name", String.class);
}
#Override
public String getValue(PersonDto dto) {
return dto.getName();
}
#Override
public void setValue(PersonDto dto, Object value) {
dto.setName((String) value);
}
}
public static class StreetColumn extends DtoTableModel.ColumnProvider<PersonDto, String> {
public StreetColumn() {
super("Street", String.class);
}
#Override
public String getValue(PersonDto dto) {
return dto.getStreet();
}
#Override
public void setValue(PersonDto dto, Object value) {
dto.setStreet((String) value);
}
}
}
DTO based TableModel:
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
public class DtoTableModel<T> extends AbstractTableModel {
private final ArrayList<T> rows;
private final ArrayList<ColumnProvider<T, ?>> columns;
protected DtoTableModel() {
rows = new ArrayList<T>();
columns = new ArrayList<ColumnProvider<T, ?>>();
}
#Override
public int getRowCount() {
return rows.size();
}
#Override
public int getColumnCount() {
return columns.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return columns.get(columnIndex).getValue(rows.get(rowIndex));
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
final ColumnProvider<T, ?> column = columns.get(columnIndex);
column.setValue(rows.get(rowIndex), aValue);
this.fireTableCellUpdated(rowIndex, columnIndex);
}
#Override
public String getColumnName(int column) {
return columns.get(column).getTitle();
}
public void addColumn(ColumnProvider<T, ?> column) {
this.columns.add(column);
this.fireTableStructureChanged();
}
public void addRow(T row) {
this.rows.add(row);
this.fireTableRowsInserted(this.rows.size() - 1, this.rows.size() - 1);
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return this.columns.get(columnIndex).getValueClass();
}
public static abstract class ColumnProvider<T, V> {
private String title;
private final Class<V> valueClass;
protected ColumnProvider(String title, Class<V> valueClass) {
this.title = title;
this.valueClass = valueClass;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Class<V> getValueClass() {
return valueClass;
}
public abstract V getValue(T dto);
public abstract void setValue(T dto, Object value);
}
}
Example-"Application":
import javax.swing.*;
import java.awt.*;
public class JTableTest extends JFrame {
private final JTable jTable;
public JTableTest() throws HeadlessException {
super("JFrame test");
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
final GridBagLayout layout = new GridBagLayout();
final Container contentPane = this.getContentPane();
contentPane.setLayout(layout);
final GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
final DtoTableModel<PersonDto> dm = new DtoTableModel<PersonDto>();
jTable = new JTable(dm);
dm.addColumn(new PersonDto.NameColumn());
dm.addColumn(new PersonDto.StreetColumn());
dm.addRow(new PersonDto(1L, "Paul", "Mayfairy Street"));
dm.addRow(new PersonDto(2L, "Peter", "Ferdinand Street"));
JScrollPane scrollpane = new JScrollPane(jTable);
contentPane.add(scrollpane, gridBagConstraints);
this.pack();
}
public static void main(String[] args) {
final JTableTest jTableTest = new JTableTest();
jTableTest.setVisible(true);
}
}
public class Table{
private String column[];
private String dataType[];
private boolean PK[];
private boolean NN[];
private int count;
public Table()
{
count =0;
}
public void AddColumn(String name,String dtype,boolean pk,boolean nn)
{
column[count]=name;
dataType[count]=dtype;
PK[count]=pk;
NN[count]=nn;
count++;
}
public void Display(Table T)
{
}
public void DeleteColumn(String name)
{
if(count==0){return;}
else if(count ==1)
{
if(name==column[0])
column[0]=null;
dataType[0]=null;
count--;
return;
}
else
for(int i=0;i<count;i++)
{
if(name==column[i])
{
column[i]=column[count-1];
dataType[i]=dataType[count-1];
PK[i]=PK[count-1];
NN[i]=NN[count-1];
}
}
}
This is my table class; as im designing an Entity table and for keeping column Name data type etc. Is this class and its private attributes correct or should i break this into more classes eg attributes.
I think that you should create Column class.
I will do it in this way (of course it can be done better):
public class DataType {
public static String DATA_TYPE_1 = "dataType1";
public static String DATA_TYPE_2 = "dataType2";
public static String DATA_TYPE_3 = "dataType3";
}
public class Column() {
private String name;
private DataType dataType;
private boolean PK;
private boolean NN;
// getters and setters
}
public class Table {
private ArrayList<Column> columns;
public Table() {
columns = new ArrayList<Column>();
}
public boolean AddColumn(Column column) {
columns.add(column);
}
public boolean DeleteColumn(String name) {
for (Column c : columns) {
if (c.getName().equals(name)) {
return columns.remove(column);
}
}
return false;
}
}
I'm working on my homework and I can't complete one piece of my program ...
I have JTable class which makes table in my code ... i have to write method which takes information from sql database and writes it in list
method MUST look like:
public static List selectAnswers (int questionId) throws SQLException, IOException
following code is written by me:
public static List<AnswerRow> selectAnswers (int questionId) throws SQLException, IOException
{
Connection veza = connectToDatabase();
Properties query = new Properties();
AnswersTableModel atm = new AnswersTableModel();
String selectAnswers = query.getProperty("selectAnswers");
PreparedStatement preparedStatement = veza.prepareStatement(selectAnswers);
ResultSet rs = preparedStatement.executeQuery();
List<AnswerRow> lista = new ArrayList<AnswerRow>();
while(rs.next()){
String answerText = rs.getString("answerText");
boolean isRight = rs.getBoolean("answerRight");
?????????????????????????????????????????????????
}
closeConnectionToDatabase(veza);
return lista;
}
????? field is missing and i dont know what to write there to write information answeText and isRight into AnswerRow class , into AnswerTableModel, into list ...
Code which makes JTable (and is given to me and cannot be changed by my teacher) is here:
package hr.tvz.java.deveti.model;
import java.util.List;
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
public class AnswersTableModel extends AbstractTableModel {
private Object[][] answers;
private String[] columnNames;
public AnswersTableModel (String[] colNames){
super();
columnNames = colNames;
}
public AnswersTableModel() {
super();
this.columnNames = new String[AnswerRow.TABLE_COLUMNS];
this.columnNames[0] = "Odgovor";
this.columnNames[1] = "Točan/Netočan";
}
public java.lang.Class<?> getColumnClass(int columnIndex) {
return getValueAt(0, columnIndex).getClass();
}
public int getColumnCount() {
return AnswerRow.TABLE_COLUMNS;
}
public int getRowCount() {
if (answers != null)
return answers.length;
else
return 0;
}
public Object getValueAt(int row, int column) {
return answers[row][column];
}
public String getColumnName(int column){
return columnNames[column];
}
public void setValueAt (Object aValue, int rowIndex, int columnIndex){
answers[rowIndex][columnIndex] = aValue;
}
public boolean isCellEditable (int rowIndex, int columnIndex){
return true;
}
public void addNewRow(){
Object[] o = new Object[] {"", false};
if ((answers == null) || (answers.length == 0)) {
answers = new Object[][] {o};
}else{
Object[][] answersTemp = new Object[answers.length + 1][AnswerRow.TABLE_COLUMNS];
for (int i = 0; i < answers.length; i++)
answersTemp[i] = answers[i];
answersTemp[answersTemp.length - 1] = o;
answers = answersTemp;
}
}
public List<AnswerRow> getAnswerRows() {
List<AnswerRow> list = new ArrayList<>();
for (Object[] oRow : answers) {
AnswerRow row = new AnswerRow();
row.setAnswer((String) oRow[0]);
row.setRight((boolean) oRow[1]);
list.add(row);
}
return list;
}
public void setAnswerRows(List<AnswerRow> answerRows){
if (answerRows.size() == 0 ) {
this.answers = new Object[0][0];
return;
}
this.answers = new Object[answerRows.size()][AnswerRow.TABLE_COLUMNS];
for (int i = 0; i < answers.length; i++){
answers[i][0] = answerRows.get(i).getAnswer();
answers[i][1] = answerRows.get(i).isRight();
}
this.columnNames = new String[AnswerRow.TABLE_COLUMNS];
this.columnNames[0] = "Odgovor";
this.columnNames[1] = "Točno/Netočno";
}
public class AnswerRow {
public static final int TABLE_COLUMNS = 2;
private boolean isRight;
private String answer;
public AnswerRow(){
answer = "";
isRight = false;
}
public AnswerRow(String answer, boolean isRight){
this.answer = answer;
this.isRight = isRight;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer){
this.answer = answer;
}
public boolean isRight(){
return isRight;
}
public void setRight(boolean isRight){
this.isRight = isRight;
}
}
}
Please help me .. thanks !
List<AnswerRow> lista = new ArrayList<AnswerRow>();
while(rs.next()){
String answerText = rs.getString("answerText");
boolean isRight = rs.getBoolean("answerRight");
//Create AnswerRow instance and set values to it and Add it to list.
AnswersTableModel .AnswerRow ansrow = atm.new AnswerRow();
ansrow.setAnswer(answerText);
ansrow.setRight(isRight);
//Add it to list.
lista.add(ansrow);
}
One thing I am not sure is why you have AnswersTableModel and what you do with that.
Use public AnswerRow(String answer, boolean isRight) constructor to create object
AnswerRow ar=null;
while(rs.next()){
String answerText = rs.getString("answerText");
boolean isRight = rs.getBoolean("answerRight");
ar=new AnswerRow(answerText, isRight);
lista.add(ar);
}
I should tell this first, this is NOT about Rendering a Table cell.
Here is the TableModel that i'm building using a 2D array based on a User object in my DB.
List<User> userList = userManagerService.getAllUsers();
/* String[] col_user = {"Username", "Name", "Phone", .... } */
String[][] data = new String[userList.size()][col_user.length];
int i = 0;
for (User user : userList) {
String[] userdata = new String[col_user.length];
userdata[0] = user.getUserUsername();
userdata[1] = user.getUserName();
userdata[2] = user.getUserPhone();
userdata[3] = user.getUserNic();
userdata[4] = user.getUserAddress();
userdata[5] = user.getUserEmail();
data[i++] = userdata;
}
VstTableItemModel tiModel = new VstTableItemModel(data, col_user);
dataTable.setModel(tiModel);
My problem is how can i get a User object back, using the selected row in the Table. Note that i can't make a new User object and populate it with the row data. I must get the queried User object(objects in userList). So, is their any way to set a Object with a table row ?
Here is my VstTableItemModel class.
public class VstTableItemModel extends AbstractTableModel {
ArrayList<Object[]> data;
String[] header;
public VstTableItemModel(Object[][] obj, String[] header) {
this.header = header;
data = new ArrayList<Object[]>();
for (int i = 0; i < obj.length; ++i) {
data.add(obj[i]);
}
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return header.length;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data.get(rowIndex)[columnIndex];
}
#Override
public String getColumnName(int index) {
return header[index];
}
}
Instead of splitting the User object up before you create the model, add it directly to the model and allow the model to do the work for you...
For example
public class VstTableItemModel extends AbstractTableModel {
private List<User> users;
public VstTableItemModel(List<User> users) {
this.users = new ArrayList<User>(users);
}
#Override
public int getRowCount() {
return users.size();
}
#Override
public int getColumnCount() {
return 6;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object value = "??";
User user = users.get(rowIndex);
switch (columnIndex) {
case 0:
value = user.getUserUsername();
break;
case 1:
value = user.getUserName();
break;
case 2:
value = user.getUserPhone();
break;
case 3:
value = user.getUserNic();
break;
case 4:
value = user.getUserAddress();
break;
case 5:
value = user.getUserEmail();
break;
}
return value;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return // Return the class that best represents the column...
}
/* Override this if you want the values to be editable...
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
//....
}
*/
/**
* This will return the user at the specified row...
* #param row
* #return
*/
public User getUserAt(int row) {
return users.get(row);
}
}
This way, you should be able to do something like...
List<User> userList = userManagerService.getAllUsers();
VstTableItemModel tiModel = new VstTableItemModel(userList);
Now when you need to...you can grab a the user that is represent at a specific row...
User user = tiModel.getUserAt(rowIndex);