How to have a menu on the mac top toolbar with JavaFX? - java

On Mac OS, applications that run in the background sometimes have their icon attached to a gui or menu in the right corner of the screen. I believe it is similar to what Windows has on the bottom-right corner.
However I want this for my JavaFX application as well. And I don't know how to google for that. All I found was JavaFX' MenuBar, what unfortunately is not what I'm looking for.

You need to set a system property in order to move it out from your JFrame:
System.setProperty("apple.laf.useScreenMenuBar", "true");
This will show your JMenuBar in the MacOS Toolbar.
Or you could check if you are running MacOS and then set the property:
if (System.getProperty("os.name").contains("Mac")) {
System.setProperty("apple.laf.useScreenMenuBar", "true");
}

public class SystemTray {
private static final Logger logger = LogManager.getLogger(Main.class);
public static java.awt.SystemTray tray = java.awt.SystemTray.getSystemTray(); // set up a system tray icon.
public static TrayIcon trayIcon;
public static Image trayIconImage;
public static MenuItem startRecording;
public static MenuItem stopRecording;
public static MenuItem playRecording;
public static MenuItem pauseRecording;
public static MenuItem startOver;
public static MenuItem exitItem;
final static PopupMenu popup=new PopupMenu();
public static boolean windows = Main.checkOS();
public SystemTray() {
}
public static void addAppToTray() {
try {
// ensure awt toolkit is initialized.
Toolkit.getDefaultToolkit();
URL IconPath;
// app requires system tray support, just exit if there is no support.
if (!java.awt.SystemTray.isSupported()) {
System.out.println("No system tray support, application exiting.");
return;
//Platform.exit();
}
if (windows) {
File file = new File("./resources/main/cogwheel-win.png");
// IconPath =this.getClass().getResource("cogwheel-windows.png");
IconPath =file.toURI().toURL();
}
else {
File file = new File("./resources/main/cogwheel-mac.png");
// IconPath =this.getClass().getResource("cogwheel-mac.png");
IconPath =file.toURI().toURL();
}
logger.info(IconPath.getFile().toString());
trayIconImage = ImageIO.read(IconPath);
trayIcon = new TrayIcon(trayIconImage);
startRecording = new MenuItem("Start Recording (Shift+Space)");
stopRecording = new MenuItem("Stop Recording (Shift+Space)");
playRecording = new MenuItem("Play Recording (Shift+P)");
pauseRecording = new MenuItem("Pause Recording (Shift+P)");
startOver = new MenuItem("Start Over (Shift+R)");
//openItem.addActionListener(event -> Platform.runLater(this::showStage));
// and select the exit option, this will shutdown JavaFX and remove the
// tray icon (removing the tray icon will also shut down AWT).
exitItem = new MenuItem("Quit CAD");
exitItem.addActionListener(event -> {
Platform.exit();
tray.remove(trayIcon);
});
// setup the popup menu for the application.
popup.add(startRecording);
popup.add(stopRecording);
popup.addSeparator();
popup.add(playRecording);
popup.add(pauseRecording);
popup.addSeparator();
popup.add(startOver);
popup.addSeparator();
popup.add(exitItem);
trayIcon.setPopupMenu(popup);
// add the application tray icon to the system tray.
tray.add(trayIcon);
// startRecording.addActionListener(event -> Platform.runLater(Creator::startRecording));
} catch (AWTException | IOException e) {
System.out.println("Unable to init system tray");
logger.info(e.getMessage());
}
}
}

I write apps like this a lot, and this is what I discovered as being the easiest and most effective way to use Java/FX to create an app on MacOS that only exists as an icon in the system tray.
I utilize the FXTrayIcon library to accomplish this as that library does the conversions between JavaFX and AWT quite nicely.
First I just add this to my POM file:
<dependency>
<groupId>com.dustinredmond.fxtrayicon</groupId>
<artifactId>FXTrayIcon</artifactId>
<version>3.3.0</version>
</dependency>
Then I use a Launcher class which takes advantage of what AWT can do that JavaFX cannot which is get rid of the Dock icon (not to mention still no native FX support for the system tray).
import java.awt.*;
public class Launcher {
public static void main(String[] args) {
System.setProperty("apple.awt.UIElement", "true");
Toolkit.getDefaultToolkit();
Main.main(args);
}
}
Then here is a simple Main class that is fully functional
import com.dustinredmond.fxtrayicon.FXTrayIcon;
import javafx.application.Application;
import javafx.stage.Stage;
import java.net.URL;
public class Main extends Application {
private URL icon = Main.class.getResource("icon.png");
#Override public void start(Stage primaryStage) throws Exception {
new FXTrayIcon.Builder(primaryStage, icon, 22, 22)
.menuItem("Say Hello", e->helloIcon())
.separator()
.addExitMenuItem("Exit", e-> System.exit(0))
.show()
.build();
}
private void helloIcon() {
System.out.println("Hello Icon");
}
public static void main(String[] args) {
launch(args);
}
}
This is what it looks like, and no Dock icon at all nor does the app show up in the CMD+TAB app switching.

Related

windows 10 notification - OpenJDK Platform Binary

I made a Windows 10 notification using the Eclipse IDE. I can't seem to get rid of the "OpenJDK Platform Binary" which shows whenever the notification pops up. I tried "MessageType.NONE" but it's still there.
Note: I can only solve this problem using Java.
import java.awt.*;
import java.awt.TrayIcon.MessageType;
public class notif {
public static void main(String[] args) throws AWTException {
notif td = new notif();
td.notifDisplay();
}
public void notifDisplay() throws AWTException {
SystemTray tray = SystemTray.getSystemTray();
Image img = Toolkit.getDefaultToolkit().createImage("icon.png");
TrayIcon trayIcon = new TrayIcon(img, "pepsi");
trayIcon.setImageAutoSize(true);
trayIcon.setToolTip("pepsi");
tray.add(trayIcon);
trayIcon.displayMessage("we are out of pepsi", ":(", MessageType.NONE);
}
}

Launch error while running javafx program

I am running a simple javafx program on eclipse IDE. However, whenever I run my code, a launch error is displayed. There is no description of the error by the IDE and I am not sure what is causing that.
Also, I have e(fx)clipse and Gluon plugin installed.
My code is very simple and I don't think that it is causing this error, however, I have attached it below for reference.
package application;
import Menus.MainMenu;
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
MainMenu mainMenu = new MainMenu();
primaryStage = mainMenu.getMainStage();
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Code for MainMenu is
package Menus;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class MainMenu {
private static final int HEIGHT = 600;
private static final int WIDTH = 800;
private AnchorPane mainPane;
private Scene mainScene;
private Stage mainStage;
public MainMenu() {
mainPane = new AnchorPane();
mainScene = new Scene(mainPane);
mainStage = new Stage();
mainStage.setScene(mainScene);
mainStage.setFullScreen(true);
}
public Stage getMainStage() {
return mainStage;
}
}
Check the log file for the exact error and resolve it at :
C:\app\eclipse\configuration\
Check if the JRE is properly configured in eclipse as well as environment variables.
Do not just click on the run button, check if you are running the proper program path by clicking on the arrow next to run. (This is a common problem with beginners)
If you find everything else troublesome, try re-installing the IDE and running a simple hello world. If the problem persists, it is something to do with the environment variables or your eclipse setup.

Set a desktop notification at the specified date [duplicate]

In Windows 10 there is a notification that opens in the bottom right of the screen and I find them quite useful.
Is there is any way to create Windows notifications in Java? This is what they look like:
I can successfully produce this result using this very simple sample code:
import java.awt.*;
import java.awt.TrayIcon.MessageType;
public class TrayIconDemo {
public static void main(String[] args) throws AWTException {
if (SystemTray.isSupported()) {
TrayIconDemo td = new TrayIconDemo();
td.displayTray();
} else {
System.err.println("System tray not supported!");
}
}
public void displayTray() throws AWTException {
//Obtain only one instance of the SystemTray object
SystemTray tray = SystemTray.getSystemTray();
//If the icon is a file
Image image = Toolkit.getDefaultToolkit().createImage("icon.png");
//Alternative (if the icon is on the classpath):
//Image image = Toolkit.getDefaultToolkit().createImage(getClass().getResource("icon.png"));
TrayIcon trayIcon = new TrayIcon(image, "Tray Demo");
//Let the system resize the image if needed
trayIcon.setImageAutoSize(true);
//Set tooltip text for the tray icon
trayIcon.setToolTip("System tray icon demo");
tray.add(trayIcon);
trayIcon.displayMessage("Hello, World", "notification demo", MessageType.INFO);
}
}
This can be achieved with the SystemTray and TrayIcon classes. Also, if this is a new API for you, you might want to check the dedicated tutorial "How to Use the System Tray".
you can use Notifications with javafx easily with Notification class
java.lang.Object
org.controlsfx.control.Notifications
public static showNotification(String title,String text){
Notifications notificationTest=Notifications.create();
notificationTest.position(Pos.BASELINE_RIGHT);
notificationTest.title(title);
notificationTest.text(text);
notificationTest.show();//for error noti notificationTest.showError();
}
https://www.javadoc.io/static/org.controlsfx/controlsfx/8.40.16/org/controlsfx/control/Notifications.html

How to implement Full-Screen Exclusive Mode API

I have a big java program made in GUI using netbeans, in which I have many java files. I have used frame.setExtendedState(JFrame.MAXIMIZED_BOTH); but it doesn't work well for me. What I actually want is that the items get re-sized to full screen that's when I came across this API. I want to know how to implement this API into my program. The problem is that I am a newbie (I make most of the program using Netbeans GUI) and I don't know exactly where should I add the code to make it use this API
Is there a easy way to do it? Which does not require me to make the whole program again?
You should go through the Full Exclusive Mode tutorial. All it is is a matter of checking is full screen mode is supported. If it is, then get the screen device and setFullScreenWindow(...). If it's not supported, just use regular windowing.
See this simple example
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class FullWindow extends JFrame {
private boolean isFullScreen = false;
private GraphicsDevice device;
public FullWindow(GraphicsDevice device) {
this.device = device;
initFullScreen();
}
private void initFullScreen() {
isFullScreen = device.isFullScreenSupported();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setUndecorated(isFullScreen);
setResizable(!isFullScreen);
if (isFullScreen) {
// Full-screen mode
device.setFullScreenWindow(this);
validate();
} else {
// Windowed mode
this.setExtendedState(MAXIMIZED_BOTH);
this.setVisible(true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GraphicsEnvironment env = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsDevice device = env.getDefaultScreenDevice();
new FullWindow(device);
}
});
}
}

Capturing image from webcam in java?

How can I continuously capture images from a webcam?
I want to experiment with object recognition (by maybe using java media framework).
I was thinking of creating two threads
one thread:
Node 1: capture live image
Node 2: save image as "1.jpg"
Node 3: wait 5 seconds
Node 4: repeat...
other thread:
Node 1: wait until image is captured
Node 2: using the "1.jpg" get colors
from every pixle
Node 3: save data in arrays
Node 4: repeat...
This JavaCV implementation works fine.
Code:
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.IplImage;
import java.io.File;
import static org.bytedeco.opencv.global.opencv_core.cvFlip;
import static org.bytedeco.opencv.helper.opencv_imgcodecs.cvSaveImage;
public class Test implements Runnable {
final int INTERVAL = 100;///you may use interval
CanvasFrame canvas = new CanvasFrame("Web Cam");
public Test() {
canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
}
public void run() {
new File("images").mkdir();
FrameGrabber grabber = new OpenCVFrameGrabber(0); // 1 for next camera
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
IplImage img;
int i = 0;
try {
grabber.start();
while (true) {
Frame frame = grabber.grab();
img = converter.convert(frame);
//the grabbed frame will be flipped, re-flip to make it right
cvFlip(img, img, 1);// l-r = 90_degrees_steps_anti_clockwise
//save
cvSaveImage("images" + File.separator + (i++) + "-aa.jpg", img);
canvas.showImage(converter.convert(img));
Thread.sleep(INTERVAL);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Test gs = new Test();
Thread th = new Thread(gs);
th.start();
}
}
There is also post on configuration for JavaCV
You can modify the code and be able to save the images in regular interval and do rest of the processing you want.
Some time ago I've created generic Java library which can be used to take pictures with a PC webcam. The API is very simple, not overfeatured, can work standalone, but also supports additional webcam drivers like OpenIMAJ, JMF, FMJ, LTI-CIVIL, etc, and some IP cameras.
Link to the project is https://github.com/sarxos/webcam-capture
Example code (take picture and save in test.jpg):
Webcam webcam = Webcam.getDefault();
webcam.open();
BufferedImage image = webcam.getImage();
ImageIO.write(image, "JPG", new File("test.jpg"));
It is also available in Maven Central Repository or as a separate ZIP which includes all required dependencies and 3rd party JARs.
JMyron is very simple for use.
http://webcamxtra.sourceforge.net/
myron = new JMyron();
myron.start(imgw, imgh);
myron.update();
int[] img = myron.image();
Here is a similar question with some - yet unaccepted - answers. One of them mentions FMJ as a java alternative to JMF.
This kind of goes off of gt_ebuddy's answer using JavaCV, but my video output is at a much higher quality then his answer. I've also added some other random improvements (such as closing down the program when ESC and CTRL+C are pressed, and making sure to close down the resources the program uses properly).
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import com.googlecode.javacv.CanvasFrame;
import com.googlecode.javacv.OpenCVFrameGrabber;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
public class HighRes extends JComponent implements Runnable {
private static final long serialVersionUID = 1L;
private static CanvasFrame frame = new CanvasFrame("Web Cam");
private static boolean running = false;
private static int frameWidth = 800;
private static int frameHeight = 600;
private static OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
private static BufferedImage bufImg;
public HighRes()
{
// setup key bindings
ActionMap actionMap = frame.getRootPane().getActionMap();
InputMap inputMap = frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
for (Keys direction : Keys.values())
{
actionMap.put(direction.getText(), new KeyBinding(direction.getText()));
inputMap.put(direction.getKeyStroke(), direction.getText());
}
frame.getRootPane().setActionMap(actionMap);
frame.getRootPane().setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);
// setup window listener for close action
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
stop();
}
});
}
public static void main(String... args)
{
HighRes webcam = new HighRes();
webcam.start();
}
#Override
public void run()
{
try
{
grabber.setImageWidth(frameWidth);
grabber.setImageHeight(frameHeight);
grabber.start();
while (running)
{
final IplImage cvimg = grabber.grab();
if (cvimg != null)
{
// cvFlip(cvimg, cvimg, 1); // mirror
// show image on window
bufImg = cvimg.getBufferedImage();
frame.showImage(bufImg);
}
}
grabber.stop();
grabber.release();
frame.dispose();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void start()
{
new Thread(this).start();
running = true;
}
public void stop()
{
running = false;
}
private class KeyBinding extends AbstractAction {
private static final long serialVersionUID = 1L;
public KeyBinding(String text)
{
super(text);
putValue(ACTION_COMMAND_KEY, text);
}
#Override
public void actionPerformed(ActionEvent e)
{
String action = e.getActionCommand();
if (action.equals(Keys.ESCAPE.toString()) || action.equals(Keys.CTRLC.toString())) stop();
else System.out.println("Key Binding: " + action);
}
}
}
enum Keys
{
ESCAPE("Escape", KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)),
CTRLC("Control-C", KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK)),
UP("Up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)),
DOWN("Down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)),
LEFT("Left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)),
RIGHT("Right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));
private String text;
private KeyStroke keyStroke;
Keys(String text, KeyStroke keyStroke)
{
this.text = text;
this.keyStroke = keyStroke;
}
public String getText()
{
return text;
}
public KeyStroke getKeyStroke()
{
return keyStroke;
}
#Override
public String toString()
{
return text;
}
}
You can try Java Webcam SDK library also.
SDK demo applet is available at link.
I have used JMF on a videoconference application and it worked well on two laptops: one with integrated webcam and another with an old USB webcam. It requires JMF being installed and configured before-hand, but once you're done you can access the hardware via Java code fairly easily.
You can try Marvin Framework. It provides an interface to work with cameras. Moreover, it also provides a set of real-time video processing features, like object tracking and filtering.
Take a look!
Real-time Video Processing Demo:
http://www.youtube.com/watch?v=D5mBt0kRYvk
You can use the source below. Just save a frame using MarvinImageIO.saveImage() every 5 second.
Webcam video demo:
public class SimpleVideoTest extends JFrame implements Runnable{
private MarvinVideoInterface videoAdapter;
private MarvinImage image;
private MarvinImagePanel videoPanel;
public SimpleVideoTest(){
super("Simple Video Test");
videoAdapter = new MarvinJavaCVAdapter();
videoAdapter.connect(0);
videoPanel = new MarvinImagePanel();
add(videoPanel);
new Thread(this).start();
setSize(800,600);
setVisible(true);
}
#Override
public void run() {
while(true){
// Request a video frame and set into the VideoPanel
image = videoAdapter.getFrame();
videoPanel.setImage(image);
}
}
public static void main(String[] args) {
SimpleVideoTest t = new SimpleVideoTest();
t.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
For those who just want to take a single picture:
WebcamPicture.java
public class WebcamPicture {
public static void main(String[] args) {
try{
MarvinVideoInterface videoAdapter = new MarvinJavaCVAdapter();
videoAdapter.connect(0);
MarvinImage image = videoAdapter.getFrame();
MarvinImageIO.saveImage(image, "./res/webcam_picture.jpg");
} catch(MarvinVideoInterfaceException e){
e.printStackTrace();
}
}
}
I used Webcam Capture API. You can download it from here
webcam = Webcam.getDefault();
webcam.open();
if (webcam.isOpen()) { //if web cam open
BufferedImage image = webcam.getImage();
JLabel imageLbl = new JLabel();
imageLbl.setSize(640, 480); //show captured image
imageLbl.setIcon(new ImageIcon(image));
int showConfirmDialog = JOptionPane.showConfirmDialog(null, imageLbl, "Image Viewer", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, new ImageIcon(""));
if (showConfirmDialog == JOptionPane.YES_OPTION) {
JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle("Save Image");
chooser.setFileFilter(new FileNameExtensionFilter("IMAGES ONLY", "png", "jpeg", "jpg")); //this file extentions are shown
int showSaveDialog = chooser.showSaveDialog(this);
if (showSaveDialog == 0) { //if pressed 'Save' button
String filePath = chooser.getCurrentDirectory().toString().replace("\\", "/");
String fileName = chooser.getSelectedFile().getName(); //get user entered file name to save
ImageIO.write(image, "PNG", new File(filePath + "/" + fileName + ".png"));
}
}
}
http://grack.com/downloads/school/enel619.10/report/java_media_framework.html
Using the Player with Swing
The Player can be easily used in a Swing application as well. The following code creates a Swing-based TV capture program with the video output displayed in the entire window:
import javax.media.*;
import javax.swing.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import javax.swing.event.*;
public class JMFTest extends JFrame {
Player _player;
JMFTest() {
addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
_player.stop();
_player.deallocate();
_player.close();
System.exit( 0 );
}
});
setExtent( 0, 0, 320, 260 );
JPanel panel = (JPanel)getContentPane();
panel.setLayout( new BorderLayout() );
String mediaFile = "vfw://1";
try {
MediaLocator mlr = new MediaLocator( mediaFile );
_player = Manager.createRealizedPlayer( mlr );
if (_player.getVisualComponent() != null)
panel.add("Center", _player.getVisualComponent());
if (_player.getControlPanelComponent() != null)
panel.add("South", _player.getControlPanelComponent());
}
catch (Exception e) {
System.err.println( "Got exception " + e );
}
}
public static void main(String[] args) {
JMFTest jmfTest = new JMFTest();
jmfTest.show();
}
}
Java usually doesn't like accessing hardware, so you will need a driver program of some sort, as goldenmean said. I've done this on my laptop by finding a command line program that snaps a picture. Then it's the same as goldenmean explained; you run the command line program from your java program in the takepicture() routine, and the rest of your code runs the same.
Except for the part about reading pixel values into an array, you might be better served by saving the file to BMP, which is nearly that format already, then using the standard java image libraries on it.
Using a command line program adds a dependency to your program and makes it less portable, but so was the webcam, right?
I believe the web-cam application software which comes along with the web-cam, or you native windows webcam software can be run in a batch script(windows/dos script) after turning the web cam on(i.e. if it needs an external power supply). In the bacth script , u can add appropriate delay to capture after certain time period. And keep executing the capture command in loop.
I guess this should be possible
-AD
There's a pretty nice interface for this in processing, which is kind of a pidgin java designed for graphics. It gets used in some image recognition work, such as that link.
Depending on what you need out of it, you might be able to load the video library that's used there in java, or if you're just playing around with it you might be able to get by using processing itself.
FMJ can do this, as can the supporting library it uses, LTI-CIVIL. Both are on sourceforge.
Recommand using FMJ for multimedia relatived java app.
Try using JMyron How To Use Webcam Using Java. I think using JMyron is the easiest way to access a webcam using java. I tried to use it with a 64-bit processor, but it gave me an error. It worked just fine on a 32-bit processor, though.

Categories