JTable mit Buttons

quidnovi

Erfahrenes Mitglied
Hallo Ihr Wissenden :)

Ich befülle eine JTable mit Daten aus einer DB, was auch funktioniert.

Nun möchte ich für jeden Eintrag zwei Buttons hinzufügen, "Bearbeiten" und "Löschen".
Die jeweilgen Button haben einen direkten Bezug zur ID des Datensatzes.

Habe im Inet schon geforscht, allerdings sind die Ergebnisse - für einen Anfänger - recht "umfangreich" (ums mal so zu formulieren ;))

Nun die Frage(n) an Euch:
Welche Technologie soll ich benutzen um die Buttons in den Zeilen erscheinen zu lassen?
Wie verbinde ich diese mit der ID des jeweiligen Datensatzes?

Es wäre auch die Mölgichkeit, auf die Buttons zu verzichten, und in der Tabelle stattdessen einen verlinkten String "Bearbeiten" bzw. "Löschen" anzuzeigen, allerdings habe ich nur Verlinkungen ins Inet gefunden.

Tja...das wäre dann eigentlich alles...zumindest fällt mir momentan nix mehr ein - ist ja auch so schon genug ;)

Bitte helft mir, den richtigen Weg zu finden, danke

ps: Zur besseren Veranschaulichung habe ich eine Fotomontage hinzugefügt...so sollt's dann aussehen - und vor allem auch funktionieren

Kommissionssuche.png
 

melmager

Erfahrenes Mitglied
Es gehen beide Varianten:
Buttons macht man über Cellrender, sprich man erstellt eine eigen Classe die das Zeichnen einer zeile übernimmt.

oder

du reagierst auf ein mausklick - startest dann ein Popup Menu und fragst dann nach edit/ändern

das mal als grobe richtung wohin die reise gehen könnte

@HonniCilest es sind dann 2 Klicks in einer bestimmten Reihenfolge nötig - die Klickreihenfolge ist leider nicht gesteuert durch das programm was leider DAU unsicherer ist - z.B select reihe 3; dicker finger 2 klicks auf löschen = lösche eintrag 3 und dann den eintrag 4 weil der durch löschen zum eintrag 3 wird ...

ich würde über Popup mittels einem Dialog gehen, hat mehrere Vorteile:
du kannst den Datensatz nochmal anzeigen im Popup, die 3. Möglichkeit geben abbrechen
eventuell sogar schon mit den JDialog Popup das Ändern abfangen ...

soweit mal ne grobe richtung

zusatzidee: du machst ein tooltip "links löschen / rechts edit" und reagiest beim linksklick mit einem dialog löschen/abbruch oder rechtsklick mit dem edit / abbruch dialog
 
Zuletzt bearbeitet:

quidnovi

Erfahrenes Mitglied
Hi Ihr Beiden :)

thx für die Tips...nur habe ich mich nun anders entschieden...

Ich befülle jetzt eine JTable. Das funktioniert, auch mit update und delete.
Allerdings habe ich jetzt ein Problem, welches ich leider nicht zu lösen vermag - obwohl intensivster Netzsuche.

Eine Änderung oder löschen eines Datensatzes funktioniert, nur kann ich die JTable leider nicht refreshen.

Ich kann diese nur komplett entfernen:
Java:
((DefaultTableModel)table.getModel()).setNumRows(0);

Allerdings weiß ich dann nicht, wie ich die veränderten Daten aus der DB wieder in die JTable bringe.

Hier mal der recht umfangreiche Code:
Java:
// Btn Tabelle aktualisieren
		btnRefresh.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				
				
				// DB - Tabelle Kommissionen Tabellenbezeichnung und Daten auslesen
				Vector<String> columnNames = new Vector<String>();
				Vector<Vector<Object>> data = new Vector<Vector<Object>>();
				new Vector<Object>();
				new Vector<Object>();
				try {
					String sql = "SELECT * FROM KOMMISSIONEN";
					Statement stmt = DBData.connection.createStatement();
					ResultSet rs = stmt.executeQuery(sql);
					ResultSetMetaData rsmd = rs.getMetaData();
					int columns = rsmd.getColumnCount();
					for (int i = 1; i <= columns; i++) {
						columnNames.addElement(rsmd.getColumnName(i));
					}

					while (rs.next()) {
						Vector<Object> row = new Vector<Object>(columns);
						for (int i = 1; i <= columns; i++) {
							// row.addElement(rs.getObject(i)); // Original
							row.addElement(rs.getString("ID"));
							row.addElement(rs.getString("DATUM"));
							row.addElement(rs.getString("KOMMNR"));
							row.addElement(rs.getString("KOMMNAME"));
							row.addElement(rs.getString("STRASSE"));
							row.addElement(rs.getString("HAUSNR"));
							row.addElement(rs.getString("PLZ"));
							row.addElement(rs.getString("GEMEINDE"));
							row.addElement(rs.getString("TELNR"));
							row.addElement(rs.getString("BEMERKUNG1"));
							row.addElement(rs.getString("BEMERKUNG2"));
						}
						data.addElement(row);
					}
					rs.close();
					stmt.close();
				} catch (Exception ex) {
					System.out.println(ex);
				}
				
				//----------------------------------------------------------------------

				// DB - Ergebnisse in Tabelle fuellen
				final JTable table = new JTable(data, columnNames);
				JPanel panel = new JPanel();
				JScrollPane pane = new JScrollPane(table);
				
				pane.setPreferredSize(new Dimension(950, 200));
				
				// GBC table
				GridBagConstraints gbc_table = new GridBagConstraints();
				gbc_table.insets = new Insets(0, 0, 5, 0);
				gbc_table.gridheight = 1;
				gbc_table.gridwidth = 5;
				gbc_table.fill = GridBagConstraints.BOTH;
				gbc_table.gridx = 0;
				gbc_table.gridy = 12;
				
				table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
				table.setFont(new Font("Century Gothic", Font.PLAIN, 12));
				table.setEnabled(true);
				
				panel.setOpaque(false);
				pane.setOpaque(false);
				
				panel.add(pane);
				add(panel, gbc_table);
				/*
				 * TODO zellen sollten gesperrt sein
				 */
				
				//---------------------------------------------------------------------------------------
				
				// Zeilenumbruch der einzelnen Eintraege
				// http://www.tutorials.de/swing-java2d-3d-swt-jface/228280-zeilenumbruch-im-jtable-verzweiflung.html
				int str_length = 0; // variable zum setzen des grössten wertes
				TableModel model = table.getModel();
				for (int clmCnt = model.getColumnCount(), rowCnt = model.getRowCount(), i = 0; i < rowCnt; i++) {
					for (int j = 0; j < clmCnt; j++) {
						if (model.getValueAt(i, j) != null) {
							String value = model.getValueAt(i, j).toString();
							// Es werden ja alle spalten ausgelesen deswegen hole ich
							// mir
							// den den grössten wert
							if (value.length() >= str_length) {
								str_length = value.length();

							}
							// hier wird die grösste variable als zeilenhöhe gesetz bei
							// der aktuellen Spalte
							table.setRowHeight(i, str_length / 2 + 16);
						}

					}
					// Nach jeder Zeile muss die Höhe wieder zurückgesetzt werden
					str_length = 0;

				}

				// Spaltenbreite definieren
				table.getColumnModel().getColumn(0).setPreferredWidth(30); // ID
				table.getColumnModel().getColumn(1).setPreferredWidth(130); // Datum
				table.getColumnModel().getColumn(2).setPreferredWidth(70); // KommNr
				table.getColumnModel().getColumn(3).setPreferredWidth(70); // KommName
				table.getColumnModel().getColumn(4).setPreferredWidth(70); // Strasse
				table.getColumnModel().getColumn(5).setPreferredWidth(40); // HausNr
				table.getColumnModel().getColumn(6).setPreferredWidth(40); // PLZ
				table.getColumnModel().getColumn(7).setPreferredWidth(80); // Gemeinde
				table.getColumnModel().getColumn(8).setPreferredWidth(100); // TelNr
				table.getColumnModel().getColumn(9).setPreferredWidth(160); // Bem1
				table.getColumnModel().getColumn(10).setPreferredWidth(155);// Bem2
			}
			
		});

Wie kann ich ein refresh des Tables erreichen?

Bitte helft mir, ich bin nun schon echt lange dran und meine Nerven werden immer dünner :(

Aja...ein Bildchen habe ich zur besseren "Begreifung" dazugehängt ;)

AlleKommissionen.png
 
Zuletzt bearbeitet von einem Moderator:

quidnovi

Erfahrenes Mitglied
Schönen guten Morgen :)

aja...danke Melmager :)
leider weiß ich nicht, wie und wo ich das aufrufen soll :(

Das Beispiel "Eintrag löschen":
Java:
// Eintrag loeschen
		btnEintragLoeschen.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				try {
					Statement stmt = DBData.connection.createStatement();
					String delDBTable;
					delDBTable = "DELETE FROM KOMMISSIONEN WHERE ID = " + txtFldId.getText();
					stmt.execute(delDBTable);
					JOptionPane.showMessageDialog(null, "Eintrag entfernt");
					
					((AbstractTableModel) table.getModel()).fireTableDataChanged(); // das mag Eclipse nit
					(table.getModel()).fireTableDataChanged(); 						// das mag Eclipse ebenso nit
					
				} catch (Exception e1) {
					JOptionPane.showMessageDialog(null, e1);
				}
			}

Wenn ich Dich richtig verstanden habe, dann im try-Block nach:
Java:
stmt.execute(delDbTable);

Mit folgendem steht Eclipse aber auf dem Kriegsfuß (und ich ebenso...):
Java:
((AbstractTableModel) table.getModel()).fireTableDataChanged();
(table.getModel()).fireTableDataChanged();

Wie soll der Aufruf denn ausschauen?

Bitte um Hilfestellung, danke
lg
 

quidnovi

Erfahrenes Mitglied
Hab's mal so probiert...aber es will nicht:
Java:
// DB Eintraege aendern
		btnEintragAendern.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {

				try {
					Statement stmt = DBData.connection.createStatement();
					String updateDBTable;
					String where;
					updateDBTable = "UPDATE KOMMISSIONEN SET ";
					where = " WHERE ID = " + txtFldId.getText();
					stmt.executeUpdate(updateDBTable + "kommnr = '"
							+ txtFldKommNr.getText() + "'" + ", "
							+ "kommname = '" + txtFldKommName.getText() + "'"
							+ ", " + "strasse = '" + txtFldStrasse.getText()
							+ "'" + ", " + "hausnr = '"
							+ txtFldHausNr.getText() + "'" + ", " + "plz = '"
							+ txtFldPlz.getText() + "'" + ", " + "gemeinde = '"
							+ txtFldGemeinde.getText() + "'" + ", "
							+ "telnr = '" + txtFldTelNr.getText() + "'" + ", "
							+ "bemerkung1 = '" + txtFldBem1.getText() + "'"
							+ ", " + "bemerkung2 = '" + txtFldBem2.getText()
							+ "'" + where);
					JOptionPane.showMessageDialog(null, "Eintrag gespeichert");	
					
					
					fireTableChanged(null);	//mag nit
					JOptionPane.showMessageDialog(null, "refreshed");	
				
				
				} catch (Exception e1) {
					JOptionPane.showMessageDialog(null, e1);
				}
			}
		});

Der gewählte Eintrag wird in der DB wohl so gespeichert, also daran liegt es nicht.

Tja...Sandburgen bauen ist wesentlich einfacher :D
 

melmager

Erfahrenes Mitglied
mal ganz kurz:
erst den DB eintrag löschen
dann mit
table.removeRow(int zeile); //den Eintrag in dem Modell löschen
dann
table.fireTableChanged(); // update Modell

// kann sein das removeRow schon von sich aus den Fire macht also erstmal test ohne
 
Zuletzt bearbeitet:

quidnovi

Erfahrenes Mitglied
So....habe mich jetzt mal auf den Button "Tabelle aktualisieren" konzentriert.
Im Grunde soll das ja derjenige sein, welcher die veränderte DB dann auch im Table ausgibt.

Also, jetzt habe ich mir mal den data - Vektor "KommNr" mit sysout ausgeben lassen.
Code:
Komm 1
Komm 200000
Das ist richtig, denn ich habe den 2. Datensatz bzgl. der Kommissionsnummer von 2 auf 200000 geändert.

Nur wenn ich dann die Tabelle aktualisiere, bleibt alles beim Alten :(
Java:
// Btn Tabelle aktualisieren
		btnRefresh.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				
				// nutzt nix
				fireTableChanged(null);
				
				// DB - Tabelle Kommissionen Tabellenbezeichnung und Daten auslesen
				Vector<String> columnNames = new Vector<String>();
				Vector<Vector<Object>> data = new Vector<Vector<Object>>();
				
				// Um allen Eventulitäten aus dem Weg zu gehen
				columnNames.removeAllElements();
				data.removeAllElements();
				
				
				new Vector<Object>();
				new Vector<Object>();
				try {
					String sql = "SELECT * FROM KOMMISSIONEN";
					Statement stmt = DBData.connection.createStatement();
					ResultSet rs = stmt.executeQuery(sql);
					ResultSetMetaData rsmd = rs.getMetaData();
					int columns = rsmd.getColumnCount();
					for (int i = 1; i <= columns; i++) {
						columnNames.addElement(rsmd.getColumnName(i));
					}

					while (rs.next()) {
						Vector<Object> row = new Vector<Object>(columns);
						for (int i = 1; i <= columns; i++) {
							
							row.addElement(rs.getString("ID"));
							row.addElement(rs.getString("DATUM"));
							row.addElement(rs.getString("KOMMNR"));
							row.addElement(rs.getString("KOMMNAME"));
							row.addElement(rs.getString("STRASSE"));
							row.addElement(rs.getString("HAUSNR"));
							row.addElement(rs.getString("PLZ"));
							row.addElement(rs.getString("GEMEINDE"));
							row.addElement(rs.getString("TELNR"));
							row.addElement(rs.getString("BEMERKUNG1"));
							row.addElement(rs.getString("BEMERKUNG2"));
						}
						// Test was in dem Vektor steht
						System.out.println(rs.getString("KOMMNR"));
						
						data.addElement(row);
					}
					rs.close();
					stmt.close();
				} catch (Exception ex) {
					ex.printStackTrace();
				}
				
				//----------------------------------------------------------------------

				// DB - Ergebnisse in Tabelle fuellen
				JTable table = new JTable(data, columnNames);
				//.....

Irgendwie ist mir dieser Teil noch über...versteh's nit...

Vielleicht erbarmt sich jemand und schaut sich den Code durch...danke :)
 

melmager

Erfahrenes Mitglied
Du hast einmal die DB und dann die Anzeige - im Moment machts du das ja so das du das Modell für die Anzeige komplett neu aufbaust von der DB aus
dann muss logischerweise das fireTableChanged zum Schluss kommen
 

Neue Beiträge