JavaFX Gui - Löschbutton in Tabelle anzeigen, die mittels MySQL Abfrage gefüllt wird

  • Themenstarter Themenstarter Gelöschtes Mitglied 51388
  • Beginndatum Beginndatum
G

Gelöschtes Mitglied 51388

Gast
Hallo Leute,

bin mit meinem Latein als Anfänger am Ende.

Mein Ziel ist es, auf eine MySQL – Datenbank mittels JavaFX – GUI zuzugreifen und einzelne Datensätze löschbar zu machen. Die Connection zur Datenbank funktioniert (Ping ist o.k.). Andere Spaltenwerte werden korrekt ausgelesen und angezeigt.

Das GUI wird angezeigt, aber in der Spalte Löschen wird kein Lösch-Button angezeigt. Warum? Wo ist mein Fehler?

Oder eine andere Herangehensweise: Wie kann ich einen in der Tabelle markierten Tupelzeileneintrag per Buttonklick löschen?

upload_2015-9-22_12-3-56.png

Bin für jeden Ratschlag dankbar!

Und wie kann ich den Code im Forum korrekt in seiner Form eingeben, damit er für andere besser lesbar ist? Ist meine erste Frage an die Community?

Ich erhalte keinerlei Fehlermeldungen in eclipse, arbeite auf einem Mac. Es kann höchstens sein, dass jetzt ein paar Klammern irgendwo beim rumkopieren fehlen.

Hier kommt jetzt der Code:
Java:
public class MainWindowController {

   @FXMLprivate TableView<DatenMySQLProperties> tableview;
   @FXMLprivate TableColumn<DatenMySQLProperties, Integer> colUF_ID;
   @FXMLprivate TableColumn<DatenMySQLProperties, String> colUF_Name;
   @FXMLprivate TableColumn<DatenMySQLProperties, Double> colUF_Faktor;
   @FXMLprivate TableColumn<DatenMySQLProperties, ButtonCell> colUF_Loesche;

   @FXMLprivate Button buAktualisieren;
   @FXMLprivate Button buLoeschen;
   @FXMLprivate Button buBeenden;

   Connection con = null;
   ResultSet rs = null;

   @FXML
   public void handlebuLoeschen() {
     buLoeschen.setOnAction(new EventHandler<ActionEvent>(){
       @Override
       publicvoid handle(ActionEvent event) {
         System.out.println("LOESCHE!");
         //Wie lautet hier der Befehl, um einen markierten
         //Datensatz anzusprechen und mit SQL aus MySQL zu löschen??
       }
     });
   }

   @FXML
   void initialize(){
     asserttableview != null : "fx:id=\"tableview\" was not injected: check your FXML file 'MYSQLconnection.fxml'.";

     colUF_ID.setCellValueFactory(p -> { returnp.getValue().uf_id.asObject(); });
     colUF_Name.setCellValueFactory(p -> { returnp.getValue().getUf_name(); });
     colUF_Faktor.setCellValueFactory(p -> { returnp.getValue().uf_faktor.asObject(); });

     //hier beginnen die Fehler!!! zur Lösung mittels Lösch-Button je Zeile
     colUF_Loesche.setCellValueFactory(p -> { returnp.getValue().getUf_loesche(); });

     // p -> new ButtonCell() );
     //gibt false zurück, weilüberhauptkeineverbindungbesteht, also entweder in dr Getter Bean allesdefiniern
     // p -> { return p.getTableColumn().visibleProperty(); }); //gibtlogischerweise, weilsichtbar true zurück
     /* new Callback<TableColumn.CellDataFeatures<DatenMySQLProperties, Boolean>,
     ObservableValue<Boolean>>() {
     @Override
     public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<DatenMySQLProperties, Boolean> p) {
     return new SimpleBooleanProperty(p.getValue() != null);
     } */
     // };
     //Endevoninitailize()
     //}

     //Problemeerstmalfxmldazubauen
     //hierentsteht die VerbindungzurKlasse MySQLAufrufVerbindung
     MySQLAufrufVerbindung objDbClass = new MySQLAufrufVerbindung();
     try{
       con = objDbClass.getConnection();
       buildData();
     } catch( ClassNotFoundException ce ){
       System.out.println("Mist1 //Fehler1 war, dass ich vergessen hatte, über Properties MySQL Build Path aufzurufen im Project");
       ce.printStackTrace();
     } catch( SQLException ce2 ){
       System.out.println("Mist2");
       ce2.printStackTrace();
     }
   }


   private ObservableList<DatenMySQLProperties> data;
   //mitdieserMethodekannichauf die Klasse DatenMySQLProperties zugreifen

   public void buildData(){
     data = FXCollections.observableArrayList();
     try{
       String SQL = "Select * from UmFaktor";
       ResultSet rs = con.createStatement().executeQuery(SQL);
       while( rs.next() ){
         //hierwerden die Daten in der while Schleifeausgelesen
         DatenMySQLProperties datenMySQL = new DatenMySQLProperties();
         datenMySQL.uf_id.set(rs.getInt("UF_ID"));
         datenMySQL.uf_name.set(rs.getString("UF_Name"));
         datenMySQL.uf_faktor.set(rs.getDouble("UF_Faktor"));
         //MUSS hier irgendwie der Lösch-Button definiert, eingefügt werden?? habe //ich hier irgendetwas vergessen?
         data.add( datenMySQL );
         tableview.setItems( data );
       }
     } catch(Exception e){
       e.printStackTrace();
       System.out.println("Error on Building Data");
     }
   }

   // Hier wird die Buttonzelle definiert
   class ButtonCell extends TableCell<Record, Boolean> {
     ButtonCell(){
       buLoeschen.setOnAction(new EventHandler<ActionEvent>(){
         @Override
         publicvoid handle(ActionEvent t) {
           /**
           * HIER MUSS ZUGRIFF aus MYSQL gegeben sein plus SQL Delete Abfrage
           */
         }
       });
     }
   }
}


Hier kommt noch die Bean:
Java:
package application;

import com.sun.prism.impl.Disposer.Record;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;

public class DatenMySQLProperties {
   //Bean
   public SimpleIntegerProperty uf_id = new SimpleIntegerProperty( );
   public SimpleStringProperty uf_name = new SimpleStringProperty( );
   public SimpleDoubleProperty uf_faktor = new SimpleDoubleProperty( );
   public ObservableValue<Boolean> uf_loesche = new SimpleBooleanProperty();

   public SimpleIntegerProperty getUf_id() {
     return uf_id;
   }

   public void setUf_id(SimpleIntegerProperty uf_id) {
     this.uf_id = uf_id;
   }

   public SimpleStringProperty getUf_name() {
     return uf_name;
   }

   public void setUf_name(SimpleStringProperty uf_name) {
     this.uf_name = uf_name;
   }

   public SimpleDoubleProperty getUf_faktor() {
     return uf_faktor;
   }

   public void setUf_faktor(SimpleDoubleProperty uf_faktor) {
     this.uf_faktor = uf_faktor;
   }

   //Hier kommt irgendwo der Fehler, kann man die Frage überhaupt mit so //einem Konstrukt lösen? Funktionieren tut es nämlich nicht
   public ObservableValue<application.ButtonCell> getUf_loesche() {
     class ButtonCell extends TableCell<Record, Boolean> {
       final Button cellButton = new Button("Delete");
       ButtonCell() {
         cellButton.setOnAction( new EventHandler<ActionEvent>() {
           @Override
           public void handle(ActionEvent event) {
             // TODO Auto-generated method stub
             ButtonCell.this.getTableView().getItems().get( ButtonCell.this.getIndex());
             System.out.println("Test");
           }
         });
       }
     }
     //return new Button(); funzt nicht
     //return uf_loesche; funzt nicht
   }

   public void setUf_loesche(SimpleBooleanProperty uf_loesche) {
     this.uf_loesche = uf_loesche;
   }
}
 
Zuletzt bearbeitet von einem Moderator:
Verstehe ich das richtig, du willst den loschbutton von unten direkt in der Zeile haben die gelöscht werden soll, Un dicht die zeile(n) auswählen und dann den einen Knopf drücken?
 
Eine von den beiden möglichen Ansätzen einer Lösung reicht, damit ich ein Verständnis für die Funktion in meinen Kopf bekomme ....

Lösung A: Es erscheint ein Löschbutton in jeder Zeile eines Datensatzes in der Spalte Löschen, wenn ich den dann klicke, wird der Datensatz gelöscht.

Lösung B: Ich markiere die Zeile mit dem zu löschenden Datensatz mit einem Mausklick und klicke dann auf den Löschbutton unten, der bereits in der GUI zu sehen ist und der Datensatz wird gelöscht.

Vielen Dank im Voraus ...
 
Hmmm ich bin mehr der ulc Mensch, aber an der table könnte ein model hängen und entweder bekommst du über das model, oder über die table die selektierten Zeilen zurück. Würde zumindest mir logisch erscheinen.
Sag Bescheid falls du was findest
 
Hier mal ein Code-Ausschnitt von mir:

Java:
        // Delete-Spalte
        colAction.setCellValueFactory(new PropertyValueFactory<IdentnummerVerlauf, String>("identnummerAlt"));
        colAction.setCellFactory(column -> new TableCell<IdentnummerVerlauf, String>(){
            public void updateItem(String string, boolean empty) {
                super.updateItem(string, empty);
                if (string == null || empty) {
                    setGraphic(null);
                }
                else {
                    String sIconDelete = "/icons/16/dialog-error.png";
                    Image imageIcon = new Image(getClass().getResourceAsStream(sIconDelete));
                    ImageView imageView = new ImageView(imageIcon);
                    imageView.setFitWidth(16);
                    imageView.setPreserveRatio(true);
                   
                    Button btnDelete = new Button("Löschen");
                    btnDelete.setUserData(getIndex());
                    btnDelete.setOnAction(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent event) {
                            Button btnSource = (Button)event.getSource();
                            int index = (int)btnSource.getUserData();
                            deleteIdentnummerverlauf(index);
                        }
                    });
                    btnDelete.setGraphic(imageView);
                    setGraphic(btnDelete);
                    setAlignment(Pos.CENTER);
                }
            }
        });

Das ImageIcon kannst du auch außerhalb erstellen und dann immer nur setzen, ist sicher performanter, aber zum Testen gehts so auch. IdentnummerVerlauf ist bei mir eine Klasse, da kannst du deine eigene Klasse unterbringen oder den entsprechenden Datentyp.
 

Zurück
Oben