Java ArrayIndexOutOfBoundsException in native method? [duplicate] - java

I'm subclassing JTable and using a DefaultTableModel to model my table data. The following class sets up the JTable, and adds one row to the model.
import java.io.File;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
public class SelectedFileTable extends JTable {
Vector<File> SelectedFiles = new Vector<File>();
DefaultTableModel Model = new DefaultTableModel();
TableColumn ColumnName = new TableColumn();
TableColumn ColumnSize = new TableColumn();
TableColumn ColumnRmIcon = new TableColumn();
ImageFilenameFilter Filter = new ImageFilenameFilter();
public SelectedFileTable() {
super();
this.setModel(Model);
ColumnName.setHeaderValue(new String("Name") );
ColumnName.setMinWidth(200);
ColumnSize.setHeaderValue(new String("Size") );
ColumnSize.setMinWidth(50);
ColumnSize.setMaxWidth(100);
ColumnRmIcon.setHeaderValue(new String("Remove?") );
ColumnRmIcon.setMaxWidth(100);
ColumnRmIcon.setResizable(false);
this.addColumn(ColumnName);
this.addColumn(ColumnSize);
this.addColumn(ColumnRmIcon);
this.setShowVerticalLines(false);
this.setShowHorizontalLines(true);
this.setAutoCreateColumnsFromModel(true);
this.addFile( new File("C:/temp/cfk.jpg") );
}
public void addFile(File file) {
System.out.println("FileTable adding: " + file.getName() );
if ( file.isDirectory() ) {
for ( File f : file.listFiles(Filter) ) {
this.addFile(f);
}
} else {
if ( Filter.accept(file) ) {
System.out.println("Accepting file; " + file.getName() );
SelectedFiles.add(file);
{
String name = file.getName();
Long size = new Long( file.length() );
String tempstr = new String("X");
System.out.println("RowItems before: " + Integer.toString(Model.getRowCount()) );
Model.addRow( new Object[] { name, size, tempstr } );
Model.fireTableDataChanged();
System.out.println("RowItems start : " + Integer.toString(Model.getRowCount()) );
}
System.out.println("Done Accepting file; " + file.getName() );
}
}
}
public Iterator<File> iterator() {
return SelectedFiles.iterator();
}
}
At display/visualization time, the following exception is thrown:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
at java.util.Vector.elementAt(Vector.java:432)
at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:622)
at javax.swing.JTable.getValueAt(JTable.java:1903)
at javax.swing.JTable.prepareRenderer(JTable.java:3911)
at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2072)
at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:1974)
at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1897)
at javax.swing.plaf.ComponentUI.update(ComponentUI.java:142)
at javax.swing.JComponent.paintComponent(JComponent.java:743)
at javax.swing.JComponent.paint(JComponent.java:1006)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JViewport.paint(JViewport.java:728)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:559)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4979)
at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4925)
at javax.swing.JComponent.paint(JComponent.java:996)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
at java.awt.Container.paint(Container.java:1709)
at sun.awt.RepaintArea.paintComponent(RepaintArea.java:248)
at sun.awt.RepaintArea.paint(RepaintArea.java:224)
at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:254)
at java.awt.Component.dispatchEventImpl(Component.java:4060)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Window.dispatchEventImpl(Window.java:1791)
at java.awt.Component.dispatchEvent(Component.java:3819)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)
I'm ripping my hair out - I haven't been able to find the root cause of this immensely simple use case.

I ran on this issue too (with a JList and a DefaultListModel).
Dmitry's answer is right.
However, there is another thing:
this exception can also be thrown if you don't modify the model in Swing's Event Dispatch Thread.
Doing the following can help you avoid this exception:
SwingUtilities.invokeLater(new Runnable(){public void run(){
//Update the model here
}});
http://www.javakb.com/Uwe/Forum.aspx/java-gui/3012/JList-JScrollPane-DefaultListModel-Updating

I think you need to add columns to your TableModel. Your code adds UI columns to the table but doesn't add them to the model

Dmitry is right. Replace
this.addColumn(ColumnName);
this.addColumn(ColumnSize);
this.addColumn(ColumnRmIcon);
with
Model.addColumn(ColumnName);
Model.addColumn(ColumnSize);
Model.addColumn(ColumnRmIcon);
and now the Model knows about the columsn and won't throw an Exception anymore when you try to add a row to a model which thinks it has 0 columns

From the JTable.setAutoCreateColumnsFromModel() API:
"This method calls createDefaultColumnsFromModel if autoCreateColumnsFromModel changes from false to true. "
Vector throws ArrayIndexOutOfBoundsException - if the index is out of range ( index < 0 || index >= size())
I guess the table model is missing the columns, as suggested by Dmitry

Replace your code with the following
Here you need to remove first row only that should be iterated for all the rows
private void refreshTable() {
int rowCount= model.getRowCount();
// System.out.println(rowCount);
for(int i=0;i<rowCount;i++ ){
model.removeRow(0);
//System.out.println(i);
}
}

replace
tabWindow.addTab(...);
with
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
tabWindow.addTab(...);
}
});
Such situation can hapen when you change tabbed pane in action listener.

Another issue might be related when you use RowSorter. When you edit the model RowSorter tries to re-sort the old model. It should be automatically re-created and re-run on each changes of table model.
You can fix it by
tableModel = new DefaultTableModel(data, columnNames);
jTableSentence.setModel(tableModel);
jTableSentence.setRowSorter(new TableRowSorter(tableModel));
jTableSentence.setAutoCreateRowSorter(true);
-Hayri

I was facing this problem because i was adding columns and rows to the JTable not to the model.
best way is this.
Object[][]rows = new Object[ ][ ] { {"a","b"} , {"c","d"} };
Object[]columns = new Object[] {"column1","column2"};
JTable table = new JTable();
table.setModel(new DefaultTableModel(rows,columns));

Dmitry is right, but you simply have to update your model.
To do this, add the following to your code:
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
for (int c = 0; c < table.getColumnCount(); c++) {
dtm.addColumn(table.getColumnName(c));
}

It is necessary to add isCellEditable method to your table model class with return false.
#Override
public boolean isCellEditable(int row, int column)
{
return false;
}

Related

Star rank in table row are displayed outside the table

when I Run the project the table rows are displayed correctly except the rank stars the show outside the table and inside the colonne a text appears as displayed in the image :
public ListTasksForm(Form previous) {
SpanLabel sp = new SpanLabel();
sp.setText(ServiceTask.getInstance().getAllArticles().toString());
ArrayList<Articles> articles = ServiceTask.getInstance().getAllArticles();
Object[][] rows = new Object[articles.size()][];
for (int iter = 0; iter < rows.length; iter++) {
rows[iter] = new Object[]{
articles.get(iter).getName(), articles.get(iter).getDescription(), articles.get(iter).getLabel(), articles.get(iter).getQuantity(),
articles.get(iter).getRating(), add(createStarRankSlider(articles.get(iter).getId_article()))
};
}
TableModel model = new DefaultTableModel(new String[]{"name", "description", "label", "quantity", "rating", "rate"}, rows);
Table table = new Table(model);
add(table);
getToolbar().addMaterialCommandToLeftBar("", FontImage.MATERIAL_ARROW_BACK, e -> previous.showBack());
}
});
and this is the function for the star rank creation
private Slider createStarRankSlider(int id) {
Slider starRank = new Slider();
starRank.setEditable(true);
starRank.setMinValue(0);
starRank.setMaxValue(10);
int fontSize = Display.getInstance().convertToPixels(3);
Font fnt = Font.createTrueTypeFont("Handlee", "Handlee-Regular.ttf").
derive(fontSize, Font.STYLE_PLAIN);
Style s = new Style(0xffff33, 0, fnt, (byte) 0);
Image fullStar = FontImage.createMaterial(FontImage.MATERIAL_STAR, s).toImage();
s.setOpacity(100);
s.setFgColor(0);
Image emptyStar = FontImage.createMaterial(FontImage.MATERIAL_STAR, s).toImage();
initStarRankStyle(starRank.getSliderEmptySelectedStyle(), emptyStar);
initStarRankStyle(starRank.getSliderEmptyUnselectedStyle(), emptyStar);
initStarRankStyle(starRank.getSliderFullSelectedStyle(), fullStar);
initStarRankStyle(starRank.getSliderFullUnselectedStyle(), fullStar);
starRank.setPreferredSize(new Dimension(fullStar.getWidth() * 5, fullStar.getHeight()));
starRank.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
ServiceTask.getInstance().UpdateRank(id,starRank.getIncrements());
}
});
return starRank;
}
You didn't include the code for the initStarRankStyle but it's pretty obvious what you did here. You just relied on the behavior of the container. Table derives Container so it includes all of its methods e.g. add(Component).
But these methods won't work correctly since a table fetches its data from the model and invokes add internally. So you're logic is conflicting with the table.
You need to derive table and define how you want that data to be rendered. You can do that by overriding the method protected Component createCell(Object value, int row, int column, boolean editable) as explained here.

How to properly delete row in JTable with double click?

Good afternoon guys, i'm trying to learn java programming and then i'm encountering some problem that i don't know why with my code when I'm learning about JTable.
So, what I'm trying to do is when i double clicked the row in JTable named TableGejala, the row that i double clicked will transfered into the other JTable named TableAturan and after that the row that i double clicked in TableGejala will be removed. For the part of transferring row from TableGejala to TableAturan successfully transferred when i double clicked the row, but it doesn't delete the correct row in TableGejala. Instead of deleting the row that i clicked, it delete the row below it.
For more details, this is my code to create TableGejala :
private void getTableGejala() {
while(tabel2.getRowCount() > 0){
for(int i=0;i < tabel2.getRowCount();i++){
tabel2.removeRow(i);
}
}
tabel2.addColumn("ID Gejala");
tabel2.addColumn("Nama Gejala");
TabelGejala.setModel(tabel2);
TabelGejala.setAutoResizeMode(TabelGejala.AUTO_RESIZE_ALL_COLUMNS);
}
And then this is my code to get data for my table from MySQL :
private void loadDataGejala(Boolean baru){
tabel2.getDataVector().removeAllElements();
try {
java.sql.Connection konek = (Connection) Koneksi.KoneksiDB.getConnection();
java.sql.Statement konek_statement = konek.createStatement();
String query_bukaTabel = "";
if(baru){
query_bukaTabel = "select id_gejala,nama_gejala from gejala";
}
else{
String idPkt = FieldID.getText();
query_bukaTabel = "select gejala.id_gejala,gejala.nama_gejala from gejala where gejala.id_gejala not in(select id_gejala from aturan2 where id_penyakit='"+idPkt+"')";
}
java.sql.ResultSet line_result = konek_statement.executeQuery(query_bukaTabel);
while (line_result.next()) {
Object[] getO = new Object[2];
getO[0] = line_result.getString("id_gejala");
getO[1] = line_result.getString("nama_gejala");
tabel2.addRow(getO);
}
line_result.close();
konek_statement.close();
}catch (Exception e) {}
}
This is my code to transfer the row and delete the row :
private void TabelGejalaMousePressed(java.awt.event.MouseEvent evt) {
if (evt.getClickCount()>=2){
int col = 0;
int row = 0;
row = TabelGejala.rowAtPoint(evt.getPoint());
col = TabelGejala.columnAtPoint(evt.getPoint());
String col1 = (String)TabelGejala.getValueAt(row, 0);
String col2 = (String)TabelGejala.getValueAt(row, 1);
DefaultTableModel model = (DefaultTableModel) TabelAturan.getModel();
DefaultTableModel old = (DefaultTableModel) TabelGejala.getModel();
old.removeRow(row);
model.addRow(new Object[]{col1, col2, 0});
TabelAturan.requestFocus();
TabelAturan.setRowSelectionInterval(TabelAturan.getRowCount()-1,TabelAturan.getRowCount()-1);
TabelAturan.editCellAt(TabelAturan.getRowCount()-1,2);
}
}
And this is the screenshot of my problem :
Before Double Clicked
After Double Clicked
Which part that makes my output get the wrong row to be deleted? please help me, and thank you in advance for any helps, even for reading my question :)
Firstly disable cell editable property in your first table(TabelGejala) to ensure proper deleting of row. I achieved this using the following code :-
//instance table model
DefaultTableModel tableModel = new DefaultTableModel(new Object[][]{},
new String[]{
"ID Gejala", "Nama Gejala"
}) {
#Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
};
TabelGejala.setModel(tableModel);
then use jtable.getselectedrow() and jtable.getselectedcolumn() to get values from table. after addition of desired values to second table, simply delete the selected row. here is the code, derived from your code :-
private void TabelGejalaMousePressed(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
if (evt.getClickCount() >= 2) {
DefaultTableModel model = (DefaultTableModel) TabelAturan.getModel();
DefaultTableModel old = (DefaultTableModel) TabelGejala.getModel();
model.addRow(new Object[]{TabelGejala.getValueAt(TabelGejala.getSelectedRow(), 0), TabelGejala.getValueAt(TabelGejala.getSelectedRow(), 1), 0});
old.removeRow(TabelGejala.getSelectedRow());
TabelAturan.requestFocus();
TabelAturan.setRowSelectionInterval(TabelAturan.getRowCount() - 1, TabelAturan.getRowCount() - 1);
TabelAturan.editCellAt(TabelAturan.getRowCount() - 1, 2);
}
}

Jtable Number Editor with "," separator rather than "."

I am a French guy and not new to Java.
In French, Doubles have "," separator rather than ".". So I have a JTable Cell with column class = Double, when I enter e.g 2.4 it is Ok. But when I enter 2,4 it blocks.
I used Locale.setDefault(Locale.FRENCH); but I have the same result :
Number
And as you can see in the image below, my application started with French locale :
System Locale
Is there any way to enter 2,4 rather than 2.4 ?
Sincerely.
Is there any way to enter 2,4 rather than 2.4 ?
Well there are several issues.
the default renderer will display the "." not the ",".
the default editor will display the ".", not the ","
the default editor doesn't recognize the "," as a valid character for a Double when you attempt to save the value to the TableModel
When you leave a cell the entered String must be converted to a Double. However, the Double.parseDouble(...) method does not recognize the "," even when the French Locale is used.
The default cell editor realizes the String can't be converted properly so the cell is highlighted with the red border to indicate an invalid value.
The solution below uses a custom editor to internally handle the conversion of the "," to "." before the String is parsed as a Double. It will also convert the "." to a "," so the value is displayed properly in the editor.
import java.awt.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class LocaleEditor extends DefaultCellEditor
{
private Object value;
public LocaleEditor()
{
super( new JTextField() );
((JTextField)getComponent()).setHorizontalAlignment(JTextField.RIGHT);
}
#Override
public Object getCellEditorValue()
{
return value;
}
#Override
public boolean stopCellEditing()
{
try
{
String editingValue = (String)super.getCellEditorValue();
// Don't allow user to enter "."
if (editingValue.contains("."))
{
JTextField textField = (JTextField)getComponent();
textField.setBorder(new LineBorder(Color.red));
return false;
}
// Replace local specific character
int offset = editingValue.lastIndexOf(",");
if (offset != -1)
{
StringBuilder sb = new StringBuilder(editingValue);
sb.setCharAt(offset, '.');
editingValue = sb.toString();
}
value = Double.parseDouble( editingValue );
}
catch(NumberFormatException exception)
{
JTextField textField = (JTextField)getComponent();
textField.setBorder(new LineBorder(Color.red));
return false;
}
return super.stopCellEditing();
}
#Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
Component c = super.getTableCellEditorComponent(table, value, isSelected, row, column);
JTextField textField = (JTextField)c;
textField.setBorder( new LineBorder(Color.BLACK) );
String text = textField.getText();
int offset = text.lastIndexOf(".");
// Display local specific character
if (offset != -1)
{
StringBuilder sb = new StringBuilder(text);
sb.setCharAt(offset, ',');
textField.setText( sb.toString() );
}
return c;
}
private static void createAndShowUI()
{
String[] columnNames = {"String", "Double", "Boolean"};
Object[][] data =
{
{"A", new Double(1), Boolean.TRUE },
{"B", new Double(2.25), Boolean.FALSE},
{"C", new Double(12.34), Boolean.TRUE },
{"D", new Double(1234.56), Boolean.FALSE}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
// Returning the Class of each column will allow different
// renderers and editors to be used based on Class
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;
}
};
JTable table = new JTable(model);
table.setRowHeight(20);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
// Use a custom renderer and editor
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
nf.setMinimumFractionDigits(2);
TableCellRenderer renderer = new NumberRenderer( nf );
table.setDefaultRenderer(Double.class, renderer);
TableCellEditor fce = new LocaleEditor();
table.setDefaultEditor(Double.class, fce);
JFrame frame = new JFrame("Table Five Character Editor");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( scrollPane );
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
The above code also uses code found in Table Format Renderers, which allows you to easily create a custom renderer for a given Locale. Just comment out the code if you don't want to use the renderer, but then the "." will be displayed in the table.
I recommend you to implement a custom data model using AbstractTableModel, then inside the method getValueAt(int row, int col) use NumberFormat as follows:
NumberFormat.getInstance(Locale.FRENCH).format(2.4);
If your application is only going to be used by French users, you can hardcode the default locale to French.
Locale.setDefault( Locale.FRENCH );
Alternatively, as a workaround, just set all columns to String (thus, all input will be accepted), and in DefaultTableModel->TableModelListener->tableChanged() format your String as you wish and parse it to Double afterwards with setValueAt().

Edit the cell value at a dynamic TableView?

Is it possible to edit a cell value in a dynamic TableView (dynamic rows and dynamic columns)?
All I found on the internet was some editable TextFields over the cells.
However, I want to edit the value in the table and then update my List with the new data.
I'm using IntelliJ IDEA 13.1.4 , JavaFX Scene Builder 2.0 and the newest JavaFX version.
Here is the code, where I create the dynamic rows and columns:
public List<String[]> jdata = new LinkedList<>(); //Here is the data
private TableView<String[]> sourceTable;
private ObservableList<String[]> srcData;
.
.
.
int clms;
public void showTable(Convert cnv) {
clms = cnv.getColums(); //number of the columns
for (int i = 0; i < clms; i++) {
TableColumn<String[], String> firstNameCol = new TableColumn<>("\tC"+(i+1)+" \t");
firstNameCol.setMinWidth(20);
int index = i ;
firstNameCol.setCellValueFactory(cellData -> {
String[] rowData = cellData.getValue();
if (index >= rowData.length) {
return new ReadOnlyStringWrapper("");
} else {
String cellValue = rowData[index];
return new ReadOnlyStringWrapper(cellValue);
}
});
sourceTable.getColumns().add(firstNameCol);
}
srcData = FXCollections.observableList(jdata);
sourceTable.getItems().addAll(srcData);
}
Just do
firstNameCol.setCellFactory(TextFieldTableCell.forTableColumn());
firstNameCol.setOnEditCommit(event -> {
String[] row = event.getRowValue();
row[index] = event.getNewValue();
});
This code will make the firstNameCol column editable. When you click on any cell under this column, you will get a TextField where you can enter value. When you hit enter, the value gets saved in the table.
UPDATE:
Let us say you have created a model class for your Table, and lets assume its name is TestCasesModel, this is how the above code would look.
firstNameCol.setCellFactory(TextFieldTableCell.<TestCasesModel>forTableColumn());
firstNameCol.setOnEditCommit(
new EventHandler<CellEditEvent<TestCasesModel, String>>() {
#Override
public void handle(CellEditEvent<TestCasesModel, String> t) {
((TestCasesModel) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setObjectName(t.getNewValue());
}
}
);
It is always a good practice to work with POJO classes instead of String arrays.
CellEditEvent must be imported like this:
import javafx.scene.control.TableColumn.CellEditEvent;

How to display records in a JTable from an arraylist .TXT file in java MVC?

Currently, this is my main screen:
()
I have 2 files: “patient.txt” and “treatment.txt” which hold records of multiple patients and treatments.
What I’m trying to do is to display all of those records in a nice JTable whenever I click “Display Treatments” or “Display Patients”, in a screen like so:
I am using an MVC model for this Hospital Management System (with HMSGUIModel.java, HMSGUIView.java, HMSGUIController.java, HMSGUIInterface.java files), and add records using the following code:
FileWriter tfw = new FileWriter(file.getAbsoluteFile(), true);
BufferedWriter tbw = new BufferedWriter(tfw);
tbw.write(this.view.gettNumber() + "," + this.view.gettName() + "," + this.view.gettDoctor() + "," + this.view.gettRoom());
tbw.newLine();
tbw.flush();
JOptionPane.showMessageDialog(null, "Successfully added treatment!"); }
Please help on how I can add a reader as well, to display all the records from the text file to a table?
Many thanks in advance!!
Keeping in line with your MVC, you could create a TableModel which knew how to read a give patient record.
Personally though, I'd prefer to separate the management of the patient data from the view, so the view didn't care about where the data came from.
To this end, I would start by creating a Patient object and a Treatment object, these would hold the data in a self contained entity, making the management simpler...
You would need to read this data in and parse the results...
List<Treatment> treatments = new ArrayList<Treatment>(25);
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String text = null;
while ((text = br.readline()) != null) {
String parts[] = text.split(",");
Treatmeant treament = new Treatment(parts[0],
parts[1],
parts[2],
parts[3]);
treatments.add(treament);
}
} // Handle exception as required...
I'd wrap this into a readTreatments method in some utility class to make it easier to use...
Around about here, I'd be considering using a stand alone database or even an XML document, but that's just me.
Once you have this, you can design a TableModel to support it...
public class TreatmentTableModel extends AbstractTableModel {
protected static final String[] COUMN_NAMES = {
"Treatment-Number",
"Treatment-Name",
"Doctor-in-charge",
"Room-No",
};
protected static final Class[] COLUMN_CLASSES = new Class[]{
Integer.class,
String.class,
Doctor.class,
Integer.class,
};
private List<Treatment> treatments;
public TreatmentTableModel() {
this.treatments = new ArrayList<>();
}
public TreatmentTableModel(List<Treatment> treatments) {
this.treatments = new ArrayList<>(treatments);
}
#Override
public int getRowCount() {
return treatments.size();
}
#Override
public int getColumnCount() {
return 4;
}
#Override
public String getColumnName(int column) {
return COUMN_NAMES[column];
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return COLUMN_CLASSES[columnIndex];
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Treatment treatment = treatments.get(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = treatment.getNumber();
break;
case 1:
value = treatment.getName();
break;
case 2:
value = treatment.getDoctor();
break;
case 3:
value = treatment.getRoomNumber();
break;
}
return value;
}
}
Then you simply apply it to what ever JTable you need...
private JTable treatments;
//...
treatments = new JTable(new TreatmentTableModel());
add(new JScrollPane(treatments));
Then, we you need to, you would load the List of Treatments and apply it to the table...
File file = new File("...");
treatments.setModel(new TreatmentTableModel(TreatmentUtilities.readTreatments(file)));
Depending on your needs for the table, you can look at using the DefaultTableModel and populating your data using that model. The downside to that is, you may want special capability from your table, like not being able to edit cells, store more than strings, etc... in which case you might look in to extending AbstractTableModel and defining your own behavior for the model.
A simple thing to do would be to start with the default model and expand on that.
String[] myColumns = {"Treatment-Number","Treatment-Name", "Doctor-in-charge", "Room-No"};
// init a model with no data and the specified column names
DefaultTableModel myModel = new DefaultTableModel(new Object[myList.size()][4](), myColumns);
// assuming you have a list of lists...
int i = 0;
int j = 0;
for (ArrayList<Object> list : myList) {
for ( Object o : list ) {
myModel.setValueAt(o, i, j); // set the value at cell i,j to o
j++;
}
i++;
}
JTable myTable = new JTable(myModel); // make a new table with the specified data model
// ... do other stuff with the table
If you want to access the table data, you use myTable.getModel() and update the data. This will automatically update the view of the table (completing the MVC connection)
Look here for more info on using tables.

Categories