i have the following method:
CreateStrip createStrip = new CreateStrip(input);
depBox.getChildren().add(createStrip.getStripGrid());
depBox is a VBox and .getStripGrid() return a GridPane.
CreateStrip has this method too:
public String getNameStrip() { return input.getNameStrip();}
during the life of the program depBox get many GridPane, each one with a different NameStrip.
sometimes i have the necessity to remove a specific GridPane from depBox that match with .getNameStrip().
i have tried:
for (Node node: depBox.getChildren()) {
//TODO REMOVE GRIDPANE CONTAIN THE NAME THAT MATCH WITH THE MESSAGE RECEIVED..
}
but i don't know how to set the matching control.
Step 1:
Attach data to the GridPane that allows you to identify the one to remove.
You could do this by using Node.setUserData or by using the properties Map (which I'll do in the following code snippets).
Creating the GridPane
GridPane gp = createStrip.getStripGrid();
gp.getProperties().put(NAME_KEY, createStrip);
depBox.getChildren().add(gp);
// use object not equal to any other object as key (i.e. equals uses reference equality)
static final Object NAME_KEY = new Object();
Step 2:
Use the information to remove the appropriate GridPane. searchName is the String that identifies the GridPane you want to remove (to check for equality with getNameStrip()):
depBox.getChildren().removeIf(c -> {
CreateStrip strip = (CreateStrip) c.getProperties().get(NAME_KEY);
return strip != null && searchName.equals(strip.getNameStrip());
});
Depending on your CreateStrip class it may not be necessary to add a instance of it as property. It may not even be the right thing to do, if it's a factory, but I think you get the idea nontheless.
Alternative
You can also assign a value to the id property of the Node and use those to identify the correct node using Node.lookup. However those need to be unique and be a valid css id, but you could use a Map to map from message to id.
Related
so I am using JavFX to create a form that stores all the answers in a csv file. I need to create a dropdown menu that allows the users to select an option, which is then recorded in the csv file. I have tried a lot of different options, however I think comboBox is the best option.
I have no problem creating the ComboBox, I only run into problems when it comes to the method to get the value of the box.
Can someone help me find a solution, or suggest what another JavaFX menu I can use?
This is the code I have right now:
public VBox setFamiliar(){
Button button = new Button();
button.setOnAction(e -> toString());
familiarComboBox = new ComboBox<>();
familiarVBox = new VBox();
familiarComboBox.getItems().addAll("Irmão", "Irmã", "Avó", "Avô", "Tio", "Tia", "Pai", "Mãe");
familiarVBox.getChildren().add(familiarComboBox);
familiarVBox.getChildren().add(button);
return familiarVBox;
}
Here I set the ComboBox, this part doesnt seem to have a problem because it appears and I can select an item. I created a separate void toString() method that sets the value of a variable to the current selected item
public void toString(ActionEvent e){
familiar = familiarComboBox.getSelectionModel().getSelectedItem().toString();
}
The problem is then in the get method to get the value that was selected.
public String getIrmao(){
if(familiar.equals("Irmão")){
return "2";
}
return "0";
I also tried to do familiarComboBox.getSelectionModel().getSelectedItem().equals(), and other variations of this combination.
If I understand your requirement -- that when a user makes a choice from the "Familiar" combo box, a value should be written immediately to a CSV file -- you don't need the getIrmao() method. You simply write the value out in the action which you are calling toString(...) (not a good choice of names), but which we will rename to handleFamiliarChange(...).
Now the method becomes
public void handleFamiliarChange(ActionEvent e){
final String familiar =
familiarComboBox.getSelectionModel().getSelectedItem().toString();
FileUtils.writeToCsvFile(familiar.equals("Irmão") ? 2 : 0);
}
where FileUtils.writeToCsvFile(...) is a method that does the file writing. Note that FileUtils is a class you have created to separate out file handling concerns -- your JavaFX view class should only concern itself with views.
I've a couple of copied elements in an observablelist which I use for copy/paste operations in a TableView. The name of the table is cpTable (copy and paste Table) for storing copied elements and to paste elements that are stored in the table. After each paste operation I want to clear the contents of cpTable before I copy other selected items with Ctrl+C.
But I always get the error:
JavaFX Application Thread" java.lang.UnsupportedOperationException:
Not supported.
at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.remove(ReadOnlyUnbackedObservableList.java:246)
Here is my pseudocode:
if (cpTable !=null) {
//first, get all copied items for removing all elements
ObservableList<String> copiedItems = cpTable.getItems();
int size = copiedItems.size();
// remove all elements
for(int i=0;i<size;i++) {
copiedItems.remove(i);
}
cpTable.setItems(copiedItems); //clear cpTable by setting an empty list
}
This is a method that copies the contents of selected items and puts it in a cpTable
public TableView<String> copySelectionToClipboard(TableView<String> table) {
ObservableList<String> data = table.getSelectionModel().getSelectedItems();
TableView<String> tmp = new TableView<>();
tmp.setItems(data);
return tmp;
}
When Ctrl+C is pressed the following line puts all copied items in a cpTable:
cpTable = copySelectionToClipboard( (TableView<String>) keyEvent.getSource());
As mentioned I want to clear all cpTable contents immediately after pasting
the items in a table.
Just clear your Observable List. It looks like you should use copiedItems.clear();
That should clear your table.
As James_D already mentioned, you haven't cleared exactly what's the point.
If you want to delete selected items from a table, you need to delete them from the table item list itself and not from the selection model.
A possible solution looks like this:
TableView<String> table = new TableView<>();
ObservableList<String> tableItems = table.getItems();
// needs multirowselection is set to true
ObservableList<String> readOnlyItems = table.getSelectionModel().getSelectedItems();
// removes all selected elements for the table
readOnlyItems.stream().forEach((item) -> {
tableItems.remove(item);
});
// clear the selection
table.getSelectionModel().clearSelection();
Update
This method get's an TableView, calls it's selection model to get all selected items. And then you add the data to a new TableView. And there is the problem! It's an unmodifiable read only list that you attached to your new table. First make it modifiable, like in the code below:
public TableView<String> copySelectionToClipboard(TableView<String> table) {
ObservableList<String> readOnlyData = table.getSelectionModel().getSelectedItems();
ObservableList<String> writableData = FXCollections.<String>observableArrayList(readOnlyData);
TableView<String> tmp = new TableView<>();
tmp.setItems(writableData);
return tmp;
The next problem is in your call to this method. You call it with a TableView<CsvData> and with a TableView<String> as your method needs. If CsvData is a subtype of String, than you have to change your method signature to TableView<? extends String>
If you are trying to clear all the items from your tableView and want just an empty tableView. You can use this:
myTableView.getItems().clear();
This basically gets all the items from your table view which is nothing but just the observable list now it performs clear operations to remove all the items in tableView.
Assuming you mean
table.getSelectionModel().getSelectedItems()
(since the selection model has no getItems() method), according to the Javadocs, this returns a read-only list. Thus attempting to modify the list will throw an UnsupportedOperationException.
To clear the selection, do
table.getSelectionModel().clearSelection();
(And similarly, if you want to manipulate the selection in any other way, you use methods on the selection model, rather than on the list.)
I need a reference to the object under the mouse cursor in a javaFX Pane (or ScrollPane)
The following code removes the node under the cursor from the Pane.
The node object is stored in an ArrayList and has a unique id. If I had a reference to the node object, it would be a simple matter to remove it from the list. I'd be happy just to be able to pull the id of the node object out of the target description supplied by the MouseEvent's description of the target, and use it to find my node in the list. Note: I am creating these nodes dynamically and they are nameless: myList.add(new TYPE()).
Here's the snippet that I'm using to remove the node in the Pane;
root.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle (MouseEvent me) {
// would like a line here that grabbed the reference to the target
pane.getChildren().remove(me.getTarget());
}
});
It would be better for you to put the setOnMouseClicked listener to the node on which you want to remove from the list.
List<Node> listOfNodes = new ArrayList();
Node node = new Node();
listOfNodes.add(node);
node.setOnMouseClicked((event) -> {
listOfNodes.remove(node);
});
Note: Better use ObservableList than the ordinary ArrayList especially if you want that node to be removed also out from the root pane.
To James_D: Reason for disbelief: the syntax that fails to get past the compiler is the statement containing the expression me.getTarget().getText() which is commented out. It seemed to me that that ought to have worked.
for (Text tl : textList)
if ( (me.getTarget()) == (tl) )
{
System.out.println("HuRah!");
System.out.println("text is " + tl.getText());
//System.out.println("text is " + me.getTarget().getText());
textList.remove(me.getTarget());
}
need my AdvancedDataGrid group by the name of the person, but I'm having trouble because the groupingField not accept "objectPeople.idPeople"
the name of the groupingField not accept "objectPeople.idPeople"?
GroupingField name="people.idPeople" <--error??
That's because dot is not allowed in field handling.
Explanation.
Inside DataGrid addressing groupingField property from your item is held with square braces operator:
item[groupingField]
This addressing only supports one level. E.g. if you've got object inside object, you cannot address properties of the second one with square braces in first:
var outer:Object = new Object();
var inner:Object = new Object();
outer["property"] = inner;
inner["value"] = 0;
trace(outer["property.value"]); // runtime error
trace(outer.property.value); // traces 0
outer["property.value"] = 1; // creates property "property.value" in outer
trace(outer["property.value"]); // traces 1
trace(outer.property.value); // still traces 0
Answer.
If you have idPeople inside your item, you should specify groupingField="idPeople".
If you have objectPeople with idPeople property inside your item, you should (for instance) write a getter in your item to avoid multiple levels and specify its name in groupinf field property - groupingField="idPeople":
public function get idPeople():Number
{
return objectPeople.idPeople;
}
// ...
trace(item["idPeople"]); // works now
I have a UI component that, for various reasons, I have to construct programatically. The component is a table of radio buttons grouped by column.
Right now, I'm constructing the column groups like so:
private function createGroupsForItemList(items: XMLList): void {
for each (var item: XML in items) {
var rbGroup: RadioButtonGroup = new RadioButtonGroup();
groups[item.#level.toString()] = rbGroup;
}
}
I'm trying to associate the RadioButton instances with the column groups like so:
private function createValueControl(item: XML): UIComponent {
var control: RadioButton = new RadioButton();
control.label = "";
control.group = groups[item.#level.toString()];
control.addEventListener(Event.SELECT, updateSelection);
return control;
}
I can see in the debugger that the control has an association to the group:
control.group == groups[item.#level.toString()]
However, I can see equally that the group does not know anything about the control:
group.radioButtons.length == 0
I imagine that this is because the setter for group in RadioButton is a dumb setter; all it does is copy to the variable, which doesn't do the magic that groupName does. However, I can't seem to find the value I should use to set the RadioButton.groupName property correctly.
So, in short, I'm stumped on how to get these bits to talk to each other. How do I do this?
-- EDIT --
It turns out that I can have the groups created and associated simply by setting the groupName property, but I can't get at the group to set up a selection listener; the group is NULL immediately after the setting process, which means that the second line below throws the Flex equivalent of an NPE:
control.groupName = groupNameForLevel(item);
control.group.addEventListener(Event.SELECT, updateSelection);
First instinct is that this issue has to do with invalidateDisplayList and when and how that is called. Of course, since issues related to that function are behind a number of Flex's quirks, I may just be scapegoating.
This is not the answer to your question per se, but it seems like it might actually work as an alternate solution.
RadioButtonGroups will initialize based on a IFlexDisplayObject. This means that you can do something like:
var c:HBox = new HBox();
var rbg:RadioButtonGroup = new RadioButtonGroup( c );
// do stuff with rbg.
c.addChild( new RadioButton() );
The problem is that it may not be the most practical answer, but it has the decided benefit of being a workable solution.
Setting groupName should work.
All I can suggest is to step through the group() getter of the RadioButton component and see where exactly it is failing. Are you programmatically creating the group too? If that's the case, maybe it isn't initialized fully yet.