I am experimenting with displaying an ArrayList of strings in a javaFX tablecolumn. I have read many examples which go into details about displaying and dynamically modifying custom classes etc, but I just want to see a fundamental implementation of a column displaying arraylist data.
I have tried various methods, involving using an ObservableList, but my interest is more basic than that.
Suggestions are greatly appreciated.
Here is my code:
Main:
package testCram;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableView;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("mainWindow.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
Controller:
package testCram;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import java.util.*;
public class Controller {
//instances of all controls
#FXML
public TableView<String> table;
#FXML
public TableColumn<String , String> column1;
public void setData(){
Collection<String> list = new ArrayList<>();
list.add("String1");
list.add("String2");
list.add("String3");
list.add("String4");
list.add("String5");
list.add("String6");
//I understand that you need to use 'setCellValueFactory' but I don't see what is needed to extract the values from list.
column1.setCellValueFactory(cellData ->
new ReadOnlyStringWrapper(cellData.getValue()));
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="- Infinity" minWidth="-Infinity" prefHeight="718.0" prefWidth="569.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="testCram.Controller">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Pane prefHeight="718.0" prefWidth="596.0">
<children>
<TableView fx:id="table" layoutX="75.0" layoutY="99.0" prefHeight="200.0" prefWidth="399.0">
<columns>
<TableColumn fx:id="column1" prefWidth="100.0" text="String" />
</columns>
</TableView>
</children></Pane>
</children>
</GridPane>
I worked on this further , and I will post my own answer:
In order for the column to disaply data, you must instruct the table to populate the data:
Add the line:
table.getItems().addAll(list);
under
column1.setCellValueFactory(cellData ->
new ReadOnlyStringWrapper(cellData.getValue()));
I hope this helps someone else who gets stuck.
Related
So I am new to JavaFX, and I am trying to do an app for school and I've been reading lots of related posts, but I can't seem to figure it how to do for my own case. Here Is a picture
So the big screen is my main screen and the one with the red border are children of the Vbox. And for the child, I have a separate FXML and a controller. When I hit the "Close Deal" button I want to remove the specific child of the Vbox.
I know I should do parent.getChildren().remove(specific_child_node); The problem is I don't know how to get the specific_child_node for the child for which has been the "Closed Deal" button pressed. The close button is in the child's controller and the Vbox is in the main page controller
Has anyone any idea of how I could do it?
I created a small example to show how you could do it:
MainController Class:
package sample;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import java.io.IOException;
public class MainController {
#FXML
private VBox middleVBox;
#FXML
public void handleAddChildBtnClick() {
FXMLLoader loader = new FXMLLoader(getClass().getResource("deal.fxml"));
GridPane root = null;
try {
root = loader.load();
} catch (IOException ex) {
ex.printStackTrace();
}
if (root == null) return;
// Get the controller instance:
DealController controller = loader.getController();
// Set a reference for the parent vbox:
controller.setParent(middleVBox);
middleVBox.getChildren().add(1, root);
}
}
FXML File "main.fxml":
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<GridPane alignment="center" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainController">
<children>
<VBox style="-fx-background-color: black;">
<children>
<Label text="Welcome, Client" textFill="WHITE" />
</children>
</VBox>
<VBox fx:id="middleVBox" GridPane.columnIndex="1">
<children>
<Label text="Generate Public Auction" />
<VBox>
<children>
<Label text="dfgh" textFill="#1aab0d" />
</children>
</VBox>
</children>
</VBox>
<VBox GridPane.columnIndex="2">
<children>
<Button mnemonicParsing="false" onAction="#handleAddChildBtnClick" text="Add Child" />
</children>
</VBox>
</children>
<columnConstraints>
<ColumnConstraints />
<ColumnConstraints />
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints prefHeight="200.0" />
</rowConstraints>
</GridPane>
DealController Class:
package sample;
import javafx.fxml.FXML;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
public class DealController {
#FXML
private GridPane dealRoot;
private VBox parent;
#FXML
public void handleCloseDealBtnClick() {
parent.getChildren().remove(dealRoot);
}
void setParent(VBox parent) {
this.parent = parent;
}
}
FXML File "deal.fxml":
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane fx:id="dealRoot" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.DealController">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" />
<ColumnConstraints hgrow="SOMETIMES" />
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="SOMETIMES" />
<RowConstraints vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="cvbn" textFill="#008612" />
<Button mnemonicParsing="false" onAction="#handleCloseDealBtnClick" text="Close Deal" GridPane.columnIndex="1" GridPane.rowIndex="1" />
</children>
</GridPane>
Main Class:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Creating a JavaFX GUI application and can't get ListView's to work on my Controller class. Here is the code:
MP3.Java
package mp3player;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
public class MP3 extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("mp3player.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
MP3Controller.java
package mp3player;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ListView;
public class MP3Controller {
ObservableList<String> songs = FXCollections.observableArrayList("Song 1", "Song 2");
ListView<String> songsView = new ListView<String>();
songsView.setItems(songs);
}
mp3player.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane alignment="center" hgap="10" scaleY="1.0" vgap="10" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="mp3player.MP3Controller">
<columnConstraints>
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="200.0" minHeight="171.0" prefHeight="200.0" />
<RowConstraints maxHeight="29.0" minHeight="0.0" prefHeight="0.0" />
</rowConstraints>
<children>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<HBox prefHeight="50.0" prefWidth="100.0" />
<HBox prefHeight="100.0" prefWidth="200.0">
<children>
<ListView fx:id="songsView" prefHeight="67.0" prefWidth="146.0" />
</children></HBox>
<HBox prefHeight="47.0" prefWidth="100.0" />
</children>
</VBox>
</children>
</GridPane>
Any help would be greatly appreciated. I am unsure as to what's happening here as I am following the docs pretty closely, I have a suspicion it might be to do with importing javafx? If so, you could try running the script in your machine and seeing if it works. Thanks everyone!
try following
in your code you are trying to set values outside method or constructor that why it is not allowing you to set value
you can do by creating constructor or method
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ListView;
public class MP3Controller {
ObservableList<String> songs = FXCollections.observableArrayList("Song 1", "Song 2");
ListView<String> songsView = new ListView<String>();
MP3Controller() {
songsView.setItems(songs);
}
}
I am using the AnimateFX library, which is just a compilation of node animations.
AnimationFX fx = new ZoomOut(background);
fx.setOnFinished(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
//background.setScaleX(1.0D);
//background.setScaleY(1.0D);
//background.setScaleZ(1.0D);
//background.setOpacity(1.0D);
// -- some wait function --
Stage stage = (Stage) background.getScene().getWindow();
stage.setIconified(true);
}
});
fx.play();
This block results in the window minimizing, but now the window is both transparent and minuscule.
If I uncomment the background node transformations and comment stage.setIconified(true), the animation ends with the window returning to full size, as expected.
However, if I uncomment the background node transformations without commenting stage.setIconified(true), the program minimizes without running the background node transformations.
I assumed it was some synchronizing issue, but adding a wait function in the // -- some wait function -- locale simply resulted in the program waiting without the background node transformations running, and then minimizing.
A bit confused as to why this happens.
EDIT
Here is some runnable code that replicates the problem. I find that if I replace the ImageView with a Button and change the event to that of a button action, then the problem no longer occurs.
package app;
import animatefx.animation.AnimationFX;
import animatefx.animation.ZoomOut;
import javafx.fxml.FXML;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Controller {
#FXML
VBox background;
#FXML
ImageView minimize;
#FXML
public void onMinimizeClicked(MouseEvent mouseEvent) {
AnimationFX fx = new ZoomOut(background);
fx.setSpeed(0.75D);
fx.setResetOnFinished(true);
Stage stage = (Stage) background.getScene().getWindow();
fx.setOnFinished(actionEvent -> stage.setIconified(true));
fx.play();
}
}
Edit #2
Here is my main class
package app;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.initStyle(StageStyle.TRANSPARENT);
Scene scene = new Scene(root);
scene.setFill(Color.TRANSPARENT);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Here is my sample.fxml file
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<VBox fx:id="background" prefHeight="500.0" prefWidth="400.0" style="-fx-background-color: transparent" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="app.Controller">
<AnchorPane fx:id="content" prefHeight="464.0" prefWidth="500.0" style="-fx-background-color: #3D4956
" VBox.vgrow="ALWAYS">
<children>
<ImageView fx:id="minimize" fitHeight="150.0" fitWidth="200.0" layoutX="100.0" layoutY="175.0" onMouseClicked="#onMinimizeClicked" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>
</VBox>
I don't know the cause of this behaviour but I managed to solve it by adding an image inside the ImageView in the FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<VBox fx:id="background" prefHeight="500.0" prefWidth="400.0" style="-fx-background-color: transparent" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="sample.Controller">
<AnchorPane fx:id="content" prefHeight="464.0" prefWidth="500.0" style="-fx-background-color: #3D4956
" VBox.vgrow="ALWAYS">
<children>
<ImageView fx:id="minimize" fitHeight="150.0" fitWidth="200.0" layoutX="100.0" layoutY="175.0" onMouseClicked="#onMinimizeClicked" pickOnBounds="true" preserveRatio="true" >
<Image url="file:image/iamge.png"/>
</ImageView>
</children>
</AnchorPane>
</VBox>
I'm using Scene Builder for this example, I have a listview and I want it to be already filled when I run the application, but I don't seem to find a way to do it, it simply dosn't work and the listview dosn't appear.
Here's my FXMLTasker.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="557.0" prefWidth="1012.0" style="-fx-background-color: #0288D1;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<SplitPane dividerPositions="0.5" layoutX="-8.0" layoutY="35.0" prefHeight="529.0" prefWidth="1027.0" style="-fx-background-color: #EEEEEE;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="28.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ListView fx:id="list_todo" editable="true" layoutX="14.0" layoutY="14.0" prefHeight="508.0" prefWidth="485.0" />
</children></AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="527.0" prefWidth="640.0" />
</items>
</SplitPane>
</children>
</AnchorPane>
Here's my Main.class
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
/**
*
* #author samuel
*/
public class JavaFXApplication3 extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLTasker.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
And here's my Controler
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javax.swing.JOptionPane;
/**
*
* #author samuel
*/
public class FXMLDocumentController implements Initializable {
#FXML
private ListView list_todo;
private ObservableList<String> items = FXCollections.observableArrayList();
#Override
public void initialize(URL url, ResourceBundle rb) {
list_todo.setItems(items);
items.add("First task");
items.add("Second task");
}
}
The problem is that the list dosn't appear when I run the application, it should be simple but for some reason it dosn't work. Anyone can find why?
Specify the controller to your fxml file with all other details as below,
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="557.0" prefWidth="1012.0" style="-fx-background-color: #0288D1;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="FXMLDocumentController">
</AnchorPane>
Add controller class with full specified name (with package name, if u have any)
My application functions as intended, but there are display issues when you run it. When it runs, the java window pops up with the correct window size, but the controls within the window are huge for some reason. The only way I've been able to work around this and get them to display at their normal size is if I drag the window over to one of my other monitors, drop it (at which point the oversized controls shift around a bit), and then drag it back to the laptop monitor. Then the controls shrink back and display properly.
If I drag it back over to one of my other monitors, however, the controls blow up again.
I'm using IntelliJ 14 and Scene Builder 2.0 running on MacOSX 10.10.3.
FXML File:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="332.0" prefWidth="404.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="408.0" minWidth="10.0" prefWidth="408.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button id="btnTest" contentDisplay="CENTER" mnemonicParsing="false" onAction="#foo" prefHeight="74.0" prefWidth="275.0" text="Generate Encryption Key" GridPane.halignment="CENTER">
<GridPane.margin>
<Insets />
</GridPane.margin>
</Button>
<Label fx:id="lblTop" alignment="TOP_CENTER" contentDisplay="TOP" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="TOP">
<GridPane.margin>
<Insets top="35.0" />
</GridPane.margin>
</Label>
<TextField fx:id="txtKey" alignment="CENTER" editable="false" GridPane.rowIndex="1" />
</children>
</GridPane>
Controller:
package sample;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import java.beans.EventHandler;
import java.util.ResourceBundle;
import java.util.Random;
import java.awt.*;
import java.net.URL;
public class Controller implements Initializable{
#FXML
private TextField txtKey;
#FXML
private Label lblTop;
#FXML
private Button btnButton;
Random rnd = new Random();
private char[] pool = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9'};
#Override
public void initialize(URL fxmlFileLocation, ResourceBundle resources){
assert btnButton != null : "fx:id=\"txtKey\" was not injected: check your FXML file 'sample.fxml'.";
}
public void foo (ActionEvent actionEvent){
String key = "";
for (int i = 0; i < 32; i++){
key = key + pool[rnd.nextInt(36)];
}
lblTop.setText("Your Encryption Key is:");
txtKey.setText(key);
}
}
Main:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Encryption Key Generator");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
UPADATE:
This problem seems to be an IntelliJ issue. I decided to try to build my application and after I ran the JAR, it worked perfectly. The application's logic functioned and the aforementioned display problems weren't occurring anymore.
It does do a little resizing jitter when moving between monitors, but it never displays the elements incorrectly.