Reputation: 29
I am new to JAVAFX and am trying to display the hyperlink in table cell. I could able to display as a hyperlink but not able to open the link.
Please find the logic for the same.
Main method goes here::
public class Main extends Application {
private BorderPane root;
private TableView<Item> table;
private Scene scene;
private TableColumn<Item, String> nameColumn;
private TableColumn<Item, Hyperlink> urlColumn;
private ObservableList<Item> websiteList;
@Override
public void start(Stage primaryStage) {
root = new BorderPane();
//scene = new Scene(root, 400, 400);
table = new TableView<Item>();
//root.setCenter(table);
nameColumn = new TableColumn<>("Name");
nameColumn.setCellValueFactory(new PropertyValueFactory<>("websiteName"));
urlColumn = new TableColumn<>("Address");
urlColumn.setCellValueFactory(new PropertyValueFactory<>("hyperlink"));
urlColumn.setCellFactory(new HyperlinkCell());
table.getColumns().add(nameColumn);
table.getColumns().add(urlColumn);
websiteList = FXCollections.observableArrayList();
websiteList.add(new Item("Google", "https://www.google.co.in/"));
websiteList.add(new Item("Facebook", "www.facebook.com"));
websiteList.add(new Item("Superglobals", "www.superglobals.net"));
Hyperlink hyperlink = new Hyperlink("Go to Eclipse home page");
hyperlink.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
getHostServices().showDocument("https://www.google.co.in/");
}
});
root.getChildren().addAll(hyperlink);
// root.setBottom(hyperlink);
table.setItems(websiteList);
root.setCenter(table);
scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Item.java::
public class Item {
private String websiteName;
private Hyperlink hyperlink;
public Item(String websiteName, String websiteUrl) {
this.websiteName = websiteName;
this.hyperlink = new Hyperlink(websiteUrl);
}
public String getWebsiteName() {
return websiteName;
}
public void setWebsiteName(String websiteName) {
this.websiteName = websiteName;
}
public Hyperlink getHyperlink() {
return hyperlink;
}
public void setHyperlink(String websiteUrl) {
this.hyperlink = new Hyperlink(websiteUrl);
}
}
HyperlinkCell.java::
public class HyperlinkCell implements Callback<TableColumn<Item, Hyperlink>, TableCell<Item, Hyperlink>> {
private static HostServices hostServices ;
public static HostServices getHostServices() {
return hostServices ;
}
@Override
public TableCell<Item, Hyperlink> call(TableColumn<Item, Hyperlink> arg) {
TableCell<Item, Hyperlink> cell = new TableCell<Item, Hyperlink>() {
@Override
protected void updateItem(Hyperlink item, boolean empty) {
super.updateItem(item, empty);
setGraphic(empty ? null : item);
}
};
return cell;
}
}
Output is displaying like this but am not able to open the hyperlink. Please help us on this.
Thanks.
Upvotes: 0
Views: 2181
Reputation: 209418
Just update the onAction
handler of the hyperlink in the updateItem()
method:
TableCell<Item, Hyperlink> cell = new TableCell<Item, Hyperlink>() {
@Override
protected void updateItem(Hyperlink item, boolean empty) {
super.updateItem(item, empty);
setGraphic(empty ? null : item);
if (! empty) {
item.setOnAction(e -> {
// handle event here...
});
}
}
};
Note that it's really not a good idea to use UI elements (such as Hyperlink
) in your data classes (such as Item
). I recommend you refactor this so that Item
only holds the data:
public class Item {
private String websiteName;
private String url;
public Item(String websiteName, String websiteUrl) {
this.websiteName = websiteName;
this.url = websiteUrl;
}
public String getWebsiteName() {
return websiteName;
}
public void setWebsiteName(String websiteName) {
this.websiteName = websiteName;
}
public String getUrl() {
return url;
}
public void setUrl(String websiteUrl) {
this.url = websiteUrl;
}
}
And then:
private TableColumn<Item, String> urlColumn;
// ...
urlColumn = new TableColumn<>("Address");
urlColumn.setCellValueFactory(new PropertyValueFactory<>("url"));
urlColumn.setCellFactory(new HyperlinkCell());
Somewhere in start()
you need to do
HyperlinkCell.setHostServices(getHostServices());
and finally define the Hyperlink
in the cell. That way there is only one Hyperlink
instance per cell, instead of one for every item in the table.
public class HyperlinkCell implements Callback<TableColumn<Item, Hyperlink>, TableCell<Item, Hyperlink>> {
private static HostServices hostServices ;
public static HostServices getHostServices() {
return hostServices ;
}
public static void setHostServices(HostServices hostServices) {
HyperlinkCell.hostServices = hostServices ;
}
@Override
public TableCell<Item, String> call(TableColumn<Item, String> arg) {
TableCell<Item, Hyperlink> cell = new TableCell<Item, Hyperlink>() {
private final Hyperlink hyperlink = new Hyperlink();
{
hyperlink.setOnAction(event -> {
String url = getItem();
hostServices.showDocument(url);
});
}
@Override
protected void updateItem(String url, boolean empty) {
super.updateItem(url, empty);
if (empty) {
setGraphic(null);
} else {
hyperlink.setText(url);
setGraphic(hyperlink);
}
}
};
return cell;
}
}
Upvotes: 3