how to make my JTable refresh after adding a new row - java

After I add a new row to a JTable. The information wrote goes to the txt file, but my JTable doesn't shows the last raw. But if I close the program, and run it again, the information it's in the table. So, is there a way to refresh the data in the JTable without closing the application and running it again?
String[] columns = {"nume", "compozitie", "indicatii", "contraindicatii", "administrare", "pret", "compensabil", "stoc"};
Object[][] data = null;
try {
File file = new File("medicamente.txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
data = new Object[100][];
String line;
int numLines = 0;
while ((line = bufferedReader.readLine()) != null) {
data[numLines] = line.split(",");
numLines++;
}
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
TableModel model = new DefaultTableModel(data, columns) {
#Override
public Class getColumnClass(int column) {
Class returnValue;
if ((column >= 0) && (column < getColumnCount())) {
returnValue = getValueAt(0, column).getClass();
} else {
returnValue = Object.class;
}
return returnValue;
}
};
JTable table = new JTable(model) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(1000, 500));
mainPanel.add(scrollPane);
scrollPane.setBounds(0, 240, 995, 510);
final JTextField filterText = new JTextField(null);
mainPanel.add(filterText);
filterText.setBounds(0, 750, 850, 25);
JButton button = new JButton("Filter");
mainPanel.add(button);
button.setBounds(850, 750, 150, 25);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String text = filterText.getText();
if (text.length() == 0) {
sorter.setRowFilter(null);
// model.fireTableDataChanged();
} else {
sorter.setRowFilter(RowFilter.regexFilter(text));
}
}
});

It looks like what you think is that when the file updates, so should the JTable. It doesn't work like that. What you need to do is add a row to the TableModel. A disadvantage in your case is this
TableModel model = new DefaultTableModel( data, columns)
You're using the TableModel interface, which has very limited methods you can use. Instead do this
DefaultTableModel model = new DefaultTableModel( data, columns)
Then you can use one of these methods from DefaultTableModel
public void addRow(Object[] rowData) - Adds a row to the end of the model. The new row will contain null values unless rowData is specified. Notification of the row being added will be generated.
public void addRow(Vector rowData) - Adds a row to the end of the model. The new row will contain null values unless rowData is specified. Notification of the row being added will be generated.
So when you want to add a row, you can gather your data into an array, addRow(..) then the table will get automatically update for you.
Object[] row = { data1, data2, data2, data4, data5 };
DefaultTableModel model = (DefaultTableModel)table.getModel();
model.addRow(row);
Also it looks to me like your JTable is locally scoped. You may want to give it a global, class member scope, so you can access it from where ever you need to.

you must add your data to the model of jtable and then add the model to jtable and it will be refreshed , but before that you have to define a model .

Use this code.
private void resetListData() throws ClassNotFoundException, SQLException
{
Connection cne = null;
try {
// create connection in this line as per your database like I used sqlite. so my connection string is as follow
Class.forName("org.sqlite.JDBC");
cne = DriverManager.getConnection("jdbc:sqlite:table.sqlite");
cne.setAutoCommit(false);
PreparedStatement psd = (PreparedStatement) cne.prepareStatement("Select * from table");
psd.execute();
ResultSet r = psd.getResultSet();
ResultSetMetaData rsmd = r.getMetaData();
int count = rsmd.getColumnCount();
String[] meta = new String[count];
for (int i = 0; i < count; i++)
{
String name = rsmd.getColumnName(i + 1);
meta[i] = name;
//System.out.println(name);
}
model = new DefaultTableModel(new Object[][]{}, new String[]{"name", "address"});
jTable1.setModel(model);
while (r.next())
{
Object[] row = new Object[count];
for (int i = 1; i <= count; ++i)
{
row[i - 1] = r.getString(i); // Or even rs.getObject()
}
model.addRow(row);
}
cne.close();
} catch (ClassNotFoundException | SQLException e) {
}
}
create connection and query as per your need.. my code add one row at the end of Jtable. My code directly working with your database..
Thanks..

by the way why you're using TableRowSorter in your code , why you don't use just the jtable and defaultmodel directly

I recently had the same problem and the solution was to call
model.fireTableDataChanged();
right after adding the new row to the model.
My issue was the following: I had a table on which I allowed sorting. Without clicking the column headers so that the rows would sort accordingly, I was able to add data to the model and see the changes in the table by calling table.revalidate(); However, if, at any time, I clicked the column headers, any row added afterwards wouldn't be shown, although the model data was updating properly. By only calling model.fireTableDataChanged(); after adding the data to the model, it works as a charm.

Related

Displaying images from MySQL database on a single column of JTable

I'm trying to display images retrieve from MySQL database of blob datatype. Could not figure out what is the problem that causes the image column to display data like this [B#29b8e4f7 instead of image icon.
DefaultTableModel model = new DefaultTableModel(new Object[]{
"image", "item_name", "quantity","price", "category", "color", "size"}, 0){
#Override
public Class<?> getColumnClass(int column) {
switch(column){
case 0: return ImageIcon.class;
default: return String.class;
}
}
};
myTable.setModel(model);
...
ResultSet rs = database.getRS();
int columns = rs.getMetaData().getColumnCount();
while(rs.next()){
Object[] row = new Object[columns];
for(int i = 1; i <= columns; i++){
row[i-1] = rs.getObject(i);
}
DefaultTableModel defmodel = (DefaultTableModel) tableItem.getModel();
defmodel.insertRow(rs.getRow()-1, row);
}
Since you used preparedstatement.setBlob(1, InputStream); to store the image, I have to assume that you stored the physical image file/format and not just the pixel data.
You need to read back this image format and convert to a supported image format for Swing/Java.
Start by getting a Blob reference to the database field...
Blob blob = rs.getBlob(1);
Once you have a Blob, you can use it's binary InputStream and read the data...
BufferedImage image = null;
try (InputStream is = blob.getBinaryStream()) {
image = ImageIO.read(is);
} catch (IOException exp) {
exp.printStackTrace();
}
Now, you can make it an ImageIcon using new ImageIcon(image) and put this within your table model...

List of file names in a table

I want to create a Swing gui where when I click browse I should get a text field giving the directory's path and a table of all the files in that directory.
I was able to get the first part(i.e. path). Can somebody help me in getting the files in a table?
I tried this:
public void jButton1ActionPerformed(ActionEvent e) {
JFileChooser filesave = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"TEXT File", ".txt", "text");
filesave.setFileFilter(filter);
int returnVal = filesave.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
try {
File file = filesave.getSelectedFile();
PrintWriter os = new PrintWriter(file + ".txt");
for (int row = 0; row < jTable1.getRowCount(); row++) {
for (int col = 0; col < jTable1.getColumnCount(); col++) {
os.print(jTable1.getColumnName(col));
os.print(": ");
os.println(jTable1.getValueAt(row, col));
}
}
os.close();
System.out.println("Done!");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
Well, nothing is added to the table because you didn't add anything to the table, no surprise here. If you ask me, some information is missing, but the normal way to achive this is...
create a TableModel (by extending AbstractTableModel)
set it in the JTable
when your button is clicked, update the TableModel, which should notify the listeners
Bingo, your table is updated
You can use a DefaultTableModel for that, no problem here. Search for it and you'll find enough tutorials go get by.

ResultSet to Excel (*.xlsx) Table Using Apache POI

I am trying to write ResultSet to Excel (*.xlsx) Table using Apache Poi.
Invalid Table Object Error in Office Excel
However, even though it writes the Excel file without any error, when I try to open it in Office Excel 2013, it shows an error and removes the table object to give only plain data view.
Here is the rough Sample Code using this example:
public static void writeExcel(ResultSet rs, int sqliteRowCount, String dir) {
System.out.println("Writing Excel(*.xlsx) File...");
XSSFWorkbook workbook = null;
try {
if (rs != null) {
// Get ResultSet MetaData
ResultSetMetaData rsmd = rs.getMetaData();
// Number of columns
int numColumns = rsmd.getColumnCount();
// Number of rows
// + 1 for headers
int numRows = sqliteRowCount + 1;
workbook = new XSSFWorkbook();
// Create Excel Table
XSSFSheet sheet = workbook.createSheet("Text");
XSSFTable table = sheet.createTable();
table.setDisplayName("Test");
CTTable cttable;
cttable = table.getCTTable();
// Style configurations
CTTableStyleInfo style = cttable.addNewTableStyleInfo();
style.setName("TableStyleMedium16");
style.setShowColumnStripes(false);
style.setShowRowStripes(true);
// Set Table Span Area
AreaReference reference = new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1));
cttable.setRef(reference.formatAsString());
cttable.setId(1);
cttable.setName("Test");
cttable.setDisplayName("Test");
cttable.setTotalsRowCount(numRows);
cttable.setTotalsRowShown(false);
// Create Columns
CTTableColumns columns = cttable.addNewTableColumns();
columns.setCount(numColumns);
// Create Column, Row, Cell Objects
CTTableColumn column;
XSSFRow row;
// Add Header and Columns
XSSFRow headerRow = sheet.createRow(0);
for (int i = 0; i < numColumns; i++) {
column = columns.addNewTableColumn();
column.setName("Column" + (i + 1));
column.setId(i + 1);
headerRow.createCell(i).setCellValue(rsmd.getColumnLabel(i + 1));
}
// Write each row from ResultSet
int rowNumber = 1;
while (rs.next()) {
row = sheet.createRow(rowNumber);
for (int y = 0; y < numColumns; y++) {
row.createCell(y).setCellValue(rs.getString(y + 1));
}
rowNumber++;
}
// Set AutoFilter
CTAutoFilter fltr = CTAutoFilter.Factory.newInstance();
fltr.setRef((new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1))).formatAsString());
cttable.setAutoFilter(fltr);
// sheet.setAutoFilter(CellRangeAddress.valueOf((new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1))).formatAsString()));
// Freeze Pan
sheet.createFreezePane(0, 1, 0, 2);
}
} catch (SQLException ex) {
System.out.println("SQL Error while writing Excel file!");
} finally {
try {
// Let's write the excel file now
if (workbook != null) {
String excelDir = dir + File.separator + "workbook.xlsx";
try (final FileOutputStream out = new FileOutputStream(excelDir)) {
workbook.write(out);
}
}
} catch (IOException ex) {
System.out.println("IO Error while writing Excel summary file!");
}
}
}
I know something is wrong with my code, but can't figure it out.
Any idea, why this is happening, where would be potential mistake in my code.
Update 1:
Table XML file in Excel archive if created using Apache POI
<?xml version="1.0" encoding="UTF-8"?>
<table displayName="Test" ref="A1:B881" id="1" name="Test" totalsRowCount="881" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" totalsRowShown="0"><autoFilter ref="A1:B881"/><tableColumns count="2"><tableColumn name="ID" id="1"/><tableColumn name="Name" id="2"/><tableStyleInfo name="TableStyleMedium2" showColumnStripes="true" showRowStripes="true"/></table>
Table XML file in Excel archive if table created manually
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<table xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" id="1" name="Table1" displayName="Table1" ref="A1:B881" totalsRowShown="0"><autoFilter ref="A1:B881"/><tableColumns count="2"><tableColumn id="1" name="ID"/><tableColumn id="2" name="Name"/></tableColumns><tableStyleInfo name="TableStyleLight9" showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0"/></table>
In addition, if I open the Excel archive, it does not have a theme folder in the one created by Apache POI but it is present in the one create manually in Office Excel. Strange.
Update 2:
Sample executable code (Using Netbeans):
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package apachepoi_exceltest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumns;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyleInfo;
/**
*
*/
public class ApachePOI_ExcelTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
String outputDir = "Your Local Directory Here";
// TODO code application logic here
HashMap<String, String> dataMap = new HashMap<>();
dataMap.put("ID 1", "Dummy Name 1");
dataMap.put("ID 2", "Dummy Name 2");
dataMap.put("ID 3", "Dummy Name 3");
dataMap.put("ID 4", "Dummy Name 4");
writeExcel(dataMap, outputDir);
}
private static void writeExcel(HashMap<String, String> dataMap, String outputDir) {
System.out.println("Writing Excel(*.xlsx) Summary File...");
XSSFWorkbook workbook = null;
try {
// Number of columns
int numColumns = 2; // ID and Name
// Number of rows
int numRows = dataMap.size() + 1; // +1 for header
// Create Workbook
workbook = new XSSFWorkbook();
// Create Excel Table
XSSFSheet sheet = workbook.createSheet("Summary");
XSSFTable table = sheet.createTable();
table.setDisplayName("Test");
CTTable cttable;
cttable = table.getCTTable();
// Style configurations
CTTableStyleInfo style = cttable.addNewTableStyleInfo();
style.setName("TableStyleMedium16");
style.setShowColumnStripes(false);
style.setShowRowStripes(true);
// Set Tabel Span Area
AreaReference reference = new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1));
cttable.setRef(reference.formatAsString());
cttable.setId(1);
cttable.setName("Test");
cttable.setDisplayName("Test");
cttable.setTotalsRowCount(numRows);
cttable.setTotalsRowShown(false);
// Create Columns
CTTableColumns columns = cttable.addNewTableColumns();
columns.setCount(numColumns);
// Create Column, Row, Cell Objects
CTTableColumn column;
XSSFRow row;
// Add ID Header
column = columns.addNewTableColumn();
column.setName("Column" + (1));
column.setId(1);
// Add Name Header
column = columns.addNewTableColumn();
column.setName("Column" + (1));
column.setId(1);
// Add Header Row
XSSFRow headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("ID");
headerRow.createCell(1).setCellValue("Name");
int rowNumber = 1;
for (Map.Entry<String, String> entry : dataMap.entrySet()) {
String id = entry.getKey();
String name = entry.getValue();
row = sheet.createRow(rowNumber);
row.createCell(0).setCellValue(id);
row.createCell(1).setCellValue(name);
rowNumber++;
}
// Set Filter (Below three lines code somehow not working in this example, so setting AutoFilter to WorkSheet)
// CTAutoFilter fltr = CTAutoFilter.Factory.newInstance();
// fltr.setRef((new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1))).formatAsString());
// cttable.setAutoFilter(fltr);
sheet.setAutoFilter(CellRangeAddress.valueOf((new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1))).formatAsString()));
// Freeze First Row as header Row
sheet.createFreezePane(0, 1, 0, 2);
} catch (Exception ex) {
System.out.println("Error while writing Excel summary file!");
} finally {
try {
// Lets write the Excel File Now
if (workbook != null) {
String excelDir = outputDir + File.separator + "workbook.xlsx";
try (final FileOutputStream out = new FileOutputStream(excelDir)) {
workbook.write(out);
}
}
} catch (IOException ex) {
System.out.println("IO Error while writing Excel summary file!");
}
}
}
}
Libraries Used:
ooxml-schemas-1.1.jar
poi-3.11-beta2-20140822.jar
poi-ooxml-3.11-beta2-20140822.jar
xmlbeans-2.6.0.jar
What's wrong with your code is a presence of a single line.
"cttable.setTotalsRowCount(numRows);"
Remove it and everything will work.
If in doubt, compare the XML definitions of some working table created manually in Excel and the definitions created with Apache POI
I had the same issue.
Digging deeply, I found that for some table XML data in the XLSX package, Excel is changing a single > to > after performing the repair. The XML from POI makes sense (use < and > to surround XML elements) so I have no idea why Microsoft chooses to break it.
If its the same case for you, I'd not worry too much about it.
If you want to see if you have this particular difference:
Create XLSX with POI
Repair XLSX with Excel and save to new file
Open both files with ZIP editor (e.g. 7Zip)
Find xl/tables/table1.xml
Export both XML files (POI and Excel-repaired)
Diff the files
You have not created your table correctly.
Check:
Did you create header columns in cttable?
Did you create the same header columns through cell.setCellValue?
Remove empty first header column(POI BUG) at the end
CTTable().getTableColumns().removeTableColumn(0);
Put debug into XSSFTable.class, method updateHeaders().
If your table is not created properly, then
XSSFRow row = sheet.getRow(headerRow);
will be NULL in
/**
* Synchronize table headers with cell values in the parent sheet.
* Headers <em>must</em> be in sync, otherwise Excel will display a
* "Found unreadable content" message on startup.
*/
#SuppressWarnings("deprecation")
public void updateHeaders(){
XSSFSheet sheet = (XSSFSheet)getParent();
CellReference ref = getStartCellReference();
if(ref == null) return;
int headerRow = ref.getRow();
int firstHeaderColumn = ref.getCol();
XSSFRow row = sheet.getRow(headerRow);
if (row != null && row.getCTRow().validate()) {
int cellnum = firstHeaderColumn;
for (CTTableColumn col : getCTTable().getTableColumns().getTableColumnArray()) {
XSSFCell cell = row.getCell(cellnum);
if (cell != null) {
col.setName(cell.getStringCellValue());
}
cellnum++;
}
}
}

Java Vector Data Grouping - Relevant Code

I am currently importing excel data into a vector in Java, however now i want to group that data so that similar data with lets say the same id is grouped (in my case matter number).
here is my relevant import code:
public class FileChooser extends javax.swing.JFrame {
private String path ="";
public FileChooser() {
initComponents();
}
private static Vector importExcelSheet(String fileName)
{
Vector cellVectorHolder = new Vector();
try
{
Workbook workBook = WorkbookFactory.create(new FileInputStream(fileName));
Sheet sheet = workBook.getSheetAt(0);
Iterator rowIter = sheet.rowIterator();
while(rowIter.hasNext())
{
XSSFRow row = (XSSFRow) rowIter.next();
Iterator cellIter = row.cellIterator();
Vector cellStoreVector=new Vector();
while(cellIter.hasNext())
{
XSSFCell cell = (XSSFCell) cellIter.next();
cellStoreVector.addElement(cell);
}
cellVectorHolder.addElement(cellStoreVector);
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
return cellVectorHolder;
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
int option = chooser.showOpenDialog(this); // parentComponent must a component like JFrame, JDialog...
if (option == JFileChooser.APPROVE_OPTION) {
File selectedFile = chooser.getSelectedFile();
path = selectedFile.getAbsolutePath();
jTextField1.setText(path);
}
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
Vector dataHolder = importExcelSheet(path);
Enumeration e = dataHolder.elements(); // get all vector elements
while (e.hasMoreElements()) { // step through all vector elements
Object obj = e.nextElement();
System.out.println(obj);
}// TODO add your handling code here:
}
This selects the excel spreadsheet and extracts all the values to a vector and prints them out, what i want to know is, can i group the same data in the vector and output that data instead of the whole thing.
So lets say i have a spreadsheet of cellphone contracts, and i want to select all the contracts of the Samsung galaxy s3 and not all the contracts, how would i do that?
You're suffering from Object Denial :-)
As I read your code, you have a Vector of rows containing a Vector of columns, is that correct? And if so, does one of the columns contain the phone model?
Anyways, you could be doing something along the lines of:
// TODO seriously consider something else than Vector to store the rows and columns!
Map<String,Vector> map = new HashMap<String,Vector>()
while(rowIter.hasNext())
{
boolean isFirst = false;
String phoneModel = "";
while( cellIter.hasNext() )
{
XSSFCell cell = (XSSFCell) cellIter.next();
if ( isFirst ) { phoneModel = cell.getTheTextContentOrWhatever(); isFirst = false; }
cellStoreVector.addElement(cell);
}
if ( map.get( phoneModel ) == null ) { map.put( phoneModel , new Vector() ); }
map.get( phoneModel ).add( cellStoreVector );
}
Then, the map keys will be your phones, and the value will be the Vector with the rows for that phone. It is not what I consider pretty code and needs works in terms of error handling, but you can work from there.
Cheers,

Java JTable data loading

so i have a large cardlayout with one panel as a JTable:
tbm = new DefaultTableModel();
tbm.addColumn("Account Number");
tbm.addColumn("PIN");
tbm.addColumn("Access Level");
tbm.addColumn("Balance");
table = new JTable(tbm);
JScrollPane scrollPane = new JScrollPane(table);
under actionPerformed, I am trying to load some data into the table as follows:
else if(event.getSource() == listallButton) {
String query = "SELECT * FROM ATM";
String delimiter = ",";
String input = "go";
int count=0;
al = new ArrayList<String>();
try {
communicationObject = new DataObject();
communicationObject.setMessage(query);
Socket socketToServer = new Socket("sunlab32.njit.edu",31414);
ObjectOutputStream myOutputStream = new ObjectOutputStream(socketToServer.getOutputStream());
ObjectInputStream myInputStream = new ObjectInputStream(socketToServer.getInputStream());
myOutputStream.writeObject(communicationObject);
communicationObject = (DataObject)myInputStream.readObject();
input = communicationObject.getMessage();
if (input != "stop") {
al.add(input);
data[count] = input;
count++; }
for (int i=0;i<data.length;i++) {
row = data[i];
temp = row.split(delimiter);
tbm.addRow(new String[] {temp[0],temp[1],temp[2],temp[3]}); }
tbm.fireTableDataChanged();
table.repaint();
now my problem is that the table does not get repainted after all the rows are loaded...any suggestions?
tbm.addModel should be firing table changed event, so tbm.fireTableDataChanged is not necessary.
You can try doing this though to force it to paint itself after you have added all the rows.
table.setModel(tbm);
Off topic:
Swing is a single threaded event model, which means the task that you are carrying out will block UI update.
I would suggest you move your data loading to SwingWorker and once you are done with your changes push the data on the UI. Take a look at this tutorial
There is no need to call tbm.fireTableDataChanged();. The model itself will notify the table in response to addRow(). And if the table and model are connected correctly the table will refresh itself.
You may find this example helpful, it demos use of DefaultTableModel.
As this code is not visible, make sure the table and scroll pane are setup correctly. Also, make sure your query actually returns data.

Categories

Resources