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>
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
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ausgabe 1 -- Sie trat in eine der berühmten Java autoboxing fallen.
Anrufe
List.remove(Object o)
stattList.remove(int idx)
als Sie erwartet haben.Verwenden
statt.
Probleme 2-3
Einfach Hörer
selectedItem
und binden Sie erneut auf ändern:und aktualisieren Sie Ihre Message-Klasse. Um korrekt zu arbeiten mit TableView es erforderlich, die volle FX "bean" und setzen die Eigenschaft durch Methode:
List#remove(Object o)
wird ebenfalls unterstützt. Aber es wird, entfernen Sie Objekte von Ihrem Typ (Message
) und dann rufen Sie entfernen für Integer falschen löschen genannt wird, weil Integer ist ein Objekt. Sie können Sie Lesen, besser formatierte Antwort hier: stackoverflow.com/questions/4534146/...über das wie habe ich erfahren -- ich habe gerade gelesen, vor einiger Zeit über ähnliches Problem, ich glaube, Bloch ' s "Effective Java". Check it out -- sehr nützliches Buch.
Hallo Sergey, ja, jetzt habe ich es. Es ist offensichtlich, wenn man wirklich darüber denkt. Vielen Dank!
unbind()
sollte nur entfernen Sie die unidirektionale Bindung. Zum entfernen einer bidirektionalen Bindung verwenden, müssen SieunbindBidirectional(Property<Boolean>)
oder es wird keine Wirkung haben, entsprechend der JavaDoc JavaFX 2.2.InformationsquelleAutor Sergey Grinev