PDA

View Full Version : [JAVA] Jtable e refresh


andreamarz
22-04-2012, 22:46
Salve a tutti,
purtroppo ho qualche problema con il refresh delle jtalbe in tempo reale o per meglio dire dopo la pressione di un bottone.

Ho cominciato da nemmeno un mese e mi trovo un po' spaesato nel leggere le varie guide qualcuno potrebbe darmi una mano dandomi delle dritte, non mi serve necessariamente il codice, se c'è schifo non mi fa, ma una luce per venir fuori dal tunnel...

Vi posto sotto qualche stralcio di codice e spero qualcuno possa aiutarmi

Test (classe principale):
package videom;

import java.sql.SQLException;

public class VideoM {

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
GUI frame = new GUI();
frame.Crea();
}
}

GUI
package test;

import java.awt.Container;
import java.awt.GridLayout;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

public class GUI extends JFrame {

public JTextField JTextFieldAggiungi;
public static JPanel panel2;

public void Crea() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
Container c = getContentPane();

setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
[...]
panel2 = new JPanel();
panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
instance = new Elenco();
panel2.add(instance.Elenco());
// Area di testo per inserire il punteggio
JTextFieldAggiungi = new JTextField(20);
JTextFieldAggiungi.setEditable(true);
panel3.add(JTextFieldAggiungi);

// Bottone inserimento punteggio
JButton buttonAggiungi = new JButton("Aggiungi");
buttonAggiungi.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
try {
buttonAggiungiMouseClicked(evt);
} catch (ClassNotFoundException ex) {
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (SQLException ex) {
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
panel3.add(buttonAggiungi);
[...]
private void buttonAggiungiMouseClicked(java.awt.event.MouseEvent evt) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
Inserisci.insert(JTextFieldAggiungi.getText());
}

Elenco (file con l'SQL)
class Elenco extends JFrame{
public static TableModel tableModel;
public static JTable table;
private JScrollPane scrollPane;

public JScrollPane Elenco() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {

ArrayList<Punti> listaPunti = new ArrayList<Punti>();
Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
Connection conn = DriverManager.getConnection("jdbc:derby://localhost:1527/punti;user=andrea;password=andrea");
final java.sql.Statement stmt = conn.createStatement();
ResultSet results = stmt.executeQuery("SELECT * FROM punti");

while(results.next())
{
int a = results.getInt(1);
int b = results.getInt(2);
String c = results.getString(3);
String e = "1";
boolean d;
if (c.equals(e)) {
d = true;
} else {
d = false;
}
listaPunti.add(new Punti(a, b, d));
}

tableModel = new TableModel(listaPunti);
table = new JTable(tableModel);
scrollPane = new JScrollPane(table);

return scrollPane;
}
}

Ovviamente ci sono anche i file TableModel ed Inserisci ma non penso possano esservi utili al fine della risoluzione del problema.

A chiuque volesse darmi una mano gliene sarei grato

PGI-Bis
23-04-2012, 09:10
Mhhh... ok, tu cosa vorresti fare? Lo chiedo perchè nel codice trovo indizi contrastanti. Vuoi popolare una tabella di dati presti da un database alla pressione di un pulsante?

andreamarz
23-04-2012, 09:19
Scusa evidentemente mi sono spiegato male, la tabella viene visualizzata da subito poi vi è un bottone per inserire un punteggio (inserisce automaticamente id e un campo booleano e esplicitamente leggendo da una textarea il valore dei punti) alla pressione del bottone si dovrebbe inserire il nuovo record nel DB (e lo fa) e ridisegnarmi la tabella inserendo questa volta anche l'ultimo record.

Inserisci è questo:
public class Inserisci {
public static void insert (String stringaPunti) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {

Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
Connection conn = DriverManager.getConnection("jdbc:derby://localhost:1527/videom;user=andrea;password=andrea");
try (Statement stmt = conn.createStatement()) {
String sql2 = "SELECT * FROM PUNTI";
int count = 0;
ResultSet result2 = stmt.executeQuery(sql2);
while(result2.next())
{
count++;
}
count++;
String sql = "INSERT INTO PUNTI(ID, PUNTI, BOOL) VALUES (" + count + ", " + stringaPunti + ", '1')";
int result = stmt.executeUpdate(sql);
if (result > 0)
{
//popup
System.out.println("inserimento ok");
}
else
{
System.out.println("inserimento NON ok");
}
}
}
}

PGI-Bis
23-04-2012, 10:47
Se vuoi aggiungere una riga ad una JTable passi per il suo modello.

In linea generale se usi un tuo tipo di TableModel puoi dire al modello di aggiungere il dato nel modo che preferisci, l'unica cosa che devi necessariamente fare è dire alla JTable, dopo aver inserito i valori, che qualcosa è cambiato.

Se il modello è un sottotipo di AbstractTableModel invochi (nel codice del TableModel, dopo l'avvenuto inserimento) fireTableRowsInserted, con l'indice della riga appena inserita.

Se il modello è "solo" un TableModel allora devi passare per la lista di TableModelListeners e sparare, per ogni listener, un evento del tipo:

evento = TableModelEvent(source, 3, 6, ALL_COLUMNS, INSERT)

Questo, ripeto, lo fai nel codice del tuo TableModel.

andreamarz
23-04-2012, 11:05
Io da un esempio preso online ho fatto il tablemodel implementando anche un aggiungi punti:

TableModel:
class TableModel extends AbstractTableModel {
private ArrayList<Punti> listaPunti;

public TableModel(ArrayList<Punti> listaPunti) {
this.listaPunti= listaPunti;
}

[...]

public void setValueAt(Object value, int row, int column) {
Tickets p = listaTicket.get(row);
switch (column) {
case 0: p.setId((int) value); break;
case 1: p.setPunti((int) value); break;
case 2: p.setON((Boolean) value); break; // unboxing!
}
}

// Metodo "custom", non inerente a TableModel/AbstractTableModel
public void aggiungiTicket(Tickets p) {
listaTicket.add(p);
int row = listaTicket.size() - 1;
// IMPORTANTE, notifica l'aggiunta di una riga nel model
fireTableRowsInserted(row, row);
}
}

Pensa ci sono ancora i commenti dell'esempio... non l'ho nemmeno toccato quella parte di codice.

Per la cronaca ci sono parti dove viene usata la parola "ticket" al posto di "punti" è un errore perchè ci sono aprti di codice da em inutilizzate ma semplicemente commentate la variabile diciamo ufficiale è punti

andreamarz
23-04-2012, 13:00
Forse dico una cacchiata ma ho provato ad inserire nel metodo insert

Punti p = new Punti (count, Integer.parseInt( stringaPunti ), true);
TableModel.aggiungiPunti(p);

che come detto sopra è:
public void aggiungiPunti(Punti p) {
listaPunti .add(p);
int row = listaPunti .size() - 1;
// IMPORTANTE, notifica l'aggiunta di una riga nel model
fireTableRowsInserted(row, row);
}

il problema è che l'IDE mi dice che non sto usando un metodo statico, perfetto aggiungo dove serve static ma anche fireTableRowsInserted(row, row); andrebbe static a quanto dice netBeans ma come faccio?

Magari è pure una strada totalmente sbagliata e mi sto facendo dei problemi per nulla...

PGI-Bis
23-04-2012, 14:28
Come tentativo una sua logica ce l'avrebbe ma l'effetto non è quello che vorresti avere.

Per aggiungere un punto dovresti dire una cosa di questo tipo:

Punti p = new Punti (count, Integer.parseInt( stringaPunti ), true);
TableModel m = (TableModel) table.getModel();
m.aggiungiPunti(p);

Occhio che "TableModel" è un nome usato dalle librerie standard, per evitare confusione sarebbe meglio se tu chiamassi il tuo TableModel in un modo leggermente diverso (ad esempio PuntiTableModel). Altrimenti corri il rischio che l'IDE importi il nome javax.swing.table.TableModel al posto del tuo TableModel, col risultato di non permettere l'uso di nomi di campi/metodi che esistono nel tuo TableModel ma non in javax.swing.table.TableModel

Nota che devi sparare un evento anche nella tua ridefinizione del metodo setValueAt (fireTableCellUpdated) altrimenti la JTable non si aggiorna.

andreamarz
23-04-2012, 19:05
Allora al momento devo dire che FUNZIONA non ho testato a fondo la cosa ma in serata ci provo e poi posto la mia personale soluzione completa che magari potrebbe servire ad altri nella mia medesima situazione