Bindung JavaFX 2 TableView Elemente

Arbeitete ich an einer kleinen Anwendung mit einem einfachen binding in JavaFx 2.1 Verwendung von java 1.7.0_04-b21 auf MacOSX. Eigentlich habe ich derzeit vergleichen Sie die bind-Mechanismen von Cocoa unter Mac OSX zu JavaFx und Gesicht mehrere Probleme:

Die Anwendung verwendet ein Modell hält eine observableArrayList (genannt messageList), die festlegen, wie die Elemente in einer TableView. Hinzufügen ein neuer Eintrag zu der Liste funktioniert. Der Eintrag erscheint in der TableView.

Problem 1: Löschen eines ausgewählten Elements funktioniert nicht. Wenn ich Sie entfernen ein Element aus der beobachten-Liste verschwindet nicht.

Problem 2: ich möchte füllen Sie ein Textfeld mit den gespeicherten Wert in einem Feld des Objekts ausgewählt wird, ist in der TableView.
Eigentlich für diesen Kakao kann man definieren, eine Bindung an eine Auswahl, auch wenn dieser leer ist (damit nichts ausgewählt ist) zum Zeitpunkt der definition der Bindung. Dies ist eigentlich ein sehr nützliches Konzept, und ich nicht finde wie das möglich sein kann in JavaFX.

Problem 3: Nur, wenn bereits ein Objekt ausgewählt ist, eine Bindung hergestellt werden kann, so dass ich schließlich schrieb ein EventHandler reagiert auf eine wechselnde Auswahl und (wieder -) Herstellung immer eine korrekte Bindung von meinem textfield zu den Modellen-Feld. Aber auch für diesen Ansatz meine Anwendung zerstört das Modell aus irgendeinem Grund, die ich nicht verstehe.

Klicken Sie einfach auf drei oder vier mal die Schaltfläche "hinzufügen", dann wählen Sie die Einträge, und sehen Sie die updates der textField-Instanz. Die Daten in das Modell zerstört und überschrieben - und die Einträge in der Regel kürzer... Erklärungen zu dem Effekt, sind willkommen.

Bis jetzt konnte ich nicht finden, ein verbindliches Beispiel auf einen TableView, so dass jeder input ist willkommen.

Den code meiner demo-Projekt enthalten ist in den folgenden Dateien. Alle sind in der gleichen Paket com.es.javaFxTest.

MainWindowController.java:

/*
 * Created on 19.05.2012
 */
package com.es.javaFxTest;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ResourceBundle;

import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;

public class MainWindowController implements Initializable
{

  public Model                         model;

  public TableView<Message>            messageListTableView;

  public TableColumn<Message, String>  messageTableMessageNameColumn;

  public Button                        addMessageButton;

  public Button                        deleteMessageButton;

  public TextField                     messageNameTextField;

  public SimpleObjectProperty<Message> selectedMessage;

  /* (non-Javadoc)
   * @see javafx.fxml.Initializable#initialize(java.net.URL, java.util.ResourceBundle)
   */
  @Override
  public void initialize(URL arg0, ResourceBundle arg1)
  {
    model = new Model();

    messageTableMessageNameColumn.setCellValueFactory(new PropertyValueFactory<Message, String>("messageName"));
    messageListTableView.setItems(model.getMessageList());

    addMessageButton.setOnAction(new EventHandler<ActionEvent>() {
      StringBuffer str = new StringBuffer("a"); //to fill some dummy data

      @Override
      public void handle(ActionEvent e)
      {
        //adding an object to the observed list works and the result is shown in the tableView
        model.getMessageList().add(new Message(str.toString()));
        str.append("x");
      }
    });
    deleteMessageButton.setOnAction(new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent event)
      { //observation does not work here; also the following code does not work. 
        ObservableList<Integer> selectedIndices = messageListTableView.getSelectionModel().getSelectedIndices();
        ArrayList<Integer> selectedIndices2 = new ArrayList<Integer>(selectedIndices);
        Collections.sort(selectedIndices2);
        for (int i = selectedIndices2.size() - 1; i >= 0; i--)
        {
          model.getMessageList().remove(selectedIndices2.get(i));
        }
      }
    });

    selectedMessage = new SimpleObjectProperty<Message>();
    selectedMessage.bind(messageListTableView.getSelectionModel().selectedItemProperty());

    selectedMessage.addListener(new ChangeListener<Message>() {

      @Override
      public void changed(ObservableValue< ? extends Message> observable, Message oldValue, Message newValue)
      {
        System.out.format("ObservableValue %s, \n  oldValue %s\n  newValue %s\n\n", observable, oldValue, newValue);
        if (oldValue != null)
        {
          messageNameTextField.textProperty().unbind();
          oldValue.messageName.unbind();
        }
        if (newValue != null)
        {
          messageNameTextField.textProperty().set(newValue.getMessageName());
          newValue.messageName.bindBidirectional(messageNameTextField.textProperty());
        }
      }
    });
  }
}

MainWindowLayout.java

package com.es.javaFxTest;

/*
 * Created on 18.05.2012
 */
import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class MainWindowLayout extends Application
{

  @Override
  public void start(Stage stage)
  {

    try
    {
      FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MainWindowLayout.fxml"));
      Pane root = (Pane) fxmlLoader.load();
      MainWindowController controller = (MainWindowController) fxmlLoader.getController();

      Scene scene = new Scene(root);
      stage.setTitle("Config");
      stage.setScene(scene);
      stage.show();

    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  public static void main(String[] args)
  {
    launch(args);
  }

}

Message.java

/*
 * Created on 19.05.2012
 *
 */
package com.es.javaFxTest;

import javafx.beans.property.SimpleStringProperty;

public class Message 
{



  /**
   * @param canId
   * @param messageName
   */
  public Message(String messageName)
  {
    this.messageName = new SimpleStringProperty(messageName);
  }


  SimpleStringProperty messageName;
  /**
   * @return the messageName
   */
  public String getMessageName()
  {
    return messageName.getValue();
  }
  /**
   * @param messageName the messageName to set
   */
  public void setMessageName(String messageName)
  {
    this.messageName.set(messageName);
  }

  public String toString ()
  {
    return String.format("Name:%s",messageName); 
  }

}

Model.java

/*
 * Created on 20.05.2012
 */
package com.es.javaFxTest;

import javafx.beans.property.SimpleListProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public class Model
{
  ObservableList<Message>     messageList;

  SimpleListProperty<Message> messageListProperty;

  public Model()
  {
    messageList = FXCollections.observableArrayList();
    messageListProperty = new SimpleListProperty<Message>(this,"messageList",messageList);
  }

  public final SimpleListProperty<Message> messageListProperty()
  {
    return messageListProperty;
  }

  public ObservableList<Message> getMessageList()
  {
    return messageListProperty.get();
  }

  public void setMessageList(ObservableList<Message> l)
  {
    messageListProperty.set(l);
  }
}

MainWindowLayout.xml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.collections.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="500.0" xmlns:fx="http://javafx.com/fxml" fx:controller="com.es.javaFxTest.MainWindowController">
  <children>
    <SplitPane id="splitPaneHorizontal1" dividerPositions="0.3614457831325301" focusTraversable="true" prefHeight="600.0" prefWidth="900.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
      <items>
        <AnchorPane id="anchorPane1" minHeight="0.0" minWidth="0.0" prefHeight="598.0" prefWidth="390.0">
          <children>
            <VBox id="VBox" alignment="CENTER" prefHeight="598.0" prefWidth="177.0" spacing="5.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
              <children>
                <TableView id="tableView1" fx:id="messageListTableView" editable="true" prefHeight="598.0" prefWidth="406.0">
                  <columns>
                    <TableColumn prefWidth="75.0" text="Name" fx:id="messageTableMessageNameColumn" />
                  </columns>
                </TableView>
                <HBox id="HBox" alignment="CENTER" spacing="5.0">
                  <children>
                    <Button id="button2" fx:id="addMessageButton" text="Add">
                      <HBox.margin>
                        <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
                      </HBox.margin>
                    </Button>
                    <Button id="button1" fx:id="deleteMessageButton" text="Delete">
                      <HBox.margin>
                        <Insets bottom="5.0" right="5.0" top="5.0" />
                      </HBox.margin>
                    </Button>
                  </children>
                </HBox>
              </children>
            </VBox>
          </children>
        </AnchorPane>
        <AnchorPane id="anchorPane2" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
          <children>
            <HBox id="HBox" alignment="CENTER" layoutX="44.0" layoutY="177.0" spacing="5.0">
              <children>
                <Label id="label2" text="Name:" />
                <TextField id="textField2" fx:id="messageNameTextField" prefWidth="200.0" text="TextField" />
              </children>
            </HBox>
          </children>
        </AnchorPane>
      </items>
    </SplitPane>
  </children>
</AnchorPane>
Diese Frage hat zu viele Teile und viel zu viel code. Es wäre besser, wenn jeder Teil wurde getrennt in seine eigene Frage mit minimal-code, um zu demonstrieren, ausschließlich die Frage diskutiert, dass die Frage Teil.
Hallo jewelsea, tatsächlich die Frage hat viele Teile - ja. Aber eigentlich läuft es auf eins: Funktioniert der Mechanismus für die Bindung der Arbeit für die TableView und wenn ja, gibt es irgendein Beispiel arbeiten. Für mich ist es einfach nicht funktioniert aus verschiedenen Gründen genannt, über Probleme. Immer noch jede Hilfe ist willkommen. Grüße, E. S.

InformationsquelleAutor E.S. | 2012-05-21

Schreibe einen Kommentar