I could not find any examples on the Web that show how to make hierarchical headers for JavaFX TableView, therefore, I do not provide any code. I will just post an image of what I want to achieve. Here it is:
It is highly required in many application to have such table grids. Unfortunately, I could not find any example for JavaFX. Thanks for help in advance!
It seems you are looking for nested columns.
You can add sub-columns to a main column to get hierarchical headers.
Here is a small example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class NestedColumns extends Application
{
#Override
public void start(Stage primaryStage) throws Exception
{
TableView<String> tableView = new TableView<String>();
TableColumn<String, String> nameColumn = new TableColumn<>("Name");
TableColumn<String, String> firstNameColumn = new TableColumn<>("First name");
TableColumn<String, String> lastNameColumn = new TableColumn<>("Last name");
nameColumn.getColumns().addAll(firstNameColumn, lastNameColumn);
tableView.getColumns().add(nameColumn);
Scene scene = new Scene(tableView);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Related
I use a combo that works nice. The only thing i would like to add is to diplay some items(~10) of this box by default at start . I tried to find this property but a hell to find this among all methods.
If somebody knows how to to that
I have the same question for Menubutton
Thanks
Just call show() on the ComboBox. Here is an example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ComboTest extends Application {
#Override
public void start(Stage stage) {
ComboBox<String> combo = new ComboBox<>();
for (int i = 1 ; i <= 20 ; i++) combo.getItems().add("Item "+i);
BorderPane root = new BorderPane();
root.setTop(combo);
Scene scene = new Scene(root, 650, 400);
stage.setScene(scene);
stage.show();
combo.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
The same thing works for MenuButton.
I am writing a program with javafx and tableView feature.
My purpose is when I click on a row of this table,another window opens and shows something but I don't know how to define something like setOnMouseClicked feature for my table.
I searched a lot but I coudn't find a simple way
This is my existing code that define table columns and rows.(rows are defined with observable feature)
package sample;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
TableView tableView = new TableView();
TableColumn<String, Account> column1 = new TableColumn<>("UserName");
column1.setCellValueFactory(new PropertyValueFactory<>("userName"));
column1.setMinWidth(100);
TableColumn<String, Account> column2 = new TableColumn<>("PassWord");
column2.setCellValueFactory(new PropertyValueFactory<>("passWord"));
column2.setMinWidth(100);
tableView.getColumns().add(column1);
tableView.getColumns().add(column2);
tableView.setItems(getAllAccounts());
VBox vbox = new VBox(tableView);
Scene scene = new Scene(vbox,200,200);
Stage window ;
window = primaryStage;
window.setScene(scene);
window.show();
}
private ObservableList<Account> getAllAccounts(){
ObservableList<Account> accounts= FXCollections.observableArrayList(Account.getAccounts());
return accounts;
}
}
You actually have two options:
Method 1:
Implement a click listener on the TableView and retrieve the item that was selected.
// Listen for a mouse click and access the selectedItem property
tblAccounts.setOnMouseClicked(event -> {
// Make sure the user clicked on a populated item
if (tblAccounts.getSelectionModel().getSelectedItem() != null) {
System.out.println("You clicked on " + tblAccounts.getSelectionModel().getSelectedItem().getUsername());
}
});
Method 2:
Create your own RowFactory for the TableView and handle your logic there. (I prefer this method)
// Create a new RowFactory to handle actions
tblAccounts.setRowFactory(tv -> {
// Define our new TableRow
TableRow<Account> row = new TableRow<>();
row.setOnMouseClicked(event -> {
System.out.println("Do your stuff here!");
});
return row;
});
Method #1 is the simplest approach and will work for most needs. You'll want to use method #2 for more complex needs, such as styling the individual rows, or to handle clicks on empty rows.
I'm getting tons of Unknown Source errors when updating content in my ComboBox.
Here is how I assign data to the combobox
DateBox.setItems(FXCollections.observableArrayList(dateList));
DateBox.getSelectionModel().selectFirst();
Then I add changelistener with this line
DateBox.valueProperty().addListener((obs, oldVal, newVal) -> listListener(newVal));
Now when I update the dateList and call the first segment of code again it works if I don't have that listener set. But if I call it with the listener set it spews out Unknown Source. Most likely I could bypass this by removing the listener before I update and then adding it back in but I couldn't find any way to do it. Also that wouldn't most likely be the correct way to do it.
How could I update the ComboBox (DateBox) without it causing all of those errors to popup. I assume the problem is that I change the content with setItems. I'd guess there is a way to cause the combobox to update but I couldn't find it.
Here is a runnable example where one combo box updates the other
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Arrays;
public class Main extends Application {
#Override
public void start(Stage stage) {
ArrayList<String> list = new ArrayList<>(Arrays.asList("1", "2", "3"));
ComboBox<String> comboBoxOne = new ComboBox<>();
ComboBox<String> comboBoxTwo = new ComboBox<>();
comboBoxOne.getItems().addAll(list);
comboBoxOne.setOnAction(event -> {
comboBoxTwo.getItems().clear();
ArrayList<String> listTwo = new ArrayList<>();
for (int i = 0; i < 5; i++)
listTwo.add(comboBoxOne.getValue());
comboBoxTwo.getItems().addAll(listTwo);
});
VBox vBox = new VBox(comboBoxOne, comboBoxTwo);
Scene scene = new Scene(vBox);
stage = new Stage();
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) { launch(args); }
}
I can't find a way to add a simple "String" row to my tableView.
In fact i can add a row but its content is not visible ...
Here is my code:
#FXML
private TableView<String> table;
#FXML
private TableColumn<String, String> table2;
public ObservableList<String> getLanes()
{
ObservableList<String> lanes=FXCollections.observableArrayList();
lanes.add("TEST");
return lanes;
}
Then:
table.setItems(getLanes()); //Not working
and
table.getItems().add("TEST"); //Not working
But without success.
I read that and that as well as other documentations but it did not help me to do it in this simple way.
EDIT:
Adding this line solved my problem:
table2.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue()));
Here is a simple application where we are trying to load a single value into a TableView column. It also shows how to set a cellValueFactory() on a table column.
tableColumn.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue()));
MCVE
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
TableView<String> tableView = new TableView<>();
TableColumn<String, String> tableColumn = new TableColumn<>("Name");
tableColumn.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue()));
tableView.getColumns().add(tableColumn);
ObservableList<String> items = FXCollections.observableArrayList("Itachi");
tableView.setItems(items);
VBox root = new VBox(tableView);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 300, 275);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
No matter what i do - the color of the row keeps unchanged and has a greyish color. The changes only work for when the TableView is in focus.
I have tried every other suggestion i found online, for example a solution from another thread:
.table-row-cell:selected { -fx-background-color: red; }
Nothing seems to work and affect the rows when not in focus.
Problem
You want to change the color of the selection bar for a focused and unfocused state of TableView
Solution
There is a -fx-selection-bar and -fx-selection-bar-non-focused definition in modena.css (default JavaFX style sheet). Both of them are in a section called Theming. So they are meant to be part of a changeable "global" theme. If you change them for the whole application, it will not only change the way TableView will color the selection, it will change even Menu's, List's etc. So you should be aware of it.
But from your comments above it should be clear, that you try to add the style by calling the method .setStyle() on the TableView instance. If you doing that, changing the color by this boths attributes will result in changing only the color of the TableView selection bar.
An Minimal, Complete, and Verifiable example could look like the following code:
TableRowColor.java
package tablerowcolor;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TableRowColor extends Application {
#Override
public void start(Stage primaryStage) {
ObservableList<Person> persons
= FXCollections.observableArrayList(
new Person("Sir", "Tobey"),
new Person("Admiral", "von Schneider"),
new Person("Mr.", "Pommeroy"),
new Person("Mr.", "Winterbottom"));
TableView<Person> tableView = new TableView<>(persons);
tableView.
setStyle("-fx-selection-bar: red; -fx-selection-bar-non-focused: salmon;");
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
tableView.getSelectionModel().clearAndSelect(0);
tableView.getColumns().setAll(firstNameCol, lastNameCol);
Button btn = new Button();
btn.setText("Focus me");
VBox root = new VBox();
root.getChildren().addAll(tableView, btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Selection Row Color");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public class Person {
private final StringProperty firstName
= new SimpleStringProperty(this, "firstName");
public void setFirstName(String value) {
firstNameProperty().set(value);
}
public String getFirstName() {
return firstNameProperty().get();
}
public StringProperty firstNameProperty() {
return firstName;
}
private final StringProperty lastName
= new SimpleStringProperty(this, "lastName");
;
public void setLastName(String value) {
lastNameProperty().set(value);
}
public String getLastName() {
return lastNameProperty().get();
}
public StringProperty lastNameProperty() {
return lastName;
}
public Person(String firstName, String lastName) {
this.firstName.set(firstName);
this.lastName.set(lastName);
}
}
}
Netbeans Project Structure
The JavaFX Appliction Project in Netbeans should look like this:
Working Application
The working application will look like this:
Setting Style in Scene Builder
In Scene Builder you be able to set the same style to a TableView by open the Inspector, than Properties of the TableView and add the following to the style boxes: