SwingWorker Cancel Action - multithreading

i've looking for How to cancel my thread, found some answers but it didn't help me.
My app needs to go from 0-X and by pressing Cancel button the thread is canceled and update Atual Label value with the last counting number.
Again: I've found some examples and explications and didn't help me, so please, do not post another post example.
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class SwingWorker extends JFrame {
Thread worker=new Thread();
boolean parar=false;
int em;
public int quantos;
public int sleep;
private JLabel contador = new JLabel("0");
private JLabel statusLabel = new JLabel("N\u00E3o completado");
private JButton startButton = new JButton("Iniciar");
private JLabel atual = new JLabel("0");
JButton btnNewButton = new JButton("Cancelar");
JLabel lblltimoNmero = new JLabel("\u00DAltimo n\u00FAmero");
public SwingWorker(String title) {
super(title);
setTitle("Contador do n\u00FAmero!");
getContentPane().setLayout(null);
contador.setBounds(106, 97, 48, 37);
contador.setFont(new Font("serif", Font.BOLD, 28));
getContentPane().add(contador);
statusLabel.setBounds(76, 155, 139, 14);
getContentPane().add(statusLabel);
startButton.setBounds(35, 210, 79, 23);
getContentPane().add(startButton);
//Button cancelar
btnNewButton.setBounds(118, 210, 100, 23);
getContentPane().add(btnNewButton);
btnNewButton.setEnabled(false);
btnNewButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
parar=true;
atual.setText(""+(em-1));
//----------------------------------------
// Worker cancel action
//worker.cancel();
//-------------------------
}
});
lblltimoNmero.setBounds(10, 288, 110, 14);
getContentPane().add(lblltimoNmero);
atual.setFont(new Font("Serif", Font.BOLD, 28));
atual.setBounds(106, 269, 59, 37);
getContentPane().add(atual);
JButton btnQuantosNmeros = new JButton("Ir at\u00E9");
btnQuantosNmeros.setBounds(35, 244, 79, 23);
getContentPane().add(btnQuantosNmeros);
JButton btnSleepPor = new JButton("Sleep por");
btnSleepPor.setBounds(118, 244, 89, 23);
getContentPane().add(btnSleepPor);
btnSleepPor.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
sleep =Integer.parseInt(JOptionPane.showInputDialog("Thread dormir por(ms): "));
startButton.setEnabled(true);
}
});
btnQuantosNmeros.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
quantos =Integer.parseInt(JOptionPane.showInputDialog("Ir até o número :"));
}
});
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
btnNewButton.setEnabled(true);
start();
startButton.setEnabled(false);
}
});
setSize(244, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
JOptionPane.showMessageDialog(null, "Clique em -Ir até- e em -Sleep por-");
}
private void start() {
worker = new Thread() {
public void run() {
if(quantos!=0){
for(int i=0; i<=quantos; i++) {
final int count = i;
em++;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
contador.setText(Integer.toString(count));
}
});
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
}
}}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
statusLabel.setText("Completo");
startButton.setEnabled(true);
atual.setText(Integer.toString( em-1 ));
em=0;
parar=false;
}
});
}
};
worker.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new SwingWorker("SwingWorker");
}
});
}
}

The correct way to use SwingWorker is to make a subclass of it and override its doInBackground method. See the tutorial for an example: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/simple.html, as well as the tutorial on canceling a SwingWorker: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/cancel.html.
You've created a subclass of JFrame and just named it SwingWorker, so I don't quite understand what you're trying to do. You should possibly find some tutorials on how inheritance works in Java, such as http://docs.oracle.com/javase/tutorial/java/IandI/index.html.

Related

MailJava in a new Thread

I try to get emails from csv file and start mailing process. Everything works fine if I do it in the main thread. But if I start a new thread and try to do it threre it gives me NullPointer on this line:
email.sendEmail(readerEmail.myList, mailingSubject, mailingText);
For some reason it cannot get a list of emails.
Full code is here:
package com.company;
import javax.mail.MessagingException;
import javax.swing.*;
import static com.company.MainFormAppearance.mailingSubject;
import static com.company.MainFormAppearance.mailingText;
public class NewThead implements Runnable {
public JTextArea jTextAreaStatus;
public Reader readerEmail;
private boolean doStop = false;
public synchronized void doStop() {
this.doStop = true;
}
private synchronized boolean keepRunning() {
return this.doStop == false;
}
#Override
public void run() {
while (keepRunning()){
Email email = new Email();
try {
email.sendEmail(readerEmail.myList, mailingSubject, mailingText);
} catch (MessagingException e) {
e.printStackTrace();
}
}
jTextAreaStatus.setText("completed");
}
}
Main class:
public class MainFormAppearance {
private JTextArea jTextAreaText;
private JTextArea jTextAreaSubject;
private JTextArea jTextAreaEmail;
private JTextArea jTextAreaStatus;
private JLabel blueLabel;
private JLabel copyRightLabel;
public JButton parceButton;
private JButton mailButton;
private JButton stopButton;
private String FILE_PATH_TEXT = "c:/Users/R2D2/Desktop/Main.txt";
private String FILE_PATH_SUBJECT = "c:/Users/R2D2/Desktop/Subject.txt";
public String CsvEmailsPath = "C:\\Users\\R2D2\\Desktop\\Emailstest.csv";
public String CsvBusinessesPath = "C:\\Users\\R2D2\\Desktop\\Businessestest.csv";
public static String mailingText = null;
public static String mailingSubject = null;
public Reader readerEmail;
public Reader readerBusiness;
public JPanel createContentPanel() {
JPanel totalGui = new JPanel();
totalGui.setLayout(null);
totalGui.setBackground(new Color(72, 209, 204));
jTextAreaText = new JTextArea();
jTextAreaSubject = new JTextArea();
jTextAreaEmail = new JTextArea();
jTextAreaStatus = new JTextArea();
blueLabel = new JLabel("Java Mailing Program");
copyRightLabel = new JLabel("\u00a9" + " Alex B - 2018");
parceButton = new JButton("Upload");
mailButton = new JButton("!Start!");
stopButton = new JButton("Stop");
readerEmail = new Reader();
readerBusiness = new Reader();
NewThead newThead = new NewThead();
Thread thread = new Thread(newThead);
//set program label
copyRightLabel.setLocation(10, 230);
copyRightLabel.setSize(400, 20);
copyRightLabel.setFont(new Font("Courier New", Font.ITALIC, 12));
copyRightLabel.setHorizontalAlignment(SwingConstants.CENTER);
totalGui.add(copyRightLabel);
//set program label
blueLabel.setLocation(10, 10);
blueLabel.setSize(400, 20);
blueLabel.setFont(new Font("Courier New", Font.ITALIC, 15));
blueLabel.setHorizontalAlignment(SwingConstants.CENTER);
totalGui.add(blueLabel);
//set Button 1 and click
parceButton.setLocation(270, 50);
parceButton.setSize(100, 30);
totalGui.add(parceButton);
parceButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//parce data from files to Strings
mailingText = readLineByLineJava8(FILE_PATH_TEXT);
mailingSubject = readLineByLineJava8(FILE_PATH_SUBJECT);
try {
readerEmail.readCsvFile(CsvEmailsPath);
readerBusiness.readCsvFile(CsvBusinessesPath);
} catch (IOException e1) {
e1.printStackTrace();
}
if (isNullOrEmpty(mailingText)) {
jTextAreaText.setText("Text is empty! Check it!!!");
} else {
jTextAreaText.setText("***Text is Ready***");
}
if (isNullOrEmpty(mailingSubject)) {
jTextAreaSubject.setText("Subject is empty! Check it!!!");
} else {
jTextAreaSubject.setText("***Subject is Ready***");
}
}
});
//set Button 2 and click
mailButton.setLocation(270, 100);
mailButton.setSize(100, 30);
totalGui.add(mailButton);
mailButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
thread.start();
}
});
stopButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
newThead.doStop();
jTextAreaStatus.setText("Stopped");
}
});
stopButton.setLocation(270, 150);
stopButton.setSize(100, 30);
totalGui.add(stopButton);
jTextAreaText.setLocation(20, 52);
jTextAreaText.setSize(200, 16);
jTextAreaText.setFont(new Font("Courier New", Font.ITALIC, 12));
jTextAreaText.setBorder(BorderFactory.createLineBorder(new Color(169, 169, 169)));
totalGui.add(jTextAreaText);
jTextAreaSubject.setLocation(20, 82);
jTextAreaSubject.setSize(200, 16);
jTextAreaSubject.setFont(new Font("Courier New", Font.ITALIC, 12));
jTextAreaSubject.setBorder(BorderFactory.createLineBorder(new Color(169, 169, 169)));
totalGui.add(jTextAreaSubject);
jTextAreaEmail.setLocation(20, 112);
jTextAreaEmail.setSize(200, 16);
jTextAreaEmail.setFont(new Font("Courier New", Font.ITALIC, 12));
jTextAreaEmail.setBorder(BorderFactory.createLineBorder(new Color(169, 169, 169)));
totalGui.add(jTextAreaEmail);
jTextAreaStatus.setLocation(20, 182);
jTextAreaStatus.setSize(200, 16);
jTextAreaStatus.setFont(new Font("Courier New", Font.ITALIC, 12));
jTextAreaStatus.setBorder(BorderFactory.createLineBorder(new Color(169, 169, 169)));
totalGui.add(jTextAreaStatus);
totalGui.setOpaque(true);
return totalGui;
}
public static boolean isNullOrEmpty(String str) {
if (str != null && !str.isEmpty())
return false;
return true;
}
}
Class that reads emails from csv (should be correct):
package com.company;
import au.com.bytecode.opencsv.CSVReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
public class Reader {
public CSVReader reader;
public LinkedList myList;
public void readCsvFile(String path) throws IOException {
try {
reader = new CSVReader(new FileReader(path));
String[] column;
myList = new LinkedList<>();
LinkedList <String> map;
while ((column = reader.readNext()) != null) {
map = new LinkedList<String>();
map.add(column[0]);
myList.add(String.valueOf(map).replace("[","").replace("]",""));
//myList.add(String.valueOf(map));
}
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Why i do it in another thread? Because I want to have a chance to stopp mailing process by clicking in stop button and killing a new thread.

Java Jlabel setText

I am a java beginner, i used eclipse to make a gridbaglayout:
import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.GridBagLayout;
import javax.swing.JLabel;
import java.awt.GridBagConstraints;
public class test4 {
public static JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
test4 window = new test4();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public test4() {
initialize();
}
/**
* Initialize the contents of the frame.
* #return
*/
public static void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 137, 89);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWidths = new int[]{0, 0};
gridBagLayout.rowHeights = new int[]{0, 0};
gridBagLayout.columnWeights = new double[]{0.0, Double.MIN_VALUE};
gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE};
frame.getContentPane().setLayout(gridBagLayout);
JLabel lblNewLabel = new JLabel("Label");
GridBagConstraints gbc_lblNewLabel = new GridBagConstraints();
gbc_lblNewLabel.gridx = 0;
gbc_lblNewLabel.gridy = 0;
frame.getContentPane().add(lblNewLabel, gbc_lblNewLabel);
}
}
i want to use {lblNewLabel.setText("test");} in {public static void main(String[] args) } or in {private static set(){lblNewLabel.setText("test");}} but it did not work. What should i do? Thanks for any help.
public class MyNiceApplication {
private Label niceLabel;
void initialize(){...} //Frame init...
public void setNiceLabelText(String text){
niceLabel.setText(text);
}
}
public static void main(String[] args) {
MyNiceApplication app = new MyNiceApplication();
app.setNiceLabelText("New LabelText");
}

Running an infinite loop in a JavaFX(Embedded in javax.swing.JFrame) App

I am trying to run an Infinite loop in my JavaFX app.
An infinite while loop is present in my code in the Kulta.java file.
This loop actually freezes my app.
While the same thing works when I port the app to normal javax.swing.
Now since java.lang.Thread doesn't work for javafx, I came accross javafx.concurrent.Task,
which is not working as intended. As one of the main features of multithreading, i.e. running an infinite loop in a GUI app, is not served properly, please help me with the solution.
This is my code:
Urania.java
import java.awt.Toolkit;
import java.awt.Dimension;
import javax.swing.SwingUtilities;
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
public class Urania {
public static final Dimension DIMENSION = Toolkit.getDefaultToolkit().getScreenSize();
public static void main(String[] args) {
SwingUtilities.invokeLater(
new Runnable() {
#Override
public void run() {
Kulta kulta = new Kulta();
kulta.setTitle("Abha K Pauri");
kulta.setSize(DIMENSION.width/2, DIMENSION.height/2);
kulta.setLocationRelativeTo(null);
kulta.setDefaultCloseOperation(EXIT_ON_CLOSE);
kulta.setVisible(true);
}
}
);
}
}
And here is my JFrame in which I have embedded my JavaFX app.
Kulta.java
import javax.swing.JFrame
import javafx.embed.swing.JFXPanel;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.control.Button;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.concurrent.Task;
public class Kulta extends JFrame {
private JFXPanel fxpanel;
private Scene scene;
private BorderPane borderpane;
private Button button;
public static final String INVOKE = "INVOKE";
public static final String INTERRUPT = "INTERRUPT";
public static final String[] COLORS = new String[]{"yellow", "pink", "green", "blue", "orange"};
public Kulta() {
fxpanel = new JFXPanel();
add(fxpanel);
Platform.runLater(
new Runnable() {
#Override
public void run() {
Kulta.this.setScene();
Kulta.this.setButton();
Kulta.this.setListener();
}
}
);
}
private void setScene() {
borderpane = new BorderPane();
scene = new Scene(borderpane);
fxpanel.setScene(scene);
}
private void setButton() {
button = new Button(INVOKE);
borderpane.setTop(button);
}
private void setListener() {
Event event = new Event();
button.setOnAction(event);
}
private class Event implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent event) {
boolean flag = true;
Task<Void> onInvoke = new Task<Void>() {
#Override
public Void call() {
int count = 0;
flag = true;
button.setText(INTERRUPT);
/* This loop freezes the app. */
while(flag) {
borderpane.setStyle("-fx-color: "+COLORS[count]+";");
count++;
if(count == COLORS.length)
count = 0;
}
return null;
}
};
Task<Void> onInterrupt = new Task<Void>() {
#Override
public Void call() {
button.setText(INVOKE);
if(flag)
flag = false; // This will stop the onInvoke thread
return null;
}
};
Task<Void> change = new Task<Void>() {
#Override
public Void call() {
if(button.getText().equals(INVOKE))
onInvoke().run();
else if(button.getText().equals(INTERRUPT))
onInterrupt().run();
}
};
change.run();
}
}
}
How should I write the loop in order to not let the app freeze.
Any code, solution, link or any help in any form will help a lot.
Thanks in advance.

Could some one help me with my Runnable. I have tried 3 different ways to handle this but I still can not seem to figure it out

my problem is in the onClick method. I just can't seem to figure out the how to properly construct a running Runnable/Thread/Handler.
package sed.jeff.conversion;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
public class MainActivity extends Activity
{
private static final String TAG = "MainActivity";
Button btConvert;
EditText etInitialValue;
TextView tvAnswer;
Spinner spInitialType, spFinalType;
int mInitialValue, mInitialType, mFinalValue, mFinalType, mRegion = 0;
Distance D1;
Handler handler;
Runnable r;
//initialization
#Override
protected void onCreate(Bundle savedInstanceState)
{
Log.i(TAG, "entered onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btConvert = (Button)findViewById(R.id.btnConvert);
etInitialValue = (EditText)findViewById(R.id.etInitialValue);
spInitialType = (Spinner)findViewById(R.id.spInitialType);
spFinalType = (Spinner)findViewById(R.id.spFinalType);
D1 = new Distance();
}
//implementation
protected void onStart()
{
Log.i(TAG, "entered onStart()");
super.onStart();
spInitialType.setOnItemSelectedListener(new OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
// TODO Auto-generated method stub
Log.i(TAG, "Initial Type position 1: " + position);
mInitialType = position;
}
#Override
public void onNothingSelected(AdapterView<?> parent)
{
// TODO Auto-generated method stub
}
});
spFinalType.setOnItemSelectedListener(new OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
// TODO Auto-generated method stub
Log.i(TAG, "Initial Type position 2: " + position);
mFinalType = position;
}
#Override
public void onNothingSelected(AdapterView<?> parent)
{
// TODO Auto-generated method stub
}
});
btConvert.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
Log.i(TAG, "entered onClick()");
handler = new Handler();
r = new Runnable()
{
#Override
public void run()
{
tvAnswer.setText(D1.getAnswer(mRegion, mInitialType, mFinalType, Double.parseDouble(etInitialValue.getText().toString())));
handler.post(this);
}
};
handler.post(r);
}
});
}
}
This is the class I am using to do the conversion. The only important methods here as of right now are the constructor with no inputs and the String getAnswer() method.
package sed.jeff.conversion;
public class Distance
{
double league, mile, yard, feet, inch, line, thou;
double decameter, hectometer, kilometer, megameter, meter, decimeter, centermeter, micrometer;
double fathom, nauticalMile;
double chain, rod;
double furlong, horseLength;
double hubbleLength, parsec, lightYear, astronomicalUnit;
/*(
private static double[] THOU = {1, 83.333333, 1000, 12000, 36000, 63360000, 190080000};
private static double[] LINE = {.012, 1, 12, 144, 432, 760320, 2280960};
private static double[] INCH = {.001, .083333, 1, 12, 36, 63360, 190080};
private static double[] FOOT = {.000083, .006944, .083333, 1, 3, 5280, 15840};
private static double[] YARD = {.000028, .002315, .027778, .333333, 1, 1760, 5280};
private static double[] MILE = {.00000001578, .000001315, .0000157828, .00018939, .0005681818, 1, 3};
private static double[] LEAGUE = {.00000000526, .00000043841, .00000526094, .00006313131, .0001893939, .33333333, 1};
*/
private static double[][] CONVERSION_USA = {{1, 83.333333, 1000, 12000, 36000, 63360000, 190080000},
{.012, 1, 12, 144, 432, 760320, 2280960},
{.001, .083333, 1, 12, 36, 63360, 190080},
{.000083, .006944, .083333, 1, 3, 5280, 15840},
{.000028, .002315, .027778, .333333, 1, 1760, 5280},
{.00000001578, .000001315, .0000157828, .00018939, .0005681818, 1, 3},
{.00000000526, .00000043841, .00000526094, .00006313131, .0001893939, .33333333, 1}
};
public double[] answer;
public Distance()
{
answer = new double[7];
}
public Distance(int type, int initialMeasurement, double value)
{
answer = new double[7];
switch(type)
{
case 0:
uSMeasurments(initialMeasurement, value);
break;
}
}
private void uSMeasurments(int initialType, double value)
{
for(int i = 0; i < 7; i++ )
{
answer[i] = CONVERSION_USA[initialType][i] * value;
}
}
public String getAnswer(int region, int initialType, int finalType, double value)
{
String answer = null;
switch(region)
{
case 0:
answer = Double.toString(CONVERSION_USA[initialType][finalType] * value);
break;
}
return answer;
}
public String toString()
{
String finalAnswer = "";
for(int i = 0; i < 7; i++ )
{
finalAnswer += answer[i] + " ";
}
return finalAnswer;
}
}
In this case i do not think that you need to use a handler.
Otherwise a proper way would be to do something on these lines:
Runnable r=new Runnable() {
#Override
public void run() {
tvAnswer.setText(D1.getAnswer(mRegion, mInitialType, mFinalType, Double.parseDouble(etInitialValue.getText().toString())));
}
};
handler.post(r);

To Hide JavaFx fxml or JavaFx swing application to System Tray

I want to develop a client app for website .
I want the app to reside in system tray when minimised.
I dont know how to accomplish this task .
Is their any example for this type of operation.
The key here is to set the implicit exit to false Platform.setImplicitExit(false);
Also is important to show and hide the stage in a new thread.
Platform.runLater(new Runnable() {
#Override
public void run() {
stage.show();
}
});
Platform.runLater(new Runnable() {
#Override
public void run() {
stage.hide();
}
});
Next, the whole code:
import java.awt.AWTException;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javax.imageio.ImageIO;
/**
*
* #author alvaro
*/
public class TrayTest extends Application {
private boolean firstTime;
private TrayIcon trayIcon;
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
createTrayIcon(stage);
firstTime = true;
Platform.setImplicitExit(false);
Scene scene = new Scene(new Group(), 800, 600);
stage.setScene(scene);
stage.show();
}
public void createTrayIcon(final Stage stage) {
if (SystemTray.isSupported()) {
// get the SystemTray instance
SystemTray tray = SystemTray.getSystemTray();
// load an image
java.awt.Image image = null;
try {
URL url = new URL("http://www.digitalphotoartistry.com/rose1.jpg");
image = ImageIO.read(url);
} catch (IOException ex) {
System.out.println(ex);
}
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent t) {
hide(stage);
}
});
// create a action listener to listen for default action executed on the tray icon
final ActionListener closeListener = new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
System.exit(0);
}
};
ActionListener showListener = new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
Platform.runLater(new Runnable() {
#Override
public void run() {
stage.show();
}
});
}
};
// create a popup menu
PopupMenu popup = new PopupMenu();
MenuItem showItem = new MenuItem("Show");
showItem.addActionListener(showListener);
popup.add(showItem);
MenuItem closeItem = new MenuItem("Close");
closeItem.addActionListener(closeListener);
popup.add(closeItem);
/// ... add other items
// construct a TrayIcon
trayIcon = new TrayIcon(image, "Title", popup);
// set the TrayIcon properties
trayIcon.addActionListener(showListener);
// ...
// add the tray image
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println(e);
}
// ...
}
}
public void showProgramIsMinimizedMsg() {
if (firstTime) {
trayIcon.displayMessage("Some message.",
"Some other message.",
TrayIcon.MessageType.INFO);
firstTime = false;
}
}
private void hide(final Stage stage) {
Platform.runLater(new Runnable() {
#Override
public void run() {
if (SystemTray.isSupported()) {
stage.hide();
showProgramIsMinimizedMsg();
} else {
System.exit(0);
}
}
});
}
}
As far as I know it will be possible in JFX 8. Right now the best solution is to embed your application into AWT and hide the AWT window itself.

Resources