Can someone suggest how to dynamicly add TableColumn to TableView in JavaFX?
I need to display class Row at tableView, but I know count of Nodes after another action. I've got trouble when I tried to use StringProperty from Node to set CellValueFactory. From Node class I need to display only reserved and reliability.
public class Row {
private int step;
private Node[] nodes;
private double p = 1;
private double c;
private StringProperty stepProperty;
private StringProperty pProperty;
private StringProperty cProperty;
Row(int step, Node[] nodes, double c){
this.step = step;
this.nodes = nodes;
for (Node node:
nodes) {
p *= node.getReliability();
}
this.c = c;
}
public int getStep() {return step;}
public Node getNode(int index) {return nodes[index];}
public double getP() {return p;}
public double getC() {return c;}
public StringProperty stepProperty() {
this.stepProperty = new SimpleStringProperty(step + "");
return stepProperty;
}
public StringProperty pProperty() {
this.pProperty = new SimpleStringProperty(p + "");
return pProperty;
}
public StringProperty cProperty() {
this.cProperty = new SimpleStringProperty(c + "");
return cProperty;
} }
public class Node {
private StringProperty reserved;
private StringProperty reliability;
private StringProperty price;
Node(String reserved, String reliability, String price){
this.reserved = new SimpleStringProperty(reserved);
this.reliability = new SimpleStringProperty(reliability);
this.price = new SimpleStringProperty(price);
}
public StringProperty reliabilityProperty() {
return reliability;
}
public StringProperty priceProperty() {
return price;
}
public StringProperty reservedProperty() {
return reserved;
}
public double getReliability(){
return Double.parseDouble(reliability.get());}
public int getPrice(){return Integer.parseInt(price.get());}
public int getReserved(){return Integer.parseInt(reserved.get());}
}
You just need something along the following lines:
TableView<Row> table = new TableView<>();
int numNodes = ... ;
TableColumn<Row, Number> stepCol = new TableColumn<>("Step");
stepCol.setCellValueFactory(cellData -> cellData.getValue().stepProperty());
table.getColumn().add(stepCol);
for (int n = 0 ; n < numNodes ; n++) {
final int nodeIndex = n ;
TableColumn<Row, String> reservedCol = new TableColumn<>("Reserved - "+nodeIndex);
reservedCol.setCellValueFactory(cellData -> cellData.getValue().getNode(nodeIndex).reservedProperty());
TableColumn<Row, String> reliabilityCol = new TableColumn<>("Reliability - "+nodeIndex);
reliabilityCol.setCellValueFactory(cellData -> cellData.getValue().getNode(nodeIndex).reliabilityProperty());
table.getColumns().add(reservedCol);
table.getColumns().add(reliabilityCol);
}
TableColumn<Row, String> pCol = new TableColumn<>("P");
stepCol.setCellValueFactory(cellData -> cellData.getValue().pProperty());
table.getColumn().add(pCol);
TableColumn<Row, String> cCol = new TableColumn<>("C");
stepCol.setCellValueFactory(cellData -> cellData.getValue().cProperty());
table.getColumn().add(cCol);
Related
i have to code the Dijkstra algorithm. We got a blueprint for this project. Meaning we were told the classes, field variables and methods we have to use.
We have to read the adjacency matrix from a csv file and then use the Dijkstra algorithm.
My problem already begins in in filling the TreeSet edges...
The problem occurs in Graph.class on line 45 when i try to add the Edges.
Example for the csv :
;A;B;C;D;E;F;G;H
A;;1;3;1;;;;
B;1;;;;3;3;;
C;3;;;1;;;1;
D;1;;1;;1;;2;
E;;3;;1;;1;;5
F;;3;;;1;;;1
G;;;1;2;;;;1
H;;;;;5;1;1;
=>
A -> (B,1), (C,3), (D,1)
B -> (A,1), (E,3), (F,3)
C -> (A,3), (D,1), (G,1)
D -> (A,1), (C,1), (E,1), (G,2)
E -> (B,3), (D,1), (F,1), (H,5)
F -> (B,3), (E,1), (H,1)
G -> (C,1), (D,2), (H,1)
H -> (E,5), (F,1), (G,1)
Could somebody look where my problem is ? My indices are correct i checked them with some sout.
Just need help with filling in the TreeSet! I want to try the Dijkstra part myself.
public class Edge implements Comparable<Edge>{
private int distance;
private Node neighbour;
public Edge(int distance, Node neighbour) {
this.distance = distance;
this.neighbour = neighbour;
}
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
public Node getNeighbour() {
return neighbour;
}
public void setNeighbour(Node neighbour) {
this.neighbour = neighbour;
}
#Override
public int compareTo(Edge o) {
if (this.neighbour.getId().equals(o.neighbour.getId())){
return 0;
}else{
return -1;
}
}
}
import java.util.TreeSet;
public class Node {
private String id;
private TreeSet<Edge> edges;
private int distance;
private Node previous;
private boolean isVisited;
public Node(String id) {
this.id = id;
this.edges = new TreeSet<>();
}
public Node(String id, int distance){
this.id = id;
this.distance = distance;
}
#Override
public String toString() {
return "Node{" +
"id='" + id + '\'' +
", edges=" + edges +
", distance=" + distance +
", previous=" + previous +
", isVisited=" + isVisited +
'}';
}
public String getPath(){
return null;
}
public void addEdge(Edge e){
edges.add(e);
}
public void init(){
}
public void setStartNode(Node n){
}
public void visit(Node n){
}
public String getId() {
return id;
}
}
import java.io.File;
import java.io.FileNotFoundException;
import java.nio.file.Path;
import java.util.*;
public class Graph {
private PriorityQueue pq;
private ArrayList<Node> nodes;
public Graph(){
this.pq = new PriorityQueue();
this.nodes = new ArrayList();
}
public void readGraphFromAdjacencyMatrixFile(Path file) throws FileNotFoundException {
Scanner sc = new Scanner(new File(String.valueOf(file)));
ArrayList<String> s = new ArrayList<>();
ArrayList<Character> nodesCharacter = new ArrayList<Character>();
while (sc.hasNext()){
s.add(sc.next());
}
sc.close();
for(char ch: s.get(0).toCharArray()){
if (ch != ';' && ch != ',') {
nodes.add(new Node(Character.toString(ch)));
nodesCharacter.add(ch);
}
}
ArrayList<Node> nodes2 = getNodes();
String node = "";
int index = 0;
for (int i = 1; i < s.size(); i++){
int cnt = -2;
char[] chArray = s.get(i).toCharArray();
for (int j = 0; j < chArray.length; j++){
if(j == 0){
node = String.valueOf(chArray[j]);
index = indexOfNode(String.valueOf((chArray[j])));
}
else if (j >= 2){
if (Character.isDigit(chArray[j])){
int neighbourIndex = indexOfNode("" + nodesCharacter.get(cnt));
Edge e = new Edge(Character.getNumericValue(chArray[j]), nodes.get(neighbourIndex));
nodes.get(index).addEdge(e);
cnt--;
}
}
cnt ++;
}
}
}
public String getAllPAths(){
return null;
}
public void calcWithDijkstra(String startNodeId){
}
public ArrayList<Node> getNodes() {
return nodes;
}
public int indexOfNode(String id){
int cnt = 0;
for (int i = 0; i < nodes.size(); i++){
if (id.equals(nodes.get(i).getId())){
return cnt;
}
cnt++;
}
return -1;
}
}
This question already has an answer here:
Javafx TableView not showing data
(1 answer)
Closed 4 years ago.
Purpose: To browse for a folder and select it. And to add its properties in columns.
For example, the name of the folder goes in the name column, the location goes in the location, and etc.
For some reason, I am not able to add the properties of selected folder into the table named folderTable. The program seem to know that something is in the first row after I add a folder but it doesn't display the folder itself.
I am learning, so any help is appreciated.
public class mainClass2 extends Application {
Stage window;
TableView<syncedFolders> folderTable;
Button file, edit, view, addFolder, printInfo, close, deleteFolder;
private String name, location, dateModified;
private long size;
private double printSize = 0, bytes = 0, kilobytes = 0, megabytes = 0, gigabytes = 0, tempSize = 0;
private String printSizeAb = "";
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
HBox topMenu = new HBox();
file = new Button("File");
edit = new Button("Edit");
view = new Button("View");
topMenu.getChildren().addAll(file, edit, view);
VBox leftMenu = new VBox();
printInfo = new Button("Print folder info");
printInfo.setOnAction(e -> {
round(printSize, 1);
System.out.println("Name: " + name);
System.out.println("Location: " + location);
System.out.println("Last Modified: " + dateModified);
System.out.println("Size: " + tempSize + printSizeAb);
});
leftMenu.getChildren().add(printInfo);
HBox botBox = new HBox();
addFolder = new Button("Add Folder");
deleteFolder = new Button("Delete Folder");
close = new Button("Exit");
addFolder.setOnAction(e -> {
DirectoryChooser chooser = new DirectoryChooser();
chooser.setTitle("JavaFX Projects");
File defaultDirectory = new File("D:\\");
chooser.setInitialDirectory(defaultDirectory);
File selectedDirectory = chooser.showDialog(window);
name = selectedDirectory.getName();
location = selectedDirectory.toString();
size = getFolderSize(selectedDirectory);
bytes = size;
kilobytes = (bytes / 1024);
megabytes = (kilobytes / 1024);
gigabytes = (megabytes / 1024);
if (bytes < 1024) {
printSize = kilobytes;
printSizeAb = " KB";
} else if (bytes >= 1024 && bytes < Math.pow(1024, 3)) {
printSize = megabytes;
printSizeAb = " MB";
} else // if (bytes >= Math.pow(1024, 2) && bytes <= Math.pow(1024, 3))
{
printSize = gigabytes;
printSizeAb = " GB";
}
addFolder();
lasModifiedDate();
});
// Name column
TableColumn<syncedFolders, String> nameCol = new TableColumn<>("Name");
nameCol.setMinWidth(200);
nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
// location column
TableColumn<syncedFolders, String> locationCol = new TableColumn<>("Location");
locationCol.setMinWidth(200);
locationCol.setCellValueFactory(new PropertyValueFactory<>("location"));
// date modified column
TableColumn<syncedFolders, String> dateModifiedCol = new TableColumn<>("Last Modified");
dateModifiedCol.setMinWidth(200);
dateModifiedCol.setCellValueFactory(new PropertyValueFactory<>("dateModified"));
// size column
TableColumn<syncedFolders, Double> sizeCol = new TableColumn<>("Size");
sizeCol.setMinWidth(200);
sizeCol.setCellValueFactory(new PropertyValueFactory<>("size"));
folderTable = new TableView<>();
folderTable.setItems(getSyncedFolders());
folderTable.getColumns().addAll(nameCol, locationCol, dateModifiedCol, sizeCol);
close.setOnAction(e -> closeProgram());
botBox.setPadding(new Insets(10, 10, 10, 10));
botBox.setSpacing(10);
botBox.getChildren().addAll(addFolder, deleteFolder, close);
BorderPane borderPane = new BorderPane();
borderPane.setTop(topMenu);
borderPane.setLeft(leftMenu);
borderPane.setCenter(folderTable);
borderPane.setBottom(botBox);
Scene scene = new Scene(borderPane, 800, 600);
window.setScene(scene);
window.setTitle("the title");
window.show();
window.setOnCloseRequest(e -> {
e.consume();
closeProgram();
});
}
// Get all of the products
public ObservableList<syncedFolders> getSyncedFolders() {
ObservableList<syncedFolders> folders = FXCollections.observableArrayList();
folders.add(new syncedFolders("Folder", "D://", "July", 3.4));
folders.add(new syncedFolders(name, location, dateModified, tempSize));
return folders;
}
public void addFolder() {
round(printSize, 1);
folderTable.setItems(getSyncedFolders());
folderTable.getItems().add(new syncedFolders(name, location, dateModified, tempSize));
}
private double round(double value, int precision) {
int scale = (int) Math.pow(10, precision);
tempSize = (double) Math.round(value * scale) / scale;
return tempSize;
}
public String lasModifiedDate() {
Path path = Paths.get(location);
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy - hh:mm:ss");
FileTime fileTime = null;
try {
fileTime = Files.getLastModifiedTime(path);
} catch (IOException e1) {
System.out.println("Cannot get the last modified time");
}
dateModified = dateFormat.format(fileTime.toMillis());
return dateModified;
}
private long getFolderSize(File folder) {
long length = 0;
File[] files = folder.listFiles();
int count = files.length;
for (int i = 0; i < count; i++) {
if (files[i].isFile()) {
length += files[i].length();
} else {
length += getFolderSize(files[i]);
}
}
return length;
}
private void closeProgram() {
/**
* Alert alert = new Alert(AlertType.CONFIRMATION); alert.setTitle("Confirmation
* Dialog"); alert.setHeaderText("You are about to exit");
* alert.setContentText("Are you ok with this?");
*
* Optional<ButtonType> result = alert.showAndWait(); if (result.get() ==
* ButtonType.OK)
**/
window.close();
}
}
public class syncedFolders {
private String name, location, dateModified;
private double size;
public syncedFolders() {
this.name = "";
this.location = "";
this.dateModified = "";
this.size = 0;
}
public syncedFolders(String s) {
this.name = s;
}
public syncedFolders(String name, String location, String dateModified, double size) {
this.name = name;
this.location = location;
this.dateModified = dateModified;
this.size = size;
}
public String getname() {
return name;
}
public void setname(String s) {
name = s;
}
public String getlocation() {
return location;
}
public void setlocation(String s) {
location = s;
}
public String getdateModified() {
return dateModified;
}
public void setdateModified(String s) {
dateModified = s;
}
public double getsize() {
return size;
}
public void setsize(double d) {
size = d;
}
}
The TableView uses Properties and Bindings to display the data in each column. You have a CellValueFactory installed on the columns, but you're populating it usinga PropertyValueFactory.
That is the right way to do it, but there's a problem with your syncedFolders class. The PropertyValueFactory looks into your syncedFolders class and tries to find a Property with the name you specified. The problem is that you do not have any properties defined:
private String name, location, dateModified;
private double size;
These are fields, not properties.
You will need to rewrite your syncedFolders class to have observable properties instead, like this:
private SimpleStringProperty name = new SimpleStringProperty();
Do that for each of your fields, update your constructor and setters/getters and try again!
public class syncedFolders {
private SimpleStringProperty name = new SimpleStringProperty();
private SimpleStringProperty location = new SimpleStringProperty();
private SimpleStringProperty dateModified = new SimpleStringProperty();
private SimpleDoubleProperty size = new SimpleDoubleProperty();
public syncedFolders(
String name,
String location,
String dateModified,
double size) {
this.name.set(name);
this.location.set(location);
this.dateModified.set(dateModified);
this.size.setValue(size);
}
public String getName() {
return name.get();
}
public SimpleStringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public String getLocation() {
return location.get();
}
public SimpleStringProperty locationProperty() {
return location;
}
public void setLocation(String location) {
this.location.set(location);
}
public String getDateModified() {
return dateModified.get();
}
public SimpleStringProperty dateModifiedProperty() {
return dateModified;
}
public void setDateModified(String dateModified) {
this.dateModified.set(dateModified);
}
public double getSize() {
return size.get();
}
public SimpleDoubleProperty sizeProperty() {
return size;
}
public void setSize(double size) {
this.size.set(size);
}
}
EDIT:
I would also recommend changing how you populate your table. Your current addFolder() method is adding the item directly to the table's items property, but you really should add them to the underlying ObservableList that is set as the table's items:
public void addFolder() {
round(printSize, 1);
folderTable.setItems(getSyncedFolders());
folderTable.getItems().add(new syncedFolders(name, location, dateModified, tempSize));
}
The way folderTable.setItems() works is that it binds a list to the TableView. But that I mean that any changes made to the list will be reflected in the TableView automatically; you should not need to use folderTable.getItems().add() at all.
I have following two classes whose basical purpose to create an array of objects...
class MovieInfo
{ private String movieTitle;
private String movieRating;
private String movieImg;
private String movieShowTimes;
private static double adultPrice;
private static double childPrice;
MovieInfo(String title, String rating, String img, String showTimes)
{
movieTitle = title;
movieRating = rating;
movieImg = img;
movieShowTimes = showTimes;
}
/*....sets gets methods.... */
}
///////////////////////////////
class MovieList
{
MovieInfo[] mList;
public void createList()
{
mList = new MovieInfo[22];
mList[0] = new MovieInfo("A United Kingdom","PG","A_United_Kingdom.jpg","yyyn");
mList[1] = new MovieInfo("Amitiville The Awakening","18A","AmitivilleAwakening.jpg","yyyn");
mList[2] = new MovieInfo("Arrival","14A","arrival.jpg","yyyy");
mList[3] = new MovieInfo("Baywatch","14A","baywatch.jpg","yyyy");
mList[4] = new MovieInfo("Beauty and the Beast","PG","Beauty_and_the_Beast.jpg","yyyn");
}
}
I also have JList which is attached to JPanel and radio buttons..
And my problem is that I can not get how to display name of the movie from mList[0] on this JList when I click 1st rbutton, name of the movie from mList[1] when I click 2nd rbutton and etc....
Yes I know that I need to register listener for my rbuttons and group them and add ItemStateChange (just did not want to add too much code here)... I am asking here about logic after the lines of
if(e.getSource() instanceof JRadioButton)
{
Please help! Any ideas will be highly appreciated!
You could write a custom CellRenderer, as shown in the docs.
For example, having a Movie bean and a MoviesListCellRenderer which extends DefaultListCellRenderer you could end up with something like this:
public class JListCards {
private JFrame frame;
private JPanel radiosPane;
private JRadioButton[] radios;
private String[] radiosNames = {"Movie", "Classification", "Price"};
private JList <Movie> moviesList;
private ButtonGroup group;
private Movie[] movies = new Movie[] {
new Movie("Happy Feet", "AA", 10),
new Movie("Star Wars", "B12", 15),
new Movie("Logan", "C", 20)
};
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new JListCards().createAndShowGui());
}
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
radiosPane = new JPanel(new GridLayout(1, 3));
radios = new JRadioButton[3];
group = new ButtonGroup();
for (int i = 0; i < radios.length; i++) {
radios[i] = new JRadioButton(radiosNames[i]);
radios[i].addActionListener(listener);
radiosPane.add(radios[i]);
group.add(radios[i]);
}
radios[0].setSelected(true);
moviesList = new JList<Movie>(movies);
moviesList.setCellRenderer(new MoviesListCellRenderer(0));
frame.add(moviesList);
frame.add(radiosPane, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < radios.length; i++) {
if (e.getSource().equals(radios[i])) {
moviesList.setCellRenderer(new MoviesListCellRenderer(i));
break;
}
}
}
};
class MoviesListCellRenderer extends DefaultListCellRenderer {
private int attribute;
public MoviesListCellRenderer(int attribute) {
this.attribute = attribute;
}
#Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Movie) {
Movie movie = (Movie) value;
switch (attribute) {
case 0:
setText(movie.getMovieName());
break;
case 1:
setText(movie.getClassification());
break;
default:
setText(String.valueOf(movie.getPrice()));
break;
}
}
return this;
}
}
class Movie {
private String movieName;
private String classification;
private double price;
public Movie(String movieName, String classification, double price) {
super();
this.movieName = movieName;
this.classification = classification;
this.price = price;
}
public String getMovieName() {
return movieName;
}
public void setMovieName(String movieName) {
this.movieName = movieName;
}
public String getClassification() {
return classification;
}
public void setClassification(String classification) {
this.classification = classification;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
}
Which as you can see, changes the cell renderer based on the radio selected, this code can still be improved but should give you an idea:
I am trying to solve a basic problem. Could you please have a look at this code and push me forward a little bit?
I have this
public class StrediskoController {
private Stage dialogStage;
#FXML private TableView strediskaTableView = new TableView<>();
#FXML private Label nameLabel;
private ObservableList<Stredisko> data = FXCollections.observableArrayList();
#FXML public void initialize() {
System.out.println("test");
strediskaTableView.getSelectionModel().selectedItemProperty().addListener((observableValue, oldValue, newValue) -> {
//Check whether item is selected and set value of selected item to Label
if (strediskaTableView.getSelectionModel().getSelectedItem() != null) {
nameLabel.setText(".....");
}
});
}
public void setDialogStage(Stage dialogStage) { this.dialogStage = dialogStage; }
public void GetStrediska() {
new StrediskoDAO().SeeAllStredisko(data, strediskaTableView);
}
I want to select a row in tableview and put a value of second column into label.
My StrediskoDAO looks like:
public void SeeAllStredisko(ObservableList data, TableView<Stredisko> stredisko)
{
try
{
String select = "Select * from stredisko";
PreparedStatement stmt = DatabaseConnection.prepareStatement(select);
ResultSet rst = stmt.executeQuery();
for(int i=0 ; i<rst.getMetaData().getColumnCount(); i++){
//using non property style for making dynamic table
final int j = i;
TableColumn col = new TableColumn(rst.getMetaData().getColumnName(i+1));
col.setCellValueFactory(new Callback<CellDataFeatures<ObservableList,String>,ObservableValue<String>>(){
public ObservableValue<String> call(CellDataFeatures<ObservableList, String> param) {
return new SimpleStringProperty(param.getValue().get(j).toString());
}
});
stredisko.getColumns().addAll(col);
System.out.println("Column ["+i+"] ");
}
while(rst.next())
{
ObservableList<String> row = FXCollections.observableArrayList();
for (int i = 1; i <= rst.getMetaData().getColumnCount(); i++)
{
row.add(rst.getString(i));
System.out.println(row);
}
data.add(row);
}
stredisko.setItems(data);
}
catch(ClassNotFoundException | SQLException e)
{
e.printStackTrace();
}
}
and Stredisko
public class Stredisko {
private SimpleIntegerProperty stredisko_Id;
private SimpleStringProperty name;
public Stredisko(int stredisko_Id, String name) {
this.stredisko_Id = new SimpleIntegerProperty(stredisko_Id);
this.name = new SimpleStringProperty(name);
}
public int getStredisko_Id() {
return stredisko_Id.get();
}
public SimpleIntegerProperty stredisko_IdProperty() {
return stredisko_Id;
}
public void setStredisko_Id(int stredisko_Id) {
this.stredisko_Id.set(stredisko_Id);
}
public String getName() {
return name.get();
}
public SimpleStringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
I am just a beginner in JavaFX and I would be really happy if you help me :-)
Thank you guys.
I've got following problem:
I styled a TableViews Cells into Rectangles. Now I want to add Objects with an X and Y Coordinate in it (obj.getAblaufX() and obj.getAblaufY()).
How can I add them correctly in JavaFX TableView?
My Current Code:
ObservableList<Event> eventList = loadEvents();
TableView<Event> tableView = new TableView<Event>();
tableView.getSelectionModel().setCellSelectionEnabled(true);
tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
tableView.setItems(eventList);
for(int i = 0; i < 10; i++) {
TableColumn<Event, String> tmpCol = new TableColumn<>();
tmpCol.setId(Integer.toString(i));
tmpCol.setMaxWidth(40);
tmpCol.setCellValueFactory(cellData -> new ObservableValue<String>() {
#Override
public void addListener(InvalidationListener listener) {
// TODO Auto-generated method stub
}
#Override
public void removeListener(InvalidationListener listener) {
// TODO Auto-generated method stub
}
#Override
public void addListener(ChangeListener<? super String> listener) {
// TODO Auto-generated method stub
}
#Override
public void removeListener(ChangeListener<? super String> listener) {
// TODO Auto-generated method stub
}
#Override
public String getValue() {
if(Integer.parseInt(tmpCol.getId()) == cellData.getValue().getAblaufX()) {
return cellData.getValue().getAbteilung();
} else {
return "";
}
}
});
tableView.getColumns().add(tmpCol);
}
Result:
But:
Object SP1 has X = 0 and Y = 0
Object SP2 has X = 1 and Y = 0
So, how to fix this Problem?
By using Event as item type, you pervent the TableView from displaying more than one Event per row. Use Integer as item type instead and store the values in a ObservableMap<TablePos, Event> where TablePos is a class containing the x and y coordinates:
public final class TablePos {
private final int x;
private final int y;
public TablePos(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public int hashCode() {
int hash = 7;
hash = 17 * hash + this.x;
hash = 17 * hash + this.y;
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof TablePos)) {
return false;
}
final TablePos other = (TablePos) obj;
return (this.x == other.x && this.y == other.y);
}
}
public class Event {
private final StringProperty name;
private final IntegerProperty x;
private final IntegerProperty y;
public Event(String name, int x, int y) {
// set beans for properties here to make this instance accessible to listeners
this.y = new SimpleIntegerProperty(this, "y", y);
this.x = new SimpleIntegerProperty(this, "x", x);
this.name = new SimpleStringProperty(this, "name", name);
}
public final String getName() {
return this.name.get();
}
public final void setName(String value) {
this.name.set(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final int getX() {
return this.x.get();
}
public final void setX(int value) {
this.x.set(value);
}
public final IntegerProperty xProperty() {
return this.x;
}
public final int getY() {
return this.y.get();
}
public final void setY(int value) {
this.y.set(value);
}
public final IntegerProperty yProperty() {
return this.y;
}
}
private static void put(Map<TablePos, Event> map, Event evt) {
map.put(new TablePos(evt.getX(), evt.getY()), evt);
}
#Override
public void start(Stage primaryStage) {
ObservableMap<TablePos, Event> contents = FXCollections.observableHashMap();
TableView<Integer> tableView = new TableView<>(FXCollections.observableArrayList());
TableColumn columnGroup = new TableColumn("Heutige Termine");
ChangeListener<Number> xChangeListener = (observable, oldValue, newValue) -> {
Event evt = (Event) ((Property) observable).getBean();
TablePos oldPos = new TablePos(oldValue.intValue(), evt.getY());
TablePos newPos = new TablePos(newValue.intValue(), evt.getY());
contents.remove(oldPos);
contents.put(newPos, evt);
};
ChangeListener<Number> yChangeListener = (observable, oldValue, newValue) -> {
Event evt = (Event) ((Property) observable).getBean();
TablePos oldPos = new TablePos(evt.getX(), oldValue.intValue());
TablePos newPos = new TablePos(evt.getX(), newValue.intValue());
contents.remove(oldPos);
contents.put(newPos, evt);
};
contents.addListener((MapChangeListener.Change<? extends TablePos, ? extends Event> change) -> {
if (change.wasRemoved()) {
Event evt = change.getValueRemoved();
evt.xProperty().removeListener(xChangeListener);
evt.yProperty().removeListener(yChangeListener);
}
if (change.wasAdded()) {
Event evt = change.getValueAdded();
evt.xProperty().addListener(xChangeListener);
evt.yProperty().addListener(yChangeListener);
}
});
// items denote the y coordinate
for (int i = 0; i < 10; i++) {
tableView.getItems().add(i);
}
// one column per x coordiante
for (int i = 0; i < 10; i++) {
final int index = i;
TableColumn<Integer, String> column = new TableColumn<>();
// take value from Map using x (index) and y (item value)
column.setCellValueFactory(cd
-> Bindings.selectString(
Bindings.valueAt(contents, new TablePos(index, cd.getValue())), "name"));
columnGroup.getColumns().add(column);
}
tableView.getColumns().add(columnGroup);
Event opTarget = new Event("Something", 2, 9);
put(contents, new Event("SP1", 0, 0));
put(contents, new Event("SP2", 1, 0));
put(contents, opTarget);
Button move = new Button("move");
move.setOnAction(evt -> opTarget.setX(9 - opTarget.getX()));
Button rename = new Button("rename");
rename.setOnAction(evt -> opTarget.setName(opTarget.getName().equals("42") ? "Answer" : "42"));
Scene scene = new Scene(new VBox(10, tableView, move, rename));
primaryStage.setScene(scene);
primaryStage.show();
}
Note that this requires you to know the number of rows/columns at the initialisation (I used 10 for both for simplicity). If this is not the case, you could add a listener to the ObservableMap that dynamically adds/removes rows / columns.