I am new to SpreadSheet functionality of ControlsFx Api. I would like to open Dialog on right click of Spreadsheetcell of SpreadsheetView in Javafx. Any help is greatly appreciated.
this is code where you can off the standard ContextMenu and implements own handler with Dialog, in this example TextInputDialog:
SpreadsheetView spreadsheetView = new SpreadsheetView();
//off the standard ContextMenu
spreadsheetView.setContextMenu(null);
//set own handler for right click with Dialog
spreadsheetView.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {
#Override public void handle(ContextMenuEvent event) {
CellView cellView = (CellView) event.getTarget();
TextInputDialog dialog = new TextInputDialog(cellView.getText());
Optional<String> result = dialog.showAndWait();
if (result.isPresent()){
System.out.println(cellView.getText());
}
}
});
I don't know very good this library, but it works good.
Example how it works:
My program:
public class MainController extends Application {
public static void main(String[] args) {
launch(args);
}
#Override public void start(Stage primaryStage) throws Exception {
SpreadsheetView spreadsheetView = new SpreadsheetView();
//off the standard ContextMenu
spreadsheetView.setContextMenu(null);
//set own handler for right click with Dialog
spreadsheetView.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {
#Override public void handle(ContextMenuEvent event) {
CellView cellView = (CellView) event.getTarget();
TextInputDialog dialog = new TextInputDialog(cellView.getText());
Optional<String> result = dialog.showAndWait();
if (result.isPresent()) {
System.out.println(cellView.getText());
}
}
});
HBox hBox = new HBox();
hBox.getChildren().add(spreadsheetView);
Scene scene = new Scene(hBox);
primaryStage.setScene(scene);
primaryStage.show();
}
}
It is using mouse handler on the table view which checks when mouse is clicked and on clicking it fires a new dialogue in fx and then accepts the input and updates the fx table view.
table.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getClickCount() == 1) {
Call dialogue method of java fx
}
}
});
Or if you want right click you can create cell
Eg
FirstNameCol.setCellFactory(new Callback<TableColumn<Person, String>, TableCell<Person, String>>() {
#Override
public TableCell<Person, String> call(TableColumn<Person, String> col) {
final TableCell<Person, String> cell = new TableCell<>();
cell.textProperty().bind(cell.itemProperty()); // in general might need to subclass TableCell and override updateItem(...) here
cell.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getButton == MouseButton.SECONDARY) {
// handle right click on cell...
// access cell data with cell.getItem();
// access row data with (Person)cell.getTableRow().getItem();
}
}
});
return cell ;
}
});
Related
I'm creating an JavaFX application with Scene Builder. I added a video at the beginning. So I wanna play video before my application start in fullscreen mode.
The Problem is when it is stopped I see only black screeen and nothing happened, I guess it is because video is fullscreen and it is not automatically closed.
I also have a bug before the video starts, some blink of my main window .I guess it is because video is placed in the controller that begins after my application starts.
How to close video or remove it after finish?
How to place video in main class?
Main Class
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
try {
FXMLLoader loader = new
FXMLLoader(getClass().getResource("resources/fxml/card.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root, 1600, 600);
primaryStage.setScene(scene);
scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setMaximized(true);
primaryStage.setResizable(true);
primaryStage.getIcons().add(new Image("src/card/resources/logo-icon.png"));
primaryStage.show();
//adding resize and drag primary stage
ResizeHelper.addResizeListener(primaryStage);
//assign ALT+ENTER to maximize window
final KeyCombination kb = new KeyCodeCombination(KeyCode.ENTER,
KeyCombination.CONTROL_DOWN);
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>()
{
#Override
public void handle(KeyEvent event) {
if (kb.match(event)) {
primaryStage.setMaximized(!primaryStage.isMaximized());
primaryStage.setResizable(true);
Controller cont = Context.getInstance().getController();
if (!primaryStage.isMaximized()) {
cont.getBtnFont().setPrefWidth(20);
cont.getBtnPalette().setPrefWidth(20);
cont.getBtnQuestCards().setPrefWidth(20);
cont.getBtnNonQuestCards().setPrefWidth(20);
cont.getRandomCard().setTopAnchor(cont.getRandomCard(), 80.0);
cont.getRandomCard().setBottomAnchor(cont.getRandomCard(), 70.0);
cont.getRandomCard().setLeftAnchor(cont.getRandomCard(), 300.0);
cont.getRandomCard().setRightAnchor(cont.getRandomCard(), 200.0);
cont.getRandomCardBack().setTopAnchor(cont.getRandomCardBack(), 80.0);
cont.getRandomCardBack().setBottomAnchor(cont.getRandomCardBack(), 70.0);
cont.getRandomCardBack().setLeftAnchor(cont.getRandomCardBack(), 300.0);
cont.getRandomCardBack().setRightAnchor(cont.getRandomCardBack(), 200.0);
cont.getRectRandom().setWidth(1060);
cont.getRectRandom().setHeight(410);
cont.getRectRandomBack().setWidth(1060);
cont.getRectRandomBack().setHeight(410);
cont.getRandomCard().setPrefWidth(800);
cont.getRandomCard().setPrefHeight(200);
cont.getRandomCardBack().setPrefWidth(800);
cont.getRandomCardBack().setPrefHeight(200);
} else if (primaryStage.isMaximized()){
cont.getBtnFont().setPrefWidth(50);
cont.getBtnPalette().setPrefWidth(50);
cont.getBtnQuestCards().setPrefWidth(50);
cont.getBtnNonQuestCards().setPrefWidth(50);
cont.getRandomCard().setTopAnchor(cont.getRandomCard(), 150.0);
cont.getRandomCard().setBottomAnchor(cont.getRandomCard(), 130.0);
cont.getRandomCard().setLeftAnchor(cont.getRandomCard(), 450.0);
cont.getRandomCard().setRightAnchor(cont.getRandomCard(), 270.0);
cont.getRandomCardBack().setTopAnchor(cont.getRandomCardBack(), 150.0);
cont.getRandomCardBack().setBottomAnchor(cont.getRandomCardBack(), 130.0);
cont.getRandomCardBack().setLeftAnchor(cont.getRandomCardBack(), 450.0);
cont.getRandomCardBack().setRightAnchor(cont.getRandomCardBack(), 270.0);
cont.getRectRandom().setWidth(1160);
cont.getRectRandom().setHeight(760);
cont.getRectRandomBack().setWidth(1160);
cont.getRectRandomBack().setHeight(760);
cont.getRandomCard().setPrefWidth(800);
cont.getRandomCard().setPrefHeight(400);
cont.getRandomCardBack().setPrefWidth(800);
cont.getRandomCardBack().setPrefHeight(400);
}
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
Controller CLass:
#FXML
public void initialize(URL location, ResourceBundle resources) {
String path = new File("src/card/resources/intro.mp4").getAbsolutePath();
me = new Media(new File(path).toURI().toString());
mp = new MediaPlayer(me);
media.setMediaPlayer(mp);
mp.setAutoPlay(true);
media.setSmooth(true);
}
I'm not sure about the blink you see, but it should be easy to react when the video stops.
The JavaFX MediaPlayer class provides a method statusProperty() which returns an object of type ReadOnlyObjectProperty<MediaPlayer.Status>.
The class ReadOnlyObjectProperty<T> implements the interface ObservableValue<T> which provides the method addListener(ChangeListener<? super T>).
The interface ChangeListener<T> is a "functional interface" which requires an implementation for the method void changed(ObservableValue<T> observable, T oldValue, T newValue).
So, putting it together, you should be able to create a listener which will react to the changing status of your MediaPlayer:
private void addStatusListener(MediaPlayer mp) {
ReadOnlyObjectProperty<MediaPlayer.Status> statusProperty = mp.
statusProperty();
statusProperty.addListener((v, o, n) -> playerStatusChanged(v, o, n));
}
private void playerStatusChanged(
ObservableValue<? extends MediaPlayer.Status> observable,
MediaPlayer.Status oldValue, MediaPlayer.Status newValue) {
if (oldValue == MediaPlayer.Status.PLAYING &&
newValue == MediaPlayer.Status.STOPPED) {
// TODO: CALL METHOD TO REACT TO VIDEO BEING STOPPED.
}
}
SOLUTION FOUND!
I made animation to opacity of MediaView:
#FXML public void initialize(URL location, ResourceBundle resources) {
mp = new MediaPlayer(new Media(this.getClass().getResource(MEDIA_URL).toExternalForm()));
media.setMediaPlayer(mp);
media.setSmooth(true);
mp.setAutoPlay(true);
Timeline tm = new Timeline(new KeyFrame(Duration.millis(3000), new KeyValue(media.opacityProperty(), 0.0)));
tm.setDelay(Duration.millis(5500));
tm.play();
}
I'm currently working on javafx and I have a serious problem. I can't find a way to get the index of the row of a button that I created dynamically on a table view.
If someone could help me out, that would be very helpful.
this.clmColumn.setCellFactory((TableColumn<?, ?> column) -> {
return new TableCell<?, ?>() {
#Override
protected void updateItem(? item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
final HBox hbox = new HBox(5);
final VBox vbox = new VBox(5);
Label label = new Label(item.toString());
final Button btnMais = new Button("+");
btnMais.setMinSize(25, 25);
final TableCell<?, ?> c = this;
btnMais.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// At this point i want to select the current ROW of the button that i pressed on the tableview.
}
});
final Button btnMenos = new Button("-");
btnMenos.setMinSize(25, 25);
btnMenos.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if (getItem() > 1) {
// At this point i want to select the current ROW of the button that i pressed on the tableview.
}
}
});
final Button btnRemover = new Button("Remover");
btnRemover.setFont(new Font(8));
btnRemover.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// At this point i want to select the current ROW of the button that i pressed on the tableview.
}
});
vbox.getChildren().add(hbox);
vbox.getChildren().add(btnRemover);
hbox.getChildren().add(btnMais);
hbox.getChildren().add(label);
hbox.getChildren().add(btnMenos);
hbox.setAlignment(Pos.CENTER);
vbox.setAlignment(Pos.CENTER);
setGraphic(vbox);
} else {
setGraphic(null);
}
}
};
});
In the handle() method you can do
Object row = getTableView.getItems().get(getIndex());
You can replace Object with a more specific type if you use more specific types throughout in the type parameters.
I have a button with a ContextMenu which contains a MenuItem rename.
rename.setOnMouseClicked is supposed to give the possibility to change the text in the button : The user can actually delete a letter in the text or write it then press enter to validate what he was typing, somehow working as textField.
Is it possible to do this ? if so, how can i ? Thanks!
Yes
Here's how:
public class EditableButtonApp extends Application {
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
root.setCenter(new EditableButton("Editable Button"));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
class EditableButton extends Button {
TextField tf = new TextField();
public EditableButton(String text) {
setText(text);
setOnMouseClicked(e -> {
tf.setText(getText());
setText("");
setGraphic(tf);
});
tf.setOnAction(ae -> {
// if (validateText(tf.getText())) {// this is where you would validate the text
setText(tf.getText());
setGraphic(null);
// }
});
}
}
public static void main(String[] args) { launch(args); }
}
I am using the following code with java 8 using javaFx.
import javafx.application.Application;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.web.*;
import javafx.stage.Stage;
#SuppressWarnings("all")
public class Highlighter extends Application {
private boolean marked;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
final WebView webView = new WebView();
final WebEngine engine = webView.getEngine();
engine.load("http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html");
final TextField searchField = new TextField("light");
searchField.setPromptText("Enter the text you would like to highlight and press ENTER to highlight");
searchField.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
if (engine.getDocument() != null) {
highlight(
engine,
searchField.getText()
);
}
}
});
final Button highlightButton = new Button("Highlight");
highlightButton.setDefaultButton(true);
highlightButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
searchField.fireEvent(new ActionEvent());
}
});
final Button markedButton = new Button("Mark it");
markedButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
marked = true;
}
});
markedButton.setCancelButton(true);
HBox controls = new HBox(10);
controls.getChildren().setAll(
highlightButton,
markedButton
);
VBox layout = new VBox(10);
layout.getChildren().setAll(searchField, controls, webView);
searchField.setMinHeight(Control.USE_PREF_SIZE);
controls.setMinHeight(Control.USE_PREF_SIZE);
controls.disableProperty().bind(webView.getEngine().getLoadWorker().runningProperty());
searchField.disableProperty().bind(webView.getEngine().getLoadWorker().runningProperty());
primaryStage.setScene(new Scene(layout));
primaryStage.show();
webView.requestFocus();
}
private void highlight(WebEngine engine, String text) {
engine.executeScript("$('body').removeHighlight().highlight('" + text + "')");
}
}
My problem is I want to add a label which displays the marked status of a page.
I tried simply adding a Label label = new Label("Marked: " + marked) to the controls, but this does not work.
Any recommendations how I could add a label to my code to display the marked status?
I appreciate your replies!
If you add a Label to controls with your actual code:
private boolean marked;
Label label = new Label("Marked: " + marked)
controls.getChildren().setAll(
highlightButton,
markedButton,
label
);
it will always show Marked: false, no matter if you change marked afterwards.
If you want that your control responds to changes, JavaFX has observable properties, as you can read here.
So you can replace the boolean primitive with this property that wraps the boolean value:
private final BooleanProperty marked=new SimpleBooleanProperty();
Create the label:
Label label=new Label("Marked: "+marked.get());
HBox controls = new HBox(10);
controls.setAlignment(Pos.CENTER_LEFT);
controls.getChildren().setAll(
highlightButton,
markedButton,
label
);
Change the event for markedButton:
markedButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
marked.set(true);
}
});
(this will work just once, since for now you don't have implemented a way to reset marked to false again)
And finally, add a listener for any change inmarked property:
marked.addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
label.setText("Marked: "+newValue);
}
});
Instead of the listener, you can also use Bindings:
Label label=new Label();
label.textProperty().bind(Bindings.concat("Marked: ").concat(marked));
I am creating a program in JavaFX which lists tasks from a data base and displays a button for each row with allows a user to register the task as claimed in the database. I used the code on this link to help me with the buttons for each row: https://gist.github.com/jewelsea/3081826.
However, after changing the code to fit my program, i am getting an error in relation to setting the action of the cellButton variable. I have also added the class that calls this method, just in case.
CANNOT FIND SYMBOL CONSTRUCTOR, EVENTHANDLER DOES NOT TAKE PARAMETERS..
& METHOD DOES NOT OVERRIDE OR IMPLEMENT A METHOD FROM A SUPERTYPE (I am guessing this error is as a result of the first two errors).
//Define the button cell
private class ButtonCell extends TableCell<task, Boolean> {
final Button cellButton = new Button("Claim");
ButtonCell(){
//Action when the button is pressed
cellButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
// get Selected Item
task currentPerson = (task) ButtonCell.this.getTableView().getItems().get(ButtonCell.this.getIndex());
//remove selected item from the table list
newMan.claimTask(currentPerson.getTaskID());
}
});
}
//Display button if the row is not empty
#Override
protected void updateItem(Boolean t, boolean empty) {
super.updateItem(t, empty);
if(!empty){
setGraphic(cellButton);
}
}
}
x
private TableView createTasksTable() {
TableView tableView = new TableView();
TableColumn<task,String> firstNameCol = new TableColumn<>("Task");
firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<task, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(CellDataFeatures<task, String> p) {
// p.getValue() returns the Person instance for a particular TableView row
return new SimpleStringProperty(p.getValue().getName());
}
});
//Insert Button
TableColumn col_action = new TableColumn<>("Action");
tableView.getColumns().add(col_action);
col_action.setCellValueFactory(
new Callback<TableColumn.CellDataFeatures<task, Boolean>,
ObservableValue<Boolean>>() {
#Override
public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<task, Boolean> p) {
return new SimpleBooleanProperty(p.getValue() != null);
}
});
//Adding the Button to the cell
col_action.setCellFactory(
new Callback<TableColumn<task, Boolean>, TableCell<task, Boolean>>() {
#Override
public TableCell<task, Boolean> call(TableColumn<task, Boolean> p) {
return new ButtonCell();
} });
tableView.getColumns().addAll(firstNameCol);
return tableView;
}
You have probably imported the wrong EventHandler. Make sure you have
import javafx.event.EventHandler ;
and not something from awt.