I want to send E-Mail when I click on a menu.
MenuItem sendmail= new MenuItem("Send E-Mail");
sendmail.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
// Call E-mail Client
}
});
Can you tell me how I can call e-mail client installed to the user PC from this code?
This is undocumented, but appears to work, and is a "pure FX" solution rather than relying on java.awt APIs or knowing the location of external executables. Call the Application.getHostServices().showDocument(...) method and pass in a mailto: url as the url:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class OpenDefaultBrowser extends Application {
#Override
public void start(Stage primaryStage) {
final HBox root = new HBox(5);
final TextField textField = new TextField("help#example.com");
final Button goButton = new Button("Mail");
EventHandler<ActionEvent> goHandler = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
getHostServices().showDocument("mailto:"+textField.getText());
}
};
textField.setOnAction(goHandler);
goButton.setOnAction(goHandler);
root.getChildren().addAll(textField, goButton);
final Scene scene = new Scene(root, 250, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
You can use the Desktop class. I believe the code would look something like:
import java.awt.Desktop;
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
if (desktop.isSupported(Desktop.Action.MAIL)) {
URI mailto = new URI("mailto:john#example.com?subject=Hello%20World");
desktop.mail(mailto);
}
}
I learned from #James_D example. In my case, I want users to email me in case there are issues with this app I developed. Because the email does not change, I thought it was best, for this specific case, to include a JavaFX Hyperlink to a "mail to" email address. The code is as follows:
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Report an issue");
alert.setHeaderText(null);
Text msg = new Text("For issues, email ");
Hyperlink emailLink = new Hyperlink("hector#foo.com");
emailLink.setOnAction(event -> {
getHostServices().showDocument("mailto:" + emailLink.getText());
alert.close(); // to dimiss the alert if user clicks hyperlink
});
TextFlow flow = new TextFlow(msg, emailLink);
DialogPane dialogPane = alert.getDialogPane();
dialogPane.setContent(flow);
alert.showAndWait();
This works fine if you have an email client like Outlook. We use Google Suite, which means we use Gmail. For Windows, if an email client is not installed, it will default to the Windows Mail app. I needed to open Gmail on the browser. So, I needed to change this on the Windows settings.
If you just want to start a separate process which represents the e-mail client, use java.lang.Runtime.exec (see http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html) or if you want the client to be embedded, use Java Mail API (http://www.oracle.com/technetwork/java/javamail/index.html)
Related
In running a Java program, using IntelliJ Community Edition 2021.2, I am seeing console output "java[934:22850] +[CATransaction synchronize] called within transaction" when a FileChooser dialog box is displayed. The dialog appears to work OK, but I'm puzzled about the message.
MacOS 13.0.1 (Ventura);
IntelliJ Community Edition 2021.2;
JDK 15.0.2;
JavaFX 15.0.1+1
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.io.*;
public class Main extends Application {
// ..................... and now it's time for the main routine .....................
#Override
public void start(Stage primaryStage) {
// we need a FileChooser
FileChooser myChooser = new FileChooser();
// set up a controlled exit
primaryStage.setOnCloseRequest(e -> {
e.consume();
primaryStage.close();
});
// define the main scene's building blocks
VBox root = new VBox(5); // the spacing is between each element in the VBox
Scene mainScene = new Scene(root, 650, 300);
// just one button in the scene
Button websiteSupportButton = new Button("Process file");
websiteSupportButton.setMinWidth(150);
root.getChildren().add(websiteSupportButton);
websiteSupportButton.setOnAction(e -> processFiles(primaryStage, myChooser));
// and now we're ready to associate the root Scene with the primary stage, and show it
primaryStage.setX(20);
primaryStage.setY(20);
primaryStage.setScene(mainScene);
primaryStage.setTitle("Error test");
primaryStage.show();
}
// .................................. tool scenes ..................................
// stuff moved from WebsiteSupport, and severely cut down - select an input file.
private static void processFiles(Stage myStage, FileChooser myChooser) {
File inputFile;
// need to select an input file - displaying this dialog causes multiple "java[1334:69043] +[CATransaction synchronize] called within transaction" messages
inputFile = myChooser.showOpenDialog(myStage);
if (inputFile != null) {
System.out.println(" file processed");
}
}
// .......................................... standard stuff ..........................................
public static void main(String[] args) {
launch(args);
}
}
I tried your code on:
OS X (intel) 13.0.1
JavaFX 19
OpenJDK 19.0.1
It received the same error message (multiple times for a single call):
java[34308:361725] +[CATransaction synchronize] called within transaction
I believe it occurs every time the file chooser showOpenDialog method is invoked in this configuration. A minimal example which replicates the issue on execution is:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class FileChooserCATransactionLogGeneratorApp extends Application {
#Override
public void start(Stage stage) {
stage.setScene(new Scene(new Group()));
stage.show();
FileChooser myChooser = new FileChooser();
myChooser.showOpenDialog(stage);
}
public static void main(String[] args) {
launch(args);
}
}
I advise filing a bug report.
If you do file a bug report and a bug id is generated, you can add a link to the bug report as a comment or an edit on this answer.
I am having some difficulty understanding how to set up a pop up window that displays a web page in my Swing application. I have seen this code across multiple tutorials but what I am struggling with is how to include this in my own code.
Every tutorial uses the main method with this code, but I want to call this from one of my other classes and I am not sure how.
This is the code in question:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebViewMain extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("WebView test");
WebView browser = new WebView();
WebEngine engine = browser.getEngine();
String url = "http://zoranpavlovic.blogspot.com/";
engine.load(url);
StackPane sp = new StackPane();
sp.getChildren().add(browser);
Scene root = new Scene(sp);
primaryStage.setScene(root);
primaryStage.show();
}
}
I want to be able to call the WebView from an ActionListener in one of my classes like this:
JButton mapExpandBtn = new JButton();
mapExpandBtn.setText("Expand");
mapExpandBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
new WebViewMain();
}
});
This doesn't work obviously. How can I adapt my own code or the WebViewMain code to get it to launch in my application?
In one of my recent projects I want to implement a hidden page. I want to be able to reach it by just typing the password without anything showing on the screen. I tried to just set a PasswordField as visible(false). However that didn't work. Also I would like the hidden page to pop up without having to press enter after typing the password. Is there a way for a simple javafx application to behave like that?
You could use a KeyListener. Though you need to press the screen once for the keypresses to register. And make sure to add the keylistener to the JFrame, I always forget that. This will look for keys, but requires a window to be shown, this can be empty though.
If you don't want a window at all, you can use the external library jnativehook it looks for keypresses globally.
You can add an event filter to the scene that keeps track of what has been typed.
Here is a simple example (type "secret" with the main window focussed to show the popup window; press enter if you mistype to clear the hidden text):
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class OpenSecretWindow extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Type the secret password\nto open the secret window");
label.setTooltip(new Tooltip("The secret password is \"secret\""));
StackPane root = new StackPane(label);
Scene scene = new Scene(root, 400, 400);
StringBuilder typedText = new StringBuilder();
scene.addEventFilter(KeyEvent.KEY_TYPED, e -> {
switch(e.getCharacter()) {
case "\n":
case "\r":
typedText.delete(0, typedText.length());
break ;
default:
typedText.append(e.getCharacter());
}
if ("secret".equals(typedText.toString())) {
openSecretWindow(primaryStage);
typedText.delete(0, typedText.length());
}
});
// handle backspace and delete:
scene.addEventFilter(KeyEvent.KEY_RELEASED, e -> {
if (e.getCode() == KeyCode.BACK_SPACE || e.getCode() == KeyCode.DELETE) {
if (typedText.length() > 0) {
typedText.delete(typedText.length()-1, typedText.length());
}
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
private void openSecretWindow(Stage owner) {
Stage stage = new Stage();
StackPane root = new StackPane(new Label("You have found\nthe secret window!"));
Scene scene = new Scene(root, 300, 180);
stage.setScene(scene);
stage.initOwner(owner);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I believe you could set the foreground of the JPasswordField to be the same as the background colour but don't quote me on that. Something like:
JPasswordField.SetForeground(Color.RED);
I want to automatically put the contents into a textArea when a text in notepad is copied via Ctrl+C. I'm wondering of how to listen to the Keys of notepad. Is it possible to listen to Keys of notepad or any other program?
Here is a JavaFX version of the clipboard listeners referenced in other answers and comments:
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.input.Clipboard;
import javafx.stage.Stage;
public class SystemClipboardWatcher extends Application {
#Override
public void start(Stage primaryStage) {
TextArea clipboardView = new TextArea();
AnimationTimer timer = new AnimationTimer() {
Clipboard systemClipboard = Clipboard.getSystemClipboard();
#Override
public void handle(long timestamp) {
String content = systemClipboard.getString();
// do anything you need with this, e.g.:
clipboardView.setText(content);
}
};
timer.start();
primaryStage.setScene(new Scene(clipboardView, 600, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
No, it is not possible to get all keyevents of all application in java.
So you have 2 possible solutions.
You only get the changes of the clipboard, with a clipboard-listener. SO example
Use of JNA, JNI, jintellitype, ... to listen to the system-keyevents SO example
It is possible but a very bad coding practice. If you still want to do it: https://github.com/kwhat/jnativehook.
A way better idea would be to watch for changes in the clipboard.
I have trouble when closing a window in JavaFX.
I define my setOnCloseRequest as I wanted and it works when I click the x in the window. However, I also need a button to close the window and this onCloseRequest has to work, the problem is it does not. The event does not fire at all.
I am using JavaFX 2.2 (Java 7) and I notice that the reference for setOnCloseRequest says close the window on external request
Solution
Fire an event from your internal close request (on the button push), so that the application thinks it received an external close request. Then your close request logic can be identical whether the request came from an external event or an internal one.
private EventHandler<WindowEvent> confirmCloseEventHandler = event -> {
// close event handling logic.
// consume the event if you wish to cancel the close operation.
}
...
stage.setOnCloseRequest(confirmCloseEventHandler);
Button closeButton = new Button("Close Application");
closeButton.setOnAction(event ->
stage.fireEvent(
new WindowEvent(
stage,
WindowEvent.WINDOW_CLOSE_REQUEST
)
)
);
Note
This is a Java 8+ solution, for JavaFX 2, you will need to convert the lambda functions in anonymous inner classes and will be unable to use the Alert dialog box but will need to provide your own alert dialog system as JavaFX 2 does not feature an in-built one. I strongly recommend upgrading to Java 8+ rather than staying with JavaFX 2.
Sample UI
Sample Code
The sample code will show the user a close confirmation alert and cancel the close request if the user does not confirm the close.
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.*;
import javafx.stage.WindowEvent;
import java.util.Optional;
public class CloseConfirm extends Application {
private Stage mainStage;
#Override
public void start(Stage stage) throws Exception {
this.mainStage = stage;
stage.setOnCloseRequest(confirmCloseEventHandler);
Button closeButton = new Button("Close Application");
closeButton.setOnAction(event ->
stage.fireEvent(
new WindowEvent(
stage,
WindowEvent.WINDOW_CLOSE_REQUEST
)
)
);
StackPane layout = new StackPane(closeButton);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
private EventHandler<WindowEvent> confirmCloseEventHandler = event -> {
Alert closeConfirmation = new Alert(
Alert.AlertType.CONFIRMATION,
"Are you sure you want to exit?"
);
Button exitButton = (Button) closeConfirmation.getDialogPane().lookupButton(
ButtonType.OK
);
exitButton.setText("Exit");
closeConfirmation.setHeaderText("Confirm Exit");
closeConfirmation.initModality(Modality.APPLICATION_MODAL);
closeConfirmation.initOwner(mainStage);
// normally, you would just use the default alert positioning,
// but for this simple sample the main stage is small,
// so explicitly position the alert so that the main window can still be seen.
closeConfirmation.setX(mainStage.getX());
closeConfirmation.setY(mainStage.getY() + mainStage.getHeight());
Optional<ButtonType> closeResponse = closeConfirmation.showAndWait();
if (!ButtonType.OK.equals(closeResponse.get())) {
event.consume();
}
};
public static void main(String[] args) {
launch(args);
}
}