La liaison de JavaFX 2 TableView éléments
Je travaillais sur une petite application à l'aide d'une simple liaison en JavaFx 2.1 à l'aide de java 1.7.0_04-b21 sur MacOSX. En fait je suis actuellement comparer les lier à des mécanismes de Cocoa sur Mac OSX pour la JavaFx et faire face à plusieurs problèmes:
L'application utilise un modèle de la détention d'un observableArrayList (appelé messageList) qui est défini comme les éléments d'une TableView. Ajout d'une nouvelle Entrée à la liste des œuvres. L'entrée s'affiche dans la TableView.
Question 1: la Suppression d'un élément sélectionné ne fonctionne pas. Lorsque je supprime un élément de la observables liste il ne disparaît pas.
Question 2: je veux remplir un champ de texte avec la valeur stockée dans un champ de l'objet sélectionné dans la TableView.
En effet, pour cette dans le Cacao, on peut définir une liaison à une sélection, même si c'est vide (donc, rien n'est sélectionné) au moment de la définition de la liaison. C'est en fait très utile, concept et je n'ai pas trouvé comment cela pourrait être possible en JavaFX.
Question 3: Seulement si un objet est sélectionné, une liaison peut être établie de sorte que j'ai finalement écrit un Gestionnaire de réagir à une évolution de sélection et de rétablissement toujours une bonne liaison de mon champ texte pour les modèles de champ. Mais aussi pour cette approche de mon application détruit le modèle pour une raison que je ne comprends pas maintenant.
Cliquez simplement trois ou quatre fois le Bouton ajouter, puis sélectionnez les entrées et voir les mises à jour de la zone de texte. Les données du modèle sont détruits et remplacé - et les entrées normalement obtenir plus courte... les Explications de l'effet sont les bienvenus.
Jusqu'à présent, je ne pouvais pas trouver un exemple de liaison sur une TableView donc tout commentaires sont les bienvenus.
Le code de mon projet de démonstration est inclus dans les fichiers suivants. Tous sont dans le même package 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>
Bonjour jewelsea, effectivement, la question a beaucoup de pièces - oui. Mais en fait, il se résume à une seule: le mécanisme de liaison de travail pour TableView et si oui, est-il un exemple de travail. Pour moi, il ne fonctionne tout simplement pas pour des raisons différentes nommé questions ci-dessus. Encore toute aide est appréciée. Salutations, E. S.
OriginalL'auteur E.S. | 2012-05-21
Vous devez vous connecter pour publier un commentaire.
numéro 1 -- vous entrez dans l'un des célèbres Java l'autoboxing pièges.
appels
List.remove(Object o)
au lieu deList.remove(int idx)
comme prévu.Utilisation
à la place.
questions 2-3
Il suffit de fixer l'auditeur à
selectedItem
et relier sur le changement:et mise à jour de votre classe de Message. Pour fonctionner correctement avec TableView il a besoin pour être en pleine FX "haricot" et de les exposer à la propriété par le biais de la méthode:
List#remove(Object o)
est pris en charge. Mais il va supprimer les objets de votre type (Message
) et puis vous appelez supprimer pour l'Entier de mal supprimer est appelé, parce que Entier est un Objet. Vous pouvez lire les mieux formaté réponse ici: stackoverflow.com/questions/4534146/...comment ai-je -- je viens de lire il y a quelques temps à propos de problème similaire, je crois, Bloch "Effective Java". Check it out -- livre très utile.
Bonjour Sergey, oui, maintenant je l'ai eu. Il est évident que si l'on croit vraiment à ce sujet. Merci!
unbind()
ne devrait supprimer la liaison unidirectionnelle. Pour supprimer une liaison bidirectionnelle, vous devez utiliserunbindBidirectional(Property<Boolean>)
ou elle n'aura aucun effet, selon le JavaFX 2.2 JavaDoc.OriginalL'auteur Sergey Grinev