Multiplikation von zwei Labels

Schnörz

Mitglied
Hallo zusammen

Ich habe in einem Gridpane zwei Labels die man über einen Button, in einem neuen Fenster editieren kann. Anzahl des Lebensmittel und Kalorien pro Stück. Jetzt möchte ich im Gridpane noch eine Zeile hinzufügen, die diese beiden Werte jeweils multipliziert, zu einem Total Kalorien. Ich habe von Code her keine Ahnung wie ich das bewerkstelligen kann. fixid vergeben usw. ist klar. Kann mir jemand helfen?
P.S. ich nutze Eclipse und Scene Builder in Windows.

Danke und viele Grüsse
 
So sollte es klappen...
Java:
int x = Integer.parseInt(lblAnzahlLebensmittel.getText());
int y = Integer.parseInt(lblKalorienProStueck.getText());
        
lblTotalKalorien.setText(String.valueOf(x*y));
 
Hier wäre mein Tipp: Versuche Logik von UI mehr zu trennen. Es sollte also eine Datenstruktur mit den Werten geben. Das wäre dann dein Model.

In dem Model hast Du dann also sowas in der Art:
Java:
public class Model {
    private int x;
    private int y;
    
    // Getter und Setter noch ...
    // Konstruktoren, so wie Du diese ggf. benötigst ...
}

Und Deine View greift dann auf das Model zu:
-> Wenn x oder y geändert werden, dann wird das im Model geändert.
-> Und zur Anzeige: Hier werden die Werte aus dem Model genommen.

Bei So Frameworks wie Swing, die kein Binding kennen, baue ich dann oft einfach zwei Methoden:
- Daten aus Controls in Model kopieren
- Daten aus Model in Controls kopieren

Wenn also ein Event ausgelöst wird, dann wird einfach vorgegangen:
- Daten aus Controls in Model übernehmen
- mit dem Model etwas machen
- Daten dann aus Model in Controls übernehmen

Das ist so eine relativ einfache Aufgliederung.

Wenn das Model ständig geändert werden kann, dann wird das natürlich deutlich komplexer und führt dann dazu, dass man Teile des Bindings mehr und mehr nachbaut. Model bekommt dann ein Observer-Pattern und man hat dann ggf. Methoden, die ein Model-Feld mit einem Control verbinden (Also eine Art "Binding für Arme"). Aber das würde ich immer nur bei Notwendigkeit bauen. Und da gibt es evtl. auch fertige Libs für.
 
Also ich habe es schon mit einem Ähnliche Code wie JensXF gepostet hat probiert.
Erhalte aber immer folgende Meldung:

Cannot invoke getText() on the primitive type int

Das heisst die angeforderten Daten sind bereits int und nicht text? Darum kann er sie als Textanforderung nicht erkennen?
 
Ja, Du hast also schon auf eine int Variable zugegriffen und somit hast Du vermutlich schon etwas ähnliches wie ich gesagt habe. Das ist aber ohne konkreten Code nicht zu sagen.
 
Ja, Du hast also schon auf eine int Variable zugegriffen und somit hast Du vermutlich schon etwas ähnliches wie ich gesagt habe. Das ist aber ohne konkreten Code nicht zu sagen.
Ich poste mal das Lebensmittel Model und den Lebensmittel Controller

Model:
Java:
package rb.notvorrat.model;

import java.time.LocalDate;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import rb.notvorrat.util.LocalDateAdapter;

/**
 * Model class for Lebensmittel.
 *
 * @author Robert Brüllmann
 */
public class Lebensmittel {

    private final StringProperty name;
    private final StringProperty beschreibung;
    private final SimpleIntegerProperty anzahlEW;
    private final SimpleIntegerProperty anzahlKI;
    private final ObjectProperty<LocalDate> ablaufdatum;
    private final IntegerProperty anzahl;
    private final IntegerProperty kalorien;
    private final IntegerProperty preisinCHF;


    /**
     * Default constructor.
     */
    public Lebensmittel() {
        this(null, null);
    }
    
    /**
     * Constructor with some initial data.
     * 
     * @param name
     * @param beschreibung
     */
    public Lebensmittel(String name, String beschreibung) {
        this.name = new SimpleStringProperty(name);
        this.beschreibung = new SimpleStringProperty(beschreibung);
        
        // Some initial dummy data, just for convenient testing.
        this.ablaufdatum = new SimpleObjectProperty<LocalDate>(LocalDate.of(2025, 1, 01));
        this.anzahl = new SimpleIntegerProperty(4);
        this.kalorien = new SimpleIntegerProperty(300);
        this.preisinCHF = new SimpleIntegerProperty(5);
        this.anzahlEW = new SimpleIntegerProperty(1);
        this.anzahlKI = new SimpleIntegerProperty(1);
        

    }
    
    public String getname() {
        return name.get();
    }

    public void setname(String name) {
        this.name.set(name);
    }
    
    public StringProperty nameProperty() {
        return name;
    }

    public String getbeschreibung() {
        return beschreibung.get();
    }

    public void beschreibung(String beschreibung) {
        this.beschreibung.set(beschreibung);
    }
    
    public StringProperty beschreibungProperty() {
        return beschreibung;
    }

    public int getanzahl() {
        return anzahl.get();
    }

    public void setanzahl(int anzahl) {
        this.anzahl.set(anzahl);
    }
    
    public IntegerProperty anzahlProperty() {
        return anzahl;
    }

    @XmlJavaTypeAdapter(LocalDateAdapter.class)
    public LocalDate getablaufdatum() {
        return ablaufdatum.get();
    }

    public void setablaufdatum(LocalDate ablaufdatum) {
        this.ablaufdatum.set(ablaufdatum);
    }
    
    public ObjectProperty<LocalDate> ablaufdatumProperty() {
        return ablaufdatum;
    }
    
    public int getkalorien() {
        return kalorien.get();
    }

    public void setkalorien(int kalorien) {
        this.kalorien.set(kalorien);
    }
    
    public IntegerProperty kalorienProperty() {
        return kalorien;
    }
    
    
    public int getpreisinCHF() {
        return preisinCHF.get();
    }

    public void setpreisinCHF(int preisinCHF) {
        this.preisinCHF.set(preisinCHF);
    }
    
    public IntegerProperty preisinCHFProperty() {
        return preisinCHF;
    }
    
    public int getanzahlEW() {
        return anzahlEW.get();
    }

    public void setanzahlEW(int anzahlEW) {
        this.anzahlEW.set(anzahlEW);
    }
    
    public SimpleIntegerProperty anzahlEWProperty() {
        return anzahlEW;
    }
    
    public int getanzahlKI() {
        return anzahlKI.get();
    }

    public void setanzahlKI(int anzahlKI) {
        this.anzahlKI.set(anzahlKI);
    }
    
    public SimpleIntegerProperty anzahlKIProperty() {
        return anzahlKI;
    }
    
}


Controller:
Java:
package rb.notvorrat.view;


import javafx.fxml.FXML;

import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import rb.notvorrat.Main;
import rb.notvorrat.model.Lebensmittel;
import rb.notvorrat.util.DateUtil;



import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;

public class LebensmittelOverviewController {
    //Observable List for ChoiceBox
    ObservableList<String> AnzahlEWKI = FXCollections.observableArrayList("0","1","2","3","4","5","6","7","8","9","10");
    
    @FXML
    private TableView<Lebensmittel> lebensmittelTable;
    @FXML
    private TableColumn<Lebensmittel, String> nameColumn;
    @FXML
    private TableColumn<Lebensmittel, String> beschreibungColumn;

    @FXML
    private Label nameLabel;
    @FXML
    private Label beschreibungLabel;
    @FXML
    private Label anzahlLabel;
    @FXML
    private Label ablaufdatumLabel;
    @FXML
    private Label kalorienLabel;
    @FXML
    private Label totalkalorien;
    @FXML
    private Button berechnen;
    @FXML
    private Label preisinCHFLabel;
    @FXML
    private ChoiceBox anzahlEW;
    @FXML
    private ChoiceBox anzahlKI;


    // Reference to the main application.
    private Main main;

    /**
     * The constructor.
     * The constructor is called before the initialize() method.
     */
    public LebensmittelOverviewController() {
    }

    /**
     * Initializes the controller class. This method is automatically called
     * after the fxml file has been loaded.
     */
    @FXML
    private void initialize() {
        // Initialize the person table with the two columns.
        nameColumn.setCellValueFactory(
                cellData -> cellData.getValue().nameProperty());
        beschreibungColumn.setCellValueFactory(
                cellData -> cellData.getValue().beschreibungProperty());
        anzahlEW.setItems(AnzahlEWKI);
        anzahlKI.setItems(AnzahlEWKI);
        
        
        // Clear person details.
        showLebensmittelDetails(null);

        // Listen for selection changes and show the person details when changed.
        lebensmittelTable.getSelectionModel().selectedItemProperty().addListener(
                (observable, oldValue, newValue) -> showLebensmittelDetails(newValue));
    }

    /**
     * Is called by the main application to give a reference back to itself.
     * 
     * @param main
     */
    public void setMain(Main main) {
        this.main = main;
        
     // Add observable list data to the table
        lebensmittelTable.setItems(main.getLebensmittelData());
        
    }
        /**
         * Fills all text fields to show details about the person.
         * If the specified person is null, all text fields are cleared.
         * 
         * @param person the person or null
         */
        public void showLebensmittelDetails(Lebensmittel lebensmittel) {
            if (lebensmittel != null) {
                // Fill the labels with info from the person object.
                nameLabel.setText(lebensmittel.getname());
                beschreibungLabel.setText(lebensmittel.getbeschreibung());
                anzahlLabel.setText(Integer.toString(lebensmittel.getanzahl()));
                kalorienLabel.setText(Integer.toString(lebensmittel.getkalorien()));
                preisinCHFLabel.setText(Integer.toString(lebensmittel.getpreisinCHF()));

                // birthdayLabel.setText(...);
                ablaufdatumLabel.setText(DateUtil.format(lebensmittel.getablaufdatum()));
            } else {
                // Person is null, remove all the text.
                nameLabel.setText("");
                beschreibungLabel.setText("");
                ablaufdatumLabel.setText("");
                anzahlLabel.setText("");
                kalorienLabel.setText("");
                preisinCHFLabel.setText("");
            }
            }
            
        /**
         * Called when the user clicks on the delete button.
         */
        @FXML
        public void handleDeleteLebensmittel() {
            int selectedIndex = lebensmittelTable.getSelectionModel().getSelectedIndex();
            if (selectedIndex >= 0) {
                lebensmittelTable.getItems().remove(selectedIndex);
            } else {
                // Nothing selected.
                Alert alert = new Alert(AlertType.WARNING);
                alert.initOwner(main.getPrimaryStage());
                alert.setTitle("No Selection");
                alert.setHeaderText("No Lebensmittel Selected");
                alert.setContentText("Please select a Lebensmittel in the table.");

                alert.showAndWait();
            }
        }
        
        
        /**
         * Called when the user clicks the new button. Opens a dialog to edit
         * details for a new person.
         */
        @FXML
        private void handleNewLebensmittel() {
            Lebensmittel tempLebensmittel = new Lebensmittel();
            boolean okClicked = main.showLebensmittelEditDialog(tempLebensmittel);
            if (okClicked) {
                main.getLebensmittelData().add(tempLebensmittel);
            }
        }

        /**
         * Called when the user clicks the edit button. Opens a dialog to edit
         * details for the selected person.
         */
        @FXML
        private void handleEditLebensmittel() {
            Lebensmittel selectedLebensmittel = lebensmittelTable.getSelectionModel().getSelectedItem();
            if (selectedLebensmittel != null) {
                boolean okClicked = main.showLebensmittelEditDialog(selectedLebensmittel);
                if (okClicked) {
                    showLebensmittelDetails(selectedLebensmittel);
                }

            } else {
                // Nothing selected.
                Alert alert = new Alert(AlertType.WARNING);
                alert.initOwner(main.getPrimaryStage());
                alert.setTitle("No Selection");
                alert.setHeaderText("No Lebensmittel Selected");
                alert.setContentText("Please select a person in the table.");

                alert.showAndWait();
            }
        }

}
 
Ach, JavaFX ... da hast Du ja schon ein Binding. Binde die Label doch an die jeweilige Property. (Da es eine IntegerProperty ist, musst Du da bind(intProperty.asString()) machen so ich mich richtig erinnere.

Dann kannst Du im Model die Berechnung machen: Wenn sich eine der beiden IntegerProperties ändert, dann änderst Du im Model die andere Property (Sprich für das Ergebnis fügst Du noch eine Property hinzu damit Du da Binding machen kannst.). Dabei auf viele checks achten. Sollte eine Property null sein oder keinen gültigen Wert hat, dann machst Du keine Berechnung und so.

Wäre das eine Idee für Dich?
 

Zurück
Oben