Griffon 2.10.0
FXML:
<Button layoutX="172.0" layoutY="45.0" JavaFXUtils.griffonActionId="click2"
mnemonicParsing="false" text="Test"
prefWidth="200.0"
/>
TestView.groovy:
void initUI() {
builder.application(title: application.configuration['application.title'], name: "settingsWindow",
centerOnScreen: true, resizable: false) {
scene {
def node = loadFromFXML("views/test.fxml")
connectActions(node, controller)
inputx.textProperty().bindBidirectional(model.inputProperty())
fxml node
}
}
}
Shows this button with the text "Click2"
Why is the text="Test"configuration in the FXML overwritten by the griffonActionId name?
It works when I use this in FXML:
<Button fx:id="btn1" ...
And in TestView.groovy:
#FXML private Button btn1
...
btn1.text = 'Test'
This displays:
Is this the proper the way to set the button text?
This is expected behavior. Buttons configured via Griffon actions will bind their properties to action properties. The button's text is bound to the action's name by default. You can overrode this behavior by setting the button's text explicitly in code, like you did.
Related
I want my table to change the color of a row depending on a column is checked or not or when a button is clicked.
I searched for solutions but it never worked the way I wanted to. I am happy for every keyword or help you have. Maybe I was just looking for the wrong thing?
My code looks like this:
public class Cellexample_presenter implements Initializable{
#FXML
TableColumn<ExampleData, Boolean> checkcol;
#FXML
TableView<ExampleData> testtable;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
checkcol.setText("Check");
ObservableList<ExampleData> exList = FXCollections.observableArrayList();
exList.add(new ExampleData(true));
exList.add(new ExampleData(false));
checkcol.setCellValueFactory(
new Callback<CellDataFeatures<ExampleData, Boolean>, ObservableValue<Boolean>>() {
#Override
public ObservableValue<Boolean> call(CellDataFeatures<ExampleData, Boolean> param) {
return param.getValue().checkProperty();
}
});
testtable.setItems(exList);
testtable.setEditable(true);
checkcol.setCellFactory(CheckBoxTableCell.forTableColumn(checkcol));
}
#FXML
private void clicked() {
ObservableList<ExampleData> tabledata = testtable.getItems();
for (ExampleData e : tabledata) {
System.out.println(e.isCheck());
}
}
}
I found solutions with another setCellFactory, but I doesn't seem to work when I already have a setCellFactory and I was unable to combine then. Moreover there is still the connection missing to the
change of the Checkbox.
Another solution I came across was something with a PseudoClass but this also required another setCellFactory
The method private void clicked() I used to check if the data in my object was really changed.
Also I want as another Feature to click a Button and change the color of rows with wrong data.
I was hoping there was a way to iterate trough the table, check the data and if something doesn't equals something else. It changes color.
Like this in pseudo-code
for (tablerow row: table)
if (row.ischecked()) {
row.changecolor();
}
Here is the .FXML for putting everything together:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<AnchorPane prefHeight="254.0" prefWidth="700.0" xmlns="http://javafx.com/javafx/11.0.1"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="pathToFXML/Cellexample_presenter">
<children>
<Pane layoutX="-269.0" prefHeight="315.0" prefWidth="700.0" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<TableView fx:id="testtable" layoutX="142.0" layoutY="27.0" prefHeight="200.0"
prefWidth="340.0">
<columns>
<TableColumn fx:id="checkcol" prefWidth="75.0" text="C1" />
</columns>
</TableView>
<Button fx:id="checkbtn" layoutX="70.0" layoutY="36.0" mnemonicParsing="false"
onAction="#clicked" text="isChecked" />
</children>
</Pane>
</children>
</AnchorPane>
You can use a custom TableRow for this. I also prefer to use CSS and PseudoClasses to manage the color of rows.
What needs to happen here is that the row needs to know if the checked property in the ExampleData instance currently displayed by the row changes, and needs to change color if that happens.
Of course, for any given table row, the ExampleData instance displayed by that table row may also change (e.g. if the underlying data list changes, or if the user scrolls the table, etc.)
So the basic strategy here is:
Create a listener that observes the current item's checked property, and updates the pseudoclass state if it does (which in turn causes the style to change). In the code below I call this listener checkListener.
If the item displayed by the row changes, we need to stop observing the old item's checked property and start observing the new item's checked property instead. This can be achieved via a listener on the item property of the table row. That listener on the itemProperty can then remove the checkListener from the checkedProperty of the old item (if there was an old item), and add it to the checkedProperty of the new item (if there is one). It also needs to update the pseudoclass state according to the current state of the new item's checkedProperty.
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// Existing code....
testTable.setRowFactory(tv -> new TableRow<ExampleData>() {
private final PseudoClass checkedPC = PseudoClass.getPseudoClass("checked");
private final ChangeListener<Boolean> checkListener = (obs, wasChecked, isNowChecked) ->
pseudoClassStateChanged(checkedPC, isNowChecked);
{
itemProperty().addListener((obs, oldItem, newItem) -> {
if (oldItem != null) {
oldItem.checkedProperty().removeListener(checkListener);
}
if (newItem == null) {
pseudoClassStateChanged(checkedPC, false);
} else {
pseudoClassStateChanged(checkedPC, newItem.isChecked());
newItem.checkedProperty().addListener(checkListener);
}
});
}
});
}
And then in your external CSS file include
.table-row-cell:checked {
-fx-background-color: red ;
}
I can't work out how to set the value of a Label defined in FXML from the controller initializer.
In my FXML I have (in a HBox):
<Label text="Label: " />
<Label fx:id="myLabel" />
And in the controller I have:
#FXML
private Label myLabel;
#FXML
private void initialize() {
myLabel.setText("Hello!");
}
The label stays blank when I run the program. What am I doing wrong? (I suspect initialize() is not running - the Eclipse debugger doesn't stop in it when I set a breakpoint - but I'm not sure and I can't get JavaFX to respect console printf statements for me to do debug print statements.)
In my program i have a tabPane with each tab having in own FXML file and controller .I have loaded the FXML file for tab 2 (Schedular).I`m trying to call a function in my child controller (Scheduler) from my parent controller(FXML Document) . When i load the controller using FXML Loader it returns a null. How can i solve this .
Here is my main code:
Main FXMLDocument :
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" fx:id="AnchorPane" prefHeight="600" prefWidth="800" xmlns="http://javafx.com/javafx/8.0.65" fx:controller="showprojavafxml.FXMLDocumentController">
<children>
The FXMLLoader only instantiates the controller when it loads the fxml file (this has to be the case, since the controller class is specified in the fxml file...). Since you never call load() on the loader, the controller is never created.
It looks like you are referencing the FXML file twice through two different mechanisms: once in FXMLDocumentController.initialize(), where you create a FXMLLoader whose location is set to the fxml file, and once in the main FXML document itself, via a <fx:include>. The <fx:include> is causing the UI defined in Scheduler.fxml to be displayed; the FXMLLoader you create in the initialize() method is not (because you never call load() and display the result).
To reference a controller for an included fxml, use the "Nested controller" technique.
First, add an fx:id to your fx:include:
<Tab fx:id="tab2" text="Scheduler" >
<fx:include fx:id="scheduler" source="Scheduler.fxml" />
</Tab>
Now you can inject the controller into a field whose name is the fx:id with the text "Controller" appended:
public class FXMLDocumentController {
#FXML
private SchedulerController schedulerController ;
#Override
public void initialize(URL url, ResourceBundle rb) {
schedulerController.refreshList();
}
}
Somewhere inside my FXML, I have this:
<fx:define>
<ToggleGroup fx:id="toggleGroup1"/>
</fx:define>
<Menu fx:id="toggleMyView" text="%MyView">
<items>
<RadioMenuItem text="%hide"
selected="true"
onAction="#handleLoadComponent"
toggleGroup="toggleGroup1"/>`
Somehow I get the error:
Unable to coerce toggleGroup1 to class javafx.scene.control.ToggleGroup
But why?
What I'm trying to do is to create a Menu containing several of RadioMenuItem which are all in the same ToggleGroup. How can I add them to the toggle group in my FXML file?
You have to write
toggleGroup="$toggleGroup1"
If you are using SceneBuilder then set the field ToggleGroup in properties to the name of the group.
<AnchorPane>
<TreeView fx:id="locationTreeView" focusTraversable="true" prefHeight="449.0" prefWidth="725.0" style="#tree
{
-fx-border-style:solid;
-fx-border-width:1px;
-fx-border-color:#ffffff;
}"/>
In the above fxml code I want to add one more <TreeView> but through the controller. How can I do this?
You will have to:
Give a fx:id to the AnchorPane:
<AnchorPane fx:id="theAnchorPane">
Add the corresponding field in the controller:
#FXML private AnchorPane theAnchorPane;
From the code that performs the addition you have to:
Create the new TreeView however you like:
TreeView newTreeView = ...;
Add it to the childen of the AnchorPane, possibly with some constraints:
theAnchorPane.getChildren().add(newTreeView);
AnchorPane.setTopAnchor(newTreeView, ...); // etc