jxBrowser error class don't exist - jxbrowser

import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.BrowserFunction;
import com.teamdev.jxbrowser.chromium.JSValue;
import com.teamdev.jxbrowser.chromium.LoggerProvider;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;
import javax.swing.*;
import java.awt.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class JavaScriptJavaSample {
public static void main(String[] args) {
LoggerProvider.setLevel(Level.OFF);
Browser browser = new Browser();
BrowserView browserView = new BrowserView(browser);
browser.registerFunction("MyFunction", new BrowserFunction() {
public JSValue invoke(JSValue... args) {
System.out.println("MyFunction is invoked!");
return JSValue.create("Hello!");
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(browserView, BorderLayout.CENTER);
frame.setSize(700, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
browser.loadHTML("<html><body><a href='#' onclick='MyFunction();'>Call Java method</a></body></html>");
}
}
i've add all jar file,but BrowserFunction doesn't exist, why?
all other classes work perfectly , and do not understand the problem , I
imported all the jar thanks to all in advance

As far as i know, using BrowserFunction() to register function is gone in new versions of jxbrowser. There is a new way in 6.1 version described here. Putting the new way in your code :
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.BrowserFunction;
import com.teamdev.jxbrowser.chromium.JSValue;
import com.teamdev.jxbrowser.chromium.LoggerProvider;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;
import javax.swing.*;
import java.awt.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class JavaScriptJavaSample {
public static void main(String[] args) {
LoggerProvider.setLevel(Level.OFF);
Browser browser = new Browser();
BrowserView browserView = new BrowserView(browser);
browser.addLoadListener(new LoadAdapter() {
#Override
public void onFinishLoadingFrame(FinishLoadingEvent event) {
if (event.isMainFrame()) {
Browser browser = event.getBrowser();
JSValue value = browser.executeJavaScriptAndReturnValue("window");
value.asObject().setProperty("java", new Events());
}
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(browserView, BorderLayout.CENTER);
frame.setSize(700, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
browser.loadHTML("<html><body><a href='#' onclick='alert(java.MyFunction());return false;'>Call Java method</a></body></html>");
}
}
Create another file to hold Events class :
public class Events {
public String MyFunction() {
System.out.println("MyFunction is invoked!");
return new String("Hello");
}
}
* Added return false to the end of onclick attribute of a tag, preventing browser from following the link href on click.
BTW, I suggest you to use main documentation codes, as they are up-to-date.

In order to use the BrowserFunction you should have the licence.jar and add it to your classpath .
JxBrowser has a free 30day-trial . you can also buy the license .

Related

use vlcj-javafx-demo develop a player, but it looks some components UI not update correctly when set full screen

I try to use vlcj-javafx-demo to develop a video player, and I put the progress bar(Slider) on the StackPane over the video layer. In the beginning, it looks work well, but when I set maximum or full screen the app, it looks some components UI did not update correctly. How can I correct it?
Thanks a lot!
normally:
[1]: https://i.stack.imgur.com/bbE51.png
normally:
[2]: https://i.stack.imgur.com/Plsb1.png
the red color is the sence background color.
the code :
package my.javafx.myplayer;
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Slider;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
import uk.co.caprica.vlcj.factory.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.base.MediaPlayerEventAdapter;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import java.util.ArrayList;
import java.util.List;
import static uk.co.caprica.vlcj.javafx.videosurface.ImageViewVideoSurfaceFactory.videoSurfaceForImageView;
/**
*
*/
public class VlcjJavaFxApplication extends Application {
private final MediaPlayerFactory mediaPlayerFactory;
private final EmbeddedMediaPlayer embeddedMediaPlayer;
private ImageView videoImageView;
Slider progress=new Slider();
public VlcjJavaFxApplication() {
this.mediaPlayerFactory = new MediaPlayerFactory();
this.embeddedMediaPlayer = mediaPlayerFactory.mediaPlayers().newEmbeddedMediaPlayer();
this.embeddedMediaPlayer.events().addMediaPlayerEventListener(new MediaPlayerEventAdapter() {
#Override
public void mediaPlayerReady(uk.co.caprica.vlcj.player.base.MediaPlayer mediaPlayer) {
Platform.runLater(()->{
progress.setValue(0);
progress.setMax(embeddedMediaPlayer.media().info().duration());
progress.setMin(0);
});
}
#Override
public void playing(uk.co.caprica.vlcj.player.base.MediaPlayer mediaPlayer) {
}
#Override
public void paused(uk.co.caprica.vlcj.player.base.MediaPlayer mediaPlayer) {
}
#Override
public void stopped(uk.co.caprica.vlcj.player.base.MediaPlayer mediaPlayer) {
}
#Override
public void timeChanged(uk.co.caprica.vlcj.player.base.MediaPlayer mediaPlayer, long newTime) {
Platform.runLater(()->{
progress.setValue(newTime);
});
}
});
}
#Override
public void init() {
this.videoImageView = new ImageView();
this.videoImageView.setPreserveRatio(true);
embeddedMediaPlayer.videoSurface().set(videoSurfaceForImageView(this.videoImageView));
}
#Override
public final void start(Stage primaryStage) throws Exception {
List<String> params = new ArrayList<String>();
params.add("/Users/baixq/Downloads/妙味课堂xhtml+css2/妙味课堂-XHTMLCSS2整站视频教程-4.avi");
if (params.size() != 1) {
System.out.println("Specify a single MRL");
System.exit(-1);
}
StackPane root=new StackPane();
//BorderPane root = new BorderPane();
root.setStyle("-fx-background-color: black;");
videoImageView.fitWidthProperty().bind(root.widthProperty());
videoImageView.fitHeightProperty().bind(root.heightProperty());
root.widthProperty().addListener((observableValue, oldValue, newValue) -> {
// If you need to know about resizes
});
root.heightProperty().addListener((observableValue, oldValue, newValue) -> {
// If you need to know about resizes
});
Scene scene = new Scene(root, 1200, 675, Color.RED);
primaryStage.setTitle("vlcj JavaFX");
primaryStage.setScene(scene);
AnchorPane contrlBox=new AnchorPane();//操作面板上的控制模块
contrlBox.prefWidthProperty().bind(root.widthProperty());
contrlBox.prefHeightProperty().bind(root.heightProperty().multiply(0.1));
BorderPane controlBar=new BorderPane();
controlBar.setStyle("-fx-background-color: #130c0e;");
controlBar.prefWidthProperty().bind(root.widthProperty());
controlBar.prefHeightProperty().bind(root.heightProperty().multiply(0.1));
controlBar.setCenter(progress);
Button fullScreen=new Button("全屏");
controlBar.setRight(fullScreen);
contrlBox.getChildren().add(controlBar);
contrlBox.setBottomAnchor(controlBar, 0.0);
root.getChildren().addAll(videoImageView,contrlBox);
primaryStage.show();
embeddedMediaPlayer.media().play(params.get(0));
fullScreen.setOnAction(event->{
primaryStage.setFullScreen(true);
});
root.setOnMouseEntered(event->{
Platform.runLater(()->{
FadeTransition ft = new FadeTransition(Duration.millis(500), contrlBox);
ft.setFromValue(0.0);
ft.setToValue(1);
//ft.setCycleCount(Timeline.INDEFINITE);
ft.setAutoReverse(false);
ft.play();
contrlBox.setVisible(true);
});
});
root.setOnMouseExited(event->{
Platform.runLater(()->{
FadeTransition ft = new FadeTransition(Duration.millis(500), contrlBox);
ft.setFromValue(1);
ft.setToValue(0.0);
ft.setAutoReverse(false);
ft.play();
contrlBox.setVisible(false);
});
});
//embeddedMediaPlayer.controls().setPosition(0.4f);
}
#Override
public final void stop() {
embeddedMediaPlayer.controls().stop();
embeddedMediaPlayer.release();
mediaPlayerFactory.release();
}
public static void main(String[] args) {
launch(args);
}
}
You appear to be using a Linux OS, try passing one or more of these system properties when you start your JVM:
-Dprism.dirtyopts=false
-Dprism.forceUploadingPainter=true
This is mentioned under "Linux notes" here: https://github.com/caprica/vlcj-javafx-demo/tree/vlcj-5.x
I have seen similar painting glitches on Linux before and in all cases using these properties, at least for me, clears the issue with only a small hit to performance - even when doing something like a full-screen grid of nine concurrent media players, where each one had an animating video controls overlay.

JxBrowser: How to implement 'save link as' within a ContextMenuHandler

I want to implement a 'save link as' option within a ContextMenuHandler.
But there is no browser function like loadURL(...) to force the Browser component to just start a download for the provided link.
__________________ EDITED__________________________
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.ContextMenuHandler;
import com.teamdev.jxbrowser.chromium.ContextMenuParams;
import com.teamdev.jxbrowser.chromium.SavePageType;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;
import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class ContextMenuSample {
public static void main(String[] args) {
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
Browser browser = new Browser();
BrowserView view = new BrowserView(browser);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(view, BorderLayout.CENTER);
frame.setSize(700, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
browser.setContextMenuHandler(new MyContextMenuHandler(view));
browser.loadURL("http://www.google.com");
}
private static class MyContextMenuHandler implements ContextMenuHandler {
private final JComponent component;
private MyContextMenuHandler(JComponent parentComponent) {
this.component = parentComponent;
}
private static JMenuItem createMenuItem(String title, final Runnable action) {
JMenuItem reloadMenuItem = new JMenuItem(title);
reloadMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
action.run();
}
});
return reloadMenuItem;
}
public void showContextMenu(final ContextMenuParams params) {
final JPopupMenu popupMenu = new JPopupMenu();
final Browser browser = params.getBrowser();
popupMenu.add(createMenuItem("Save As", new Runnable() {
#Override
public void run() {
Browser browser2 = new Browser();
browser2.loadURL(params.getLinkURL());
browser2.saveWebPage(params.getLinkText(), ".", SavePageType.COMPLETE_HTML);
}
}));
final Point location = params.getLocation();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
popupMenu.show(component, location.x, location.y);
}
});
}
}
}

Force tableView edit next cell automatically

After typing in the cell, I want the focus
go to the next edit cell automatically.
How to do this ?
I'm using
tv.getSelectionModel (). select (row + 1);
tv.edit (row + 1, name); // <--- here not work edition next line
But unfortunately it is not working within setOnEditCommit
When it's called by clicking a button that is outside the tableView for example it works. The impression I have is that after setOnEditCommit it puts the last line cell's over.
How to solve this?
Thank's
File of properties
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.image.ImageView;
public class Lin {
private SimpleStringProperty number;
private SimpleStringProperty name;
public Lin(String number, String name ) {
this.number = new SimpleStringProperty(number);
this.name = new SimpleStringProperty(name);
}
public SimpleStringProperty numberProperty() {
return number;
}
public String getNumber() {
return number.getValue();
}
public SimpleStringProperty nameProperty() {
return name;
}
public String getName() {
return name.getValue();
}
}
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
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.control.cell.TextFieldTableCell;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class TableTesteEdit extends Application {
TableView tv = new TableView();
public ObservableList<Lin> data = FXCollections.observableArrayList();
#Override
public void start(Stage primaryStage) {
TableColumn<Lin,String> number = new TableColumn("#");
TableColumn<Lin,String> name = new TableColumn("Name");
name.setPrefWidth(400);
number.setCellValueFactory(new PropertyValueFactory("number"));
name.setCellValueFactory(new PropertyValueFactory("name"));
name.setCellFactory( TextFieldTableCell.<Lin>forTableColumn() );
name.setOnEditCommit(
new EventHandler<TableColumn.CellEditEvent<Lin, String>>() {
#Override
public void handle(TableColumn.CellEditEvent<Lin, String> t) {
int row = t.getTablePosition().getRow();
((Lin)t.getTableView().getItems().get(row)).nameProperty().setValue(t.getNewValue());
tv.getSelectionModel().select(row+1);
tv.edit(row+1, name); // <--- here not work edition next line
}
}
);
tv.setEditable(true);
number.setEditable(false);
name.setEditable(true);
data.addAll( new Lin("1","AFTER EditCommit go next cell and edit auto"),
new Lin("2","AFTER EditCommit go next cell and edit auto"),
new Lin("3","Congratulations !!!")
);
tv.getColumns().addAll(number, name);
tv.setItems(data);
Scene scene = new Scene(tv, 300, 250);
primaryStage.setTitle("Edit Auto next Cell");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
I think the baked-in behavior of the table's editing sets the editing cell to null once an edit has been committed. My guess is that this happens after the onEditCommit handler has been invoked, so your call to edit the next cell is basically revoked.
A (not very satisfactory) way to fix this is to wrap the call to tv.edit(...) in Platform.runLater(...), which has the effect of delegating it to a runnable which is executed after the pending events have been handled:
// tv.edit(row+1, name);
Platform.runLater(() -> tv.edit(row+1, name));
Caveat: As commented below, this method is not reliable, so if this is mission-critical you should not use this approach. If you're just looking for something that is convenient for the user, if not fully reliable, then this may suffice. Unless you're willing to rewrite the table view skin, this may be as good as it gets...
You should look into the .requestFocus() method if there is something in the next cell that can pull the focus to it for example if you can only type in 4 letters you could use setOnAction(event->{ if(checkLength()) cell2.requestFocus()});
Good Luck

JavaFX representing directories

I am building an application in Java where I need to represent a predefined directory in any kind of view in my window. Imagine something like a backup application where the main window displays all of the files under a specific directory.
Is there a way to do so using JavaFX? I do not care if files are going to be displayed as a tree or icons or anything really.
Thanks
edit: what I tried so far with no luck. This is my Controller class:
import javafx.scene.control.*;
import java.io.IOException;
public class ViewController {
public ListView listView;
public ViewController() throws IOException {
listView = new ListView();
listView.getItems().addAll("Iron Man", "Titanic", "Contact", "Surrogates");
}
}
and my fxml contains:
<ListView fx:id="listView" prefHeight="200.0" prefWidth="200.0" />
I wrote up a brief program that displays a tree of files and directories chosen by the user.
The result:
How it works:
When the user clicks the "Load Folder" button,
getNodesForDirectory is called, and recursively walks through the file tree, making tree items along the way.
Here is the code:
import java.io.File;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
public class DirectoryViewer extends Application {
#Override
public void start(Stage primaryStage) {
TreeView<String> a = new TreeView<String>();
BorderPane b = new BorderPane();
Button c = new Button("Load Folder");
c.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
DirectoryChooser dc = new DirectoryChooser();
dc.setInitialDirectory(new File(System.getProperty("user.home")));
File choice = dc.showDialog(primaryStage);
if(choice == null || ! choice.isDirectory()) {
Alert alert = new Alert(AlertType.ERROR);
alert.setHeaderText("Could not open directory");
alert.setContentText("The file is invalid.");
alert.showAndWait();
} else {
a.setRoot(getNodesForDirectory(choice));
}
}
});
b.setTop(c);
b.setCenter(a);
primaryStage.setScene(new Scene(b, 600, 400));
primaryStage.setTitle("Folder View");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public TreeItem<String> getNodesForDirectory(File directory) { //Returns a TreeItem representation of the specified directory
TreeItem<String> root = new TreeItem<String>(directory.getName());
for(File f : directory.listFiles()) {
System.out.println("Loading " + f.getName());
if(f.isDirectory()) { //Then we call the function recursively
root.getChildren().add(getNodesForDirectory(f));
} else {
root.getChildren().add(new TreeItem<String>(f.getName()));
}
}
return root;
}
}
Good luck with your project!

Understanding CheckBoxTableCell changelistener using setSelectedStateCallback

I'm trying to follow: CheckBoxTableCell changelistener not working
The given code answer to that question is below and dependent on the model 'Trainee'
final CheckBoxTableCell<Trainee, Boolean> ctCell = new CheckBoxTableCell<>();
ctCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
#Override
public ObservableValue<Boolean> call(Integer index) {
return table.getItems().get(index).selectedProperty();
}
});
I would like to obtain that selected property value and add a listener to it, but I don't think I'm doing it right. I attempted to add all kind of listeners to it so that I know when the checkbox in each row is changed and I can add logic to each. I presume the code above allow ctCell to now observe changes and I can just call a change listener to it and detect selection per given row.
I tried some change properties here just to detect the changes:
ctCell.selectedStateCallbackProperty().addListener(change -> {
System.out.println("1Change happened in selected state property");
});
ctCell.selectedProperty().addListener(change -> {
System.out.println("2Change happened in selected property");
});
ctCell.itemProperty().addListener(change -> {
System.out.println("3Change happened in item property");
});
ctCell.indexProperty().addListener(change -> {
System.out.println("4Change happened in index property");
});
...but none seemed to be called.
This is the shorten set up that I have:
requestedFaxCol.setCellValueFactory(new PropertyValueFactory("clientHasRequestedFax"));
requestedFaxCol.setCellFactory(CheckBoxTableCell.forTableColumn(requestedFaxCol));
final CheckBoxTableCell<ClinicClientInfo, Boolean> ctCell = new CheckBoxTableCell<>();
ctCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
#Override
public ObservableValue<Boolean> call(Integer index) {
return clinicLinkTable.getItems().get(index).clientHasRequestedFaxProperty();}
});
Let me know if I need to provide a more information! What am I not understanding in terms of why I cannot bridge a change listener to my table cell check boxes? Or if someone can point out the a direction for me to try. Thanks!
UPDATE to depict the ultimate goal of this question
package testapp;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TestApp extends Application {
private TableView<ClinicClientInfo> clientTable = new TableView<>();
private TableColumn<ClinicClientInfo, String> faxCol = new TableColumn<>("Fax");
private TableColumn<ClinicClientInfo, Boolean> requestedFaxCol = new TableColumn<>("Requested Fax");
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
ObservableList<ClinicClientInfo> list = FXCollections.observableArrayList(
new ClinicClientInfo("", false),
new ClinicClientInfo("945-342-4324", true));
root.getChildren().add(clientTable);
clientTable.getColumns().addAll(faxCol, requestedFaxCol);
clientTable.setItems(list);
clientTable.setEditable(true);
clientTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
faxCol.setCellValueFactory(new PropertyValueFactory<>("clinicFax"));
faxCol.setVisible(true);
requestedFaxCol.setCellValueFactory(new PropertyValueFactory("clientHasRequestedFax"));
requestedFaxCol.setCellFactory(CheckBoxTableCell.forTableColumn(requestedFaxCol));
requestedFaxCol.setVisible(true);
requestedFaxCol.setEditable(true);
//My attempt to connect the listener
//If user selects checkbox and the fax value is empty, the alert should prompt
CheckBoxTableCell<ClinicClientInfo, Boolean> ctCell = new CheckBoxTableCell<>();
ctCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
#Override
public ObservableValue<Boolean> call(Integer index) {
ObservableValue<Boolean> itemBoolean = clientTable.getItems().get(index).clientHasRequestedFaxProperty();
itemBoolean.addListener(change -> {
ClinicClientInfo item = clientTable.getItems().get(index);
if(item.getClinicFax().isEmpty() && item.getClientHasRequestedFax()){
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Warning");
alert.show();
}
});
return itemBoolean;
}
});
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public class ClinicClientInfo {
private final StringProperty clinicFax;
private final BooleanProperty clientHasRequestedFax;
public ClinicClientInfo(String fax, boolean clientHasRequestedFax){
this.clinicFax = new SimpleStringProperty(fax);
this.clientHasRequestedFax = new SimpleBooleanProperty(clientHasRequestedFax);
}
public String getClinicFax(){
return clinicFax.get();
}
public void setClinicFax(String clinicFax){
this.clinicFax.set(clinicFax);
}
public StringProperty clinicFaxProperty(){
return clinicFax;
}
public boolean getClientHasRequestedFax(){
return clientHasRequestedFax.get();
}
public void setClientHasRequestedFax(boolean clientHasRequestedFax){
this.clientHasRequestedFax.set(clientHasRequestedFax);
}
public BooleanProperty clientHasRequestedFaxProperty(){
return clientHasRequestedFax;
}
}
}
The goal is to get a prompt when the user tries to select fax request when the fax string is empty.
This is already fully explained in the question you already linked, so I don't know what more I can add here other than just to restate it.
The check boxes in the cell are bidirectionally bound to the property that is returned by the selectedStateCallback. If no selectedStateCallback is set, and the cell is attached to a column whose cellValueFactory returns a BooleanProperty (which covers almost all use cases), then the check box's state is bidirectionally bound to that property.
In your code sample, I don't understand what ctCell is for. You just create it, set a selectedStateCallBack on it, and then don't do anything with it. It has nothing to do with your table and nothing to do with the cell factory you set.
So in your case, no selected state callback is set on the cells produced by your cell factory, and the cell value factory returns a boolean property, so the default applies, and the check box state is bidirectionally bound to the property returned by the cell value factory. All you have to do is register a listener with those properties.
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
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.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class CheckBoxTableCellTestApp extends Application {
private TableView<ClinicClientInfo> clientTable = new TableView<>();
private TableColumn<ClinicClientInfo, String> faxCol = new TableColumn<>("Fax");
private TableColumn<ClinicClientInfo, Boolean> requestedFaxCol = new TableColumn<>("Requested Fax");
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
ObservableList<ClinicClientInfo> list = FXCollections.observableArrayList(
new ClinicClientInfo("", false),
new ClinicClientInfo("945-342-4324", true));
// add listeners to boolean properties:
for (ClinicClientInfo clinic : list) {
clinic.clientHasRequestedFaxProperty().addListener((obs, faxWasRequested, faxIsNowRequested) ->{
System.out.printf("%s changed fax request from %s to %s %n",
clinic.getClinicFax(), faxWasRequested, faxIsNowRequested);
});
}
root.getChildren().add(clientTable);
clientTable.getColumns().addAll(faxCol, requestedFaxCol);
clientTable.setItems(list);
clientTable.setEditable(true);
clientTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
faxCol.setCellValueFactory(new PropertyValueFactory<>("clinicFax"));
faxCol.setVisible(true);
requestedFaxCol.setCellValueFactory(new PropertyValueFactory<>("clientHasRequestedFax"));
requestedFaxCol.setCellFactory(CheckBoxTableCell.forTableColumn(requestedFaxCol));
requestedFaxCol.setVisible(true);
requestedFaxCol.setEditable(true);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public class ClinicClientInfo {
private final StringProperty clinicFax;
private final BooleanProperty clientHasRequestedFax;
public ClinicClientInfo(String fax, boolean clientHasRequestedFax){
this.clinicFax = new SimpleStringProperty(fax);
this.clientHasRequestedFax = new SimpleBooleanProperty(clientHasRequestedFax);
}
public String getClinicFax(){
return clinicFax.get();
}
public void setClinicFax(String clinicFax){
this.clinicFax.set(clinicFax);
}
public StringProperty clinicFaxProperty(){
return clinicFax;
}
public boolean getClientHasRequestedFax(){
return clientHasRequestedFax.get();
}
public void setClientHasRequestedFax(boolean clientHasRequestedFax){
this.clientHasRequestedFax.set(clientHasRequestedFax);
}
public BooleanProperty clientHasRequestedFaxProperty(){
return clientHasRequestedFax;
}
}
}

Resources