Problems with your implementation
You can embed JavaFX components in Swing applications (by hosting the JavaFX component in the JFXPanel ). But you cannot embed the Swing component in JavaFX (unless you are using JavaFX 8 +).
JavaFX still has its own implementation of buttons, so it makes no sense to embed javax.swing.JButton in the JavaFX scene, even if you use Java8, and that will work.
But this will not solve all your problems. You provide a factory cell value for a button column to serve buttons, but not to provide custom rendering of factory cells. Displaying a table cell by default factory outputs the output of toString to the corresponding cell value, so you just see the string representation of the button in the table implementation.
You put buttons in your Person object. Do not do this - they do not belong there. Instead, dynamically create a button in a factory cell rendering. This allows you to use the technology of virtual table flow, in which it creates only visual nodes for what you can see on the screen, and not for each element in the table data warehouse. For example, if there are 10 rows and 10,000 elements in the table on the screen, only 10 buttons will be created, not 10,000.
How to fix it
- Instead of
javax.swing.JButton instead of javax.swing.JButton use the JavaFX Button . - Provide a factory cell selection for your button.
- Create a button in a table cell, not in Person.
- To set a button (or any arbitrary JavaFX node) in a table cell, use the setGraphic method.
The correct code example
This code contains suggested fixes and a couple of improvements.

import javafx.application.Application; import javafx.beans.property.*; import javafx.beans.value.ObservableValue; import javafx.collections.*; import javafx.event.*; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.control.TableColumn.CellDataFeatures; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.image.*; import javafx.scene.layout.*; import javafx.scene.text.Font; import javafx.stage.Stage; import javafx.util.Callback; public class GestureEvents extends Application { private TableView<Person> table = new TableView<Person>(); private final ObservableList<Person> data = FXCollections.observableArrayList( new Person("Jacob", "Smith", " jacob.smith@example.com ","Coffee"), new Person("Isabella", "Johnson", " isabella.johnson@example.com ","Fruit"), new Person("Ethan", "Williams", " ethan.williams@example.com ","Fruit"), new Person("Emma", "Jones", " emma.jones@example.com ","Coffee"), new Person("Michael", "Brown", " michael.brown@example.com ","Fruit") ); public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { stage.setTitle("Table View Sample"); final Label label = new Label("Address Book"); label.setFont(new Font("Arial", 20)); final Label actionTaken = new Label(); table.setEditable(true); TableColumn firstNameCol = new TableColumn("First Name"); firstNameCol.setMinWidth(100); firstNameCol.setCellValueFactory( new PropertyValueFactory<Person, String>("firstName")); TableColumn lastNameCol = new TableColumn("Last Name"); lastNameCol.setMinWidth(100); lastNameCol.setCellValueFactory( new PropertyValueFactory<Person, String>("lastName")); TableColumn emailCol = new TableColumn("Email"); emailCol.setMinWidth(200); emailCol.setCellValueFactory( new PropertyValueFactory<Person, String>("email")); TableColumn<Person, Person> btnCol = new TableColumn<>("Gifts"); btnCol.setMinWidth(150); btnCol.setCellValueFactory(new Callback<CellDataFeatures<Person, Person>, ObservableValue<Person>>() { @Override public ObservableValue<Person> call(CellDataFeatures<Person, Person> features) { return new ReadOnlyObjectWrapper(features.getValue()); } }); btnCol.setComparator(new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.getLikes().compareTo(p2.getLikes()); } }); btnCol.setCellFactory(new Callback<TableColumn<Person, Person>, TableCell<Person, Person>>() { @Override public TableCell<Person, Person> call(TableColumn<Person, Person> btnCol) { return new TableCell<Person, Person>() { final ImageView buttonGraphic = new ImageView(); final Button button = new Button(); { button.setGraphic(buttonGraphic); button.setMinWidth(130); } @Override public void updateItem(final Person person, boolean empty) { super.updateItem(person, empty); if (person != null) { switch (person.getLikes().toLowerCase()) { case "fruit": button.setText("Buy fruit"); buttonGraphic.setImage(fruitImage); break; default: button.setText("Buy coffee"); buttonGraphic.setImage(coffeeImage); break; } setGraphic(button); button.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { actionTaken.setText("Bought " + person.getLikes().toLowerCase() + " for: " + person.getFirstName() + " " + person.getLastName()); } }); } else { setGraphic(null); } } }; } }); table.setItems(data); table.getColumns().addAll(firstNameCol, lastNameCol, emailCol, btnCol); final VBox vbox = new VBox(); vbox.setSpacing(5); vbox.setPadding(new Insets(10, 10, 10, 10)); vbox.getChildren().addAll(label, table, actionTaken); VBox.setVgrow(table, Priority.ALWAYS); stage.setScene(new Scene(vbox)); stage.show(); } public static class Person { private final SimpleStringProperty firstName; private final SimpleStringProperty lastName; private final SimpleStringProperty email; private final SimpleStringProperty likes; private Person(String fName, String lName, String email, String likes) { this.firstName = new SimpleStringProperty(fName); this.lastName = new SimpleStringProperty(lName); this.email = new SimpleStringProperty(email); this.likes = new SimpleStringProperty(likes); } public String getFirstName() { return firstName.get(); } public void setFirstName(String fName) { firstName.set(fName); } public String getLastName() { return lastName.get(); } public void setLastName(String fName) { lastName.set(fName); } public String getEmail() { return email.get(); } public void setEmail(String fName) { email.set(fName); } public String getLikes() { return likes.get(); } public void setLikes(String likes) { this.likes.set(likes); } }
When using Swing components in JavaFX
After further study, I found examples that override cell graphics using predefined cell types, such as text and checks. It is unclear whether any generic jfx component can be placed in a cell, such as a JFXPanel.
A JFXPanel is designed to embed a JavaFX component in Swing, not a Swing component in JavaFX, so it would be completely futile to try to place a JFXPanel in a JavaFX TableView . That is why you do not find examples of anyone trying to do something.
This is not like JTable, because with JTable I can post anything that inherits from JComponent if I set up the visualization class correctly.
The JavaFX TableView in this regard is similar to Swing JTable . Instead of JComponent Node is the main building block for JavaFX β they are similar, albeit different. You can map any Node to the JavaFX TableView , as long as you provide the appropriate factory cell for it.
In Java 8, there is a SwingNode that may contain a Swing JComponent . A SwingNode allows you to display any Swing component in a JavaView TableView.
The code for using SwingNode very simple:
import javafx.application.Application; import javafx.embed.swing.SwingNode; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.stage.Stage; import javax.swing.*; public class SwingFx extends Application { @Override public void start(Stage stage) { SwingNode swingNode = new SwingNode(); SwingUtilities.invokeLater(() -> swingNode.setContent(new JButton("Click me!"))); stage.setScene(new Scene(new StackPane(swingNode), 100, 50)); stage.show(); } public static void main(String[] args) { launch(SwingFx.class); } }
Alternative implementation
Basically what I'm trying to do is add gesture scrolling support to my java project so the user can βclickβ on tables and tabs
Despite the fact that Java 8 will allow you to achieve exactly what you want, if you prefer to use an older version of Java, you can use SwaS Multitouch for Java (MT4J) for this instead of JavaFX.