silent execution bug with processing standalone program - processing

I have been trying to use processing (3.0.2) as a lib to display video. You can see the beginning of my main class below. I am using Maven to build a fat .jar that I run on the command line. The program runs, does not freeze, and can be closed, but no video... (screenshot below) The problem is that happens totally silently: no warning, no crash.
I am totally sure that the video file is found by the program, since removing it triggers a RuntimeException.
Edit: Ok, so the file is found, but not the frames. The program is stuck trying to find a nonzero frame.
Edit 2: It seems it is in fact a GStreamer problem. Apparently, Processing does not support the GStreamer 1.x lineage. Installing GStreamer 0.1x as explained here and here, unfortunately did not work for me.
Edit 3: Trying with a basic example (code below), I see that the Movie.read() method is never triggered, although the draw() method is. Since there still are no errors or warnings, I guess it's a library problem. Interestingly, this very same code works perfectly when executed as a .pde from the Processing IDE, so there must be a library there that I am lacking. Any ideas??
My dependencies:
core.jar
video.jar
jna.jar
gstreamer-java.jar
System: Ubuntu 14.04 LTS, Java HotSpot(TM) 64-Bit Server VM (java version "1.8.0_77"), Processing 3.0.2 with video library installed through the processing IDE.
import processing.core.PApplet;
import processing.video.*;
public class TestMovie extends PApplet{
Movie myMovie;
public static void main(String[] args){
PApplet.main(TestMovie.class.getName());
}
public void settings(){
size(720, 480, FX2D);
}
public void setup() {
//background(0);
try{
myMovie = new Movie(this, "red_45deg_284sec_500ml.mpg");
}catch(Exception e){
System.out.println(e.getMessage());
}
myMovie.loop();
}
public void draw() {
image(myMovie.get(), 0, 0);
System.out.println("I'm drawing!");
}
// Called every time a new frame is available to read
void movieEvent(Movie m) {
try{
m.read();
}catch(Exception e){
System.out.println(e.getMessage());
}
System.out.println("new frame!");
}
}

So, I finally got the movie playing, and it does not seem to be a library problem after all... For some mysterious reason, movieEvent() does not execute, most likely because no event is triggered. Using Movie.available() solved it as follows:
public class TestMovie extends PApplet{
Movie myMovie;
public static void main(String[] args){
PApplet.main(TestMovie.class.getName());
}
public void settings(){
size(720, 480, FX2D);
}
public void setup() {
//background(0);
try{
myMovie = new Movie(this, "red_45deg_284sec_500ml.mpg");
}catch(Exception e){
System.out.println(e.getMessage());
}
myMovie.loop();
}
public void draw() {
if (myMovie.available()) {
myMovie.read();
}
image(myMovie, 0, 0);
}
}

Related

JavaFX image not changing when function is called by Platform.runLater

I have a function to change an image and its opacity in a JavaFX GUI:
private static Image image = null;
private static ImageView imageView = new ImageView();
// some code to add image in GUI
public static void changeImage() {
imageView.setOpacity(0.5);
imageView.setImage(null);
}
When I call this function within the JavaFX instance, the image disappears or is changing if I use an image instead of null for setImage(). I tried calling the function by pressing a button.
In this case all works as I expected.
When I call this function from another class, the actual image will change its opacity, but the image itself is never changing. I call the function the following way:
public static void changeImg() {
Platform.runLater(() -> FX_Gui.changeImage());
}
Changing labels, progess bars... all works, but I did not manage to change an image.
There's a lot of aspects to this question that don't make sense.
Generally speaking, the GUI in JavaFX is intended to be self-contained and non-linear in it's execution. Programming an outside method to assume some state of the GUI, and then to directly manipulate the GUI based on that assumption is not the correct approach. So any attempt to know the state of the GUI by kludging in a Thread.sleep() call is inherently incorrect.
The new JFXPanel() call is not needed, as Application.launch() will initialize JavaFX. Presumably, this was added before the sleep(500) was put in, since calling changeImg() would fail if run immediately after the Thread.start() command, since the launch() wouldn't have time to even start yet.
As has been noted, having some kind of startup image that's replaced once the screen completes initialization should be done from within the FX_Min.start(Stage) method, although it's highly unlikely that you'd even see the first image.
The question seems to be aimed at designing a kind of application where the GUI is just some small part of it and the main application is going to go on to do lengthy processing and then trigger the GUI to something in response to the results of that processing. Or perhaps the main application is monitoring an external API and feeding updates to GUI periodically. In most cases, however, the GUI is usually initialized so that it can take control of the operation, launching background threads to do the lengthy processing and using JavaFX tools to handle the triggering of GUI updates and intake of results.
In the instance that the design really needs to have something other than the GUI be the central control, then use of Application does not seem appropriate. It is, after all, designed to control the Application, and monitors the status of the GUI once it's been launched to shut everything down when the GUI is closed. This is why the OP had to put the Application.launch() call in a separate thread - launch() doesn't return until the GUI shuts down.
If the application outside of the GUI is going to control everything then it's best to manually start JavaFX with Platform.startup(), and handle all the monitoring manually. The following code doesn't do any monitoring, but it does start up the GUI and change the image without any issues:
public class Control_Min {
public static void main(String[] args) {
Platform.startup(() -> new Fx_Min().start(new Stage()));
Platform.runLater(() -> Fx_Min.changeImage());
}
}
Note that no changes are required to the OP's code in Fx_Min. However, there's no reason for Fx_Min to extend Application any more, and the code from its start() method can be placed anywhere.
It should be further noted that, although this works, it's really way outside the norm for JavaFX applications. It's possible that the OP's situation really does require this kind of architecture, but that would place it into a very small minority of applications. Designing the application around Application.launch() and initiating lengthy processing in background threads through the JavaFX tools provided is almost always a better approach.
OK, so given new information from the OP it's clear that this should be based on Application and that the GUI should launch some kind of socket listener that would presumably block waiting for input.
Anything that blocks can't run on the FXAT, and there needs to be a way to allow the socket listener to communicate back to the GUI when it receives data. Ideally, the socket listener should be JavaFX unaware, and just plain Java.
IMO, the best way to do this is to provide a Consumer to accept information from the socket listener, and to pass it to the socket listener in it's constructor. That way, the GUI knows nothing about the nature of the socket listener except that it has a dependency on requiring a message consumer. Similarly, the socket listener has no knowledge about what invoked it, just that it has given it a message consumer.
This limits your coupling, and you are free to write your GUI without worrying about any of the inner workings of the socket listener, and visa versa.
So here's the GUI, cleaned up and simplified a bit so that the socket listener stuff is easier to follow. Basically, the GUI is just going to throw the message from the socket listener into a Text already on the screen. The message consumer handles the Platform.runLater() so that the socket listener isn't even aware of it:
public class Fx_Min extends Application {
#Override
public void start(Stage primaryStage) {
ImageView imageView = new ImageView(new Image("/images/ArrowUp.png"));
Text text = new Text("");
primaryStage.setScene(new Scene(new VBox(10, imageView, text), 800, 600));
primaryStage.setResizable(true);
primaryStage.show();
imageView.setImage(new Image("/images/Flag.png"));
new SocketListener(socketMessage -> Platform.runLater(() -> text.setText(socketMessage))).startListening();
}
public static void main(String[] args) {
launch(args);
}
}
Here's the socket listener. Clearly, this isn't going to listen on a socket, but it loops around a sleep() to simulate action happening on the Pi. The message format here is String, just to keep everything simple, but obviously this is the worse possible choice for an actual implementation of this. Build a special message class:
public class SocketListener {
private Consumer<String> messageConsumer;
public SocketListener(Consumer<String> messageConsumer) {
this.messageConsumer = messageConsumer;
}
public void startListening() {
Thread listenerThread = new Thread(() -> listenForIRCommand());
listenerThread.setDaemon(true);
listenerThread.start();
}
private void listenForIRCommand() {
for (int x = 0; x < 100; x++) {
try {
Thread.sleep(5000);
messageConsumer.accept("Station " + x);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
It should be really clear that since the call to listenForIRCommand() is executed from inside a background thread, that it's completely freed from any JavaFX contstraints. Anything that generally possible in Java can be done from there without worrying about it's impact on the GUI.
In the meantime I found out that the reason for not changing the image is that I run changeImage() before the initialization of the GUI is completed. If I wait about 500 mS before I sent the changeImage() command all works fine.
Below is the minimal code that demonstrates the issue I had:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
public class Control_Min {
public static void changeImg() {
Platform.runLater(() -> Fx_Min.changeImage());
}
public static void main(String[] args) {
new Thread() {
public void run() {
Application.launch(Fx_Min.class);
}
}.start();
// JFXPanel will initialize the JavaFX toolkit.
new JFXPanel();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
changeImg();
}
}
And the Gui itself:
public class Fx_Min extends Application {
private static Stage stage;
private static GridPane rootPane;
private static Scene scene;
private static Image image = null;
private static ImageView imageView = new ImageView();
#Override
public void start(Stage primaryStage) {
stage = primaryStage;
rootPane = new GridPane();
scene = new Scene(rootPane,800,600);
try {
image = new Image(new FileInputStream("C:\\Users\\Peter\\eclipse-workspace\\FX_Test\\src\\application\\Image1.jpg"));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
imageView.setImage(image);
rootPane.add(imageView, 1, 0);
stage.setScene(scene);
stage.setResizable(true);
stage.show();
System.out.println("Gui is ready");
}
public static void changeImage() {
try {
image = new Image(new FileInputStream("C:\\Users\\Peter\\eclipse-workspace\\FX_Test\\src\\application\\Image2.jpg"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
imageView.setImage(image);
System.out.println("Image Changed");
}
public static void main(String[] args) {
launch(args);
}
}
This code works fine.
In the console I get:
Gui is ready
Image Changed
When I remove the Thread.sleep(500) the image will not change.
In the console I get:
Image Change
Gui is ready
My conclusion is that I have send the runlater method before the FX runtime has been initialized.
(Have not fixed the static issue yet as this was not the issue. I will do in my original program later.)
My task is the following:
I program a GUI for my internet radio player on my PC.
The GUI controls the radio and polls what is playing.
I want to control the radio by an IR remote control too.
I have already a Raspberry Pi that communicates with the remote.
Therefore, my plan is to run a server socket on the PC, that receives the commands from the Raspberry Pi.
The server will run in its own thread. I want to use the runLater command to update the GUI.
Is there a better way to update the GUI from the server?
Goal is that the GUI will update immediately when I press a button on the remote.
With my latest learnings about JavaFX I will start the application now directly in the FX class and get the server thread started from the FX class

SWT Dialog does not display correctly

When opening a new dialog, while its loading, you click couple of times on parent shell, apparently the new dialog does not display correctly.
Please see the example below:
Examples
https://i.stack.imgur.com/ZovxE.png (eclipse IDE example)
https://i.stack.imgur.com/5zVar.png
https://i.stack.imgur.com/u86b9.png
https://i.stack.imgur.com/FGaAr.png
Initially I encountered the problem in december 2014, and back then also reported by vaious in house devlopers which were using different development systems and then same problem has been reported by our several customers.
This behavior can be reproduced using following environment:
Windows Version: 7 Pro 64 Bit - 6.1.7601
Java Version: RE 1.8.0_121_b13
SWT Versions
3.8.2
4.6.2
4.7M6
I20170319-2000
I could only reproduce the problem on Windows 7 with the windows basic theme/design/style (not with classic or aero).
On windows 10 its not reproducible.
reproduce
code to reproduce
package test;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class Main {
public static void main(String[] args) {
Display display = new Display();
final Shell shell = createShell(display);
createButton(shell);
shell.open();
eventLoop(display, shell);
display.dispose();
}
private static Shell createShell(Display display) {
final Shell shell = new Shell(display);
shell.setLayout(new RowLayout());
shell.setSize(500, 200);
return shell;
}
private static void createButton(final Shell shell) {
final Button openDialog = new Button(shell, SWT.PUSH);
openDialog.setText("Click here to open Dialog ...");
openDialog.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
TestDialog inputDialog = new TestDialog(shell);
inputDialog.open();
}
});
}
private static void eventLoop(Display display, final Shell shell) {
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
class TestDialog extends Dialog {
public TestDialog(Shell parent) {
super(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.MIN | SWT.MAX | SWT.RESIZE);
setText("Dialog");
}
public void open() {
Shell shell = new Shell(getParent(), getStyle());
shell.setText(getText());
createContents(shell);
shell.pack();
initializeBounds(shell);
shell.open();
eventLoop(shell);
}
private void createContents(final Shell shell) {
shell.setLayout(new GridLayout(2, true));
Label label = new Label(shell, SWT.NONE);
label.setText("Some Label text ...");
final Text text = new Text(shell, SWT.BORDER);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
text.setLayoutData(data);
createCloseButton(shell);
/* time for the user to create the misbehavior */
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void createCloseButton(final Shell shell) {
Button closeButton = new Button(shell, SWT.PUSH);
closeButton.setText("Close");
GridData data = new GridData(GridData.FILL_HORIZONTAL);
closeButton.setLayoutData(data);
closeButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
shell.close();
}
});
shell.setDefaultButton(closeButton);
}
private void initializeBounds(Shell shell) {
Rectangle bounds = shell.getBounds();
Rectangle parentBounds = getParent().getBounds();
bounds.x = parentBounds.x;
bounds.y = parentBounds.y;
shell.setBounds(bounds);
}
private void eventLoop(Shell shell) {
Display display = getParent().getDisplay();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
steps to reproduce
Start the application
it should look like: https://i.stack.imgur.com/dMJ9e.png
Click on the button.
Keep continuously clicking on right bottom corner of the parent shell (avoid hitting the new opening dialog), till mouse cursor changes to wait icon and parent shell changes its color.
it should look as following: https://i.stack.imgur.com/c1Ikp.png
Wait until the new dialog appears.
it looks likes as following: https://i.stack.imgur.com/kTDgQ.png (incorrectly displayed)
instead: https://i.stack.imgur.com/cHVjn.png (correctly displayed)
steps to reproduce done in video
https://youtu.be/7ukhloCPf0k
When you mouse hover some of the UI elements (the originally not correctly drawn), you can notice some of them to be get painted (e.g. table rows).
https://i.stack.imgur.com/kkMKn.png (before opening the dialog)
https://i.stack.imgur.com/ZXIKc.png (after opening the dialog)
https://i.stack.imgur.com/25M7S.jpg (after mouse over)
Even calling Shell.update() or Shell.redraw() after the Dialog opened does not fix it.
In Windows Performance Options -> Visual Effects -> disable "Use visual styles on windows and buttons" is the only option I found which provides a workaround,
which seems to be the same as changing the design/theme/style to classic.
https://www.sevenforums.com/tutorials/1908-visual-effects-settings-change.html (How to Change Windows Visual Effects)
In the end, I have following questions:
Is it a SWT or Windows problem?
Is there any related topic in bug entries for Windows or in Eclipse Bugzilla?
Is there someone else who experienced the same problem? please share the experience.
Is there any settings in SWT or Windows which could affect its look n feel and fix the problem?
In the end, I have following questions: Is it a SWT or Windows problem?
Neither. As others have mentioned, you certainly should not tie up the UI thread with any long-running task. That work belongs in a background thread.
In regards to using a background thread, there are several ways you could go about this depending on how you want your Dialog to behave.
One option would be to kick off the background thread and then open the dialog when the task is done. I personally don't care for this because while the task is running, a user may think that nothing is happening.
Another option would be to open the dialog but display a "Loading" message, or something to that effect to give meaningful feedback and let a user know that the application isn't frozen (like how it looks/responds in your example).
The strategy would be to:
Create the dialog
Start the long task on a background thread and register a callback
Open the dialog with a "Loading" message
When the task is complete, the dialog will be updated from the callback
If you search around a bit on using Executors, you should find some far better examples and detail on how to use them.
Here's a brief example to illustrate what that might look like:
(Note: There are definitely a few issues with this code, but for the sake of brevity and illustrating the point I opted for a slightly naive solution. Also there are Java 8-esque ways that would be a bit shorter, but again, this illustrates the idea behind using a background thread; the same concepts apply)
Given a Callable (or Runnable if you don't need a return value),
public class LongTask implements Callable<String> {
#Override
public String call() throws Exception {
Thread.sleep(15000);
return "Hello, World!";
}
}
You can use the Executors class to create a thread pool, and then an ExecutorService to submit the Callable for execution. Then, using Futures.addCallback(), you can register a callback which will execute one of two methods depending on whether the task was successful or failed.
final ExecutorService threadPool = Executors.newFixedThreadPool(1);
final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(threadPool);
final ListenableFuture<String> future = executorService.submit(new LongTask());
Futures.addCallback(future, new FutureCallback(){...});
In this case I used the Google Guava implementation ListeningExecutorService which makes things a bit cleaner and simpler, in my opinion. But again, you may not even need this if you opt for a more "Java 8" approach.
As for the callback, when the task is successful, we update the Dialog with the results. If it fails, we can update it with something to indicate failure:
public static class DialogCallback implements FutureCallback<String> {
private final MyDialog dialog;
public DialogCallback(final MyDialog dialog) {
this.dialog = dialog;
}
#Override
public void onSuccess(final String result) {
dialog.getShell().getDisplay().asyncExec(new Runnable() {
#SuppressWarnings("synthetic-access")
#Override
public void run() {
dialog.setStatus(result);
}
});
}
#Override
public void onFailure(final Throwable t) {
dialog.getShell().getDisplay().asyncExec(new Runnable() {
#SuppressWarnings("synthetic-access")
#Override
public void run() {
dialog.setStatus("Failure");
}
});
}
}
In this case I opted for the Callable to return a String, thus the FutureCallback should be parameterized with String. You may want to use some other class that you created, which will work just as well.
Notice that we use the Display.asyncExec() method to ensure that the code which updates the UI runs on the UI thread, because the callback may execute on the background thread.
Like I said, there are still a few issues here, including what happens when you click the cancel button before the task completes, etc. But hopefully this helps illustrate an approach for handling long-running background tasks without blocking the UI thread.
Full example code:
public class DialogTaskExample {
private final Display display;
private final Shell shell;
private final ListeningExecutorService executorService;
public DialogTaskExample() {
display = new Display();
shell = new Shell(display);
shell.setLayout(new GridLayout());
executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
final Button button = new Button(shell, SWT.PUSH);
button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
button.setText("Start");
button.addSelectionListener(new SelectionAdapter() {
#SuppressWarnings("synthetic-access")
#Override
public void widgetSelected(final SelectionEvent e) {
final MyDialog dialog = new MyDialog(shell);
dialog.setBlockOnOpen(false);
dialog.open();
dialog.setStatus("Doing stuff...");
final ListenableFuture<String> future = executorService.submit(new LongTask());
Futures.addCallback(future, new DialogCallback(dialog));
}
});
}
public void run() {
shell.setSize(200, 200);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
executorService.shutdown();
display.dispose();
}
public static void main(final String... args) {
new DialogTaskExample().run();
}
public static class DialogCallback implements FutureCallback<String> {
private final MyDialog dialog;
public DialogCallback(final MyDialog dialog) {
this.dialog = dialog;
}
#Override
public void onSuccess(final String result) {
dialog.getShell().getDisplay().asyncExec(new Runnable() {
#SuppressWarnings("synthetic-access")
#Override
public void run() {
dialog.setStatus(result);
}
});
}
#Override
public void onFailure(final Throwable t) {
dialog.getShell().getDisplay().asyncExec(new Runnable() {
#SuppressWarnings("synthetic-access")
#Override
public void run() {
dialog.setStatus("Failure");
}
});
}
}
public static class LongTask implements Callable<String> {
/**
* {#inheritDoc}
*/
#Override
public String call() throws Exception {
Thread.sleep(15000);
return "Hello, World!";
}
}
public static class MyDialog extends Dialog {
private Composite baseComposite;
private Label label;
/**
* #param parentShell
*/
protected MyDialog(final Shell parentShell) {
super(parentShell);
}
/**
* {#inheritDoc}
*/
#Override
protected Control createDialogArea(final Composite parent) {
baseComposite = (Composite) super.createDialogArea(parent);
label = new Label(baseComposite, SWT.NONE);
return baseComposite;
}
public void setStatus(final String text) {
label.setText(text);
baseComposite.layout();
}
}
}
The code seems to be straight forward, only that you are making the main Thread sleep for 15secs hence the delay. If not required remove the sleep or reduce the time for sleep to 5secs or so.

VLCJ playmedia() stops play after about 1 second of playback

I've used the code from Caprica's old Tutorial2B.java to play the whole file:
public class Tutorial2B {
private final EmbeddedMediaPlayerComponent mediaPlayerComponent;
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Tutorial2B(args);
}
});
}
private Tutorial2B(String[] args) {
JFrame frame = new JFrame("vlcj Tutorial");
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
frame.setContentPane(mediaPlayerComponent);
frame.setLocation(100, 100);
frame.setSize(1050, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
mediaPlayerComponent.getMediaPlayer().playMedia("/home/me/sample.MP3");
}
}
However, I cannot get the following code to play my audio file for more than a split second:
public class Tutorial2B {
private final AudioMediaPlayerComponent mediaPlayerComponent;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Tutorial2B();
}
});
}
private Tutorial2B() {
mediaPlayerComponent = new AudioMediaPlayerComponent();
MediaPlayer mediaPlayer = mediaPlayerComponent.getMediaPlayer();
mediaPlayer.playMedia("/home/me/sample.mp3")
}
Any clues as to why this isn't working?
current code Dec 21st:
public class Tutorial2B {
static AudioMediaPlayerComponent mediaPlayerComponent = null;
public static void main(String[] args) {
mediaPlayerComponent = new AudioMediaPlayerComponent();
mediaPlayerComponent.getMediaPlayer().playMedia("/home/sss.mp3");
}
}
Removed the call SwingUtilities. Plays fine now.
The reason the tutorial application works and your modified audio player application doesn't is because of garbage collection.
In both examples, when you do SwingUtilities.invokeLater() and the run() method terminates, your entire application goes out of scope and becomes eligible for garbage collection. You are not keeping a reference to the application class.
In the case of the example application this OK because creating a Swing UI (the JFrame) is enough to prevent the application from being garbage collected.
In the case of your modified application, there is no Swing UI created and consequently nothing that will prevent the application being garbage collected. In fact, in this case your application will simply exit.
I am actually surprised you say removing the use of SwingUtilities fixes your problem as there is still nothing I can see that will keep your application from being garbage collected. When I see an application like this, I have seen on Linux it will exit just about immediately, and on Windows it will exit some unpredictable time later after a garbage collection has been executed.
The more robust solution is to use something like join() on the current thread to prevent the application from exiting, or somehow otherwise keep a reference to your application class pinned, and then for example to wait for a media player event of "finished" or "error" before terminating your application.
In "real" applications this sort of thing is generally not a concern since there are other things keeping your application from being garbage collected (like a UI, or some other application framework).

Monitor clipboard in Mac OS

I need to monitor clipboard events in my mac os app. I found a sample for a clipboard viewer and another question in stackoverflow asking for the same thing, but none of them has a solution on how to monitor the clipboard events.
That is, immediately after the user hits command + c, I get an event notifying. I know that the functionality exists, as there is an app that uses this functionality
Ideas?
I have written a clipboard listener [it will print every new text based information that entered the clipboard] in native Java see the following code:
import java.awt.Toolkit;
import java.awt.datatransfer.*;
import java.io.IOException;
public class ClipboardListener extends Thread implements ClipboardOwner {
Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
public void run(){
Transferable selection = systemClipboard.getContents(this);
gainOwnership(selection);
while (true) {}
}
public void gainOwnership(Transferable t){
try {this.sleep(100);}
catch (InterruptedException e) {}
systemClipboard.setContents(t, this);
}
public void lostOwnership(Clipboard clipboard, Transferable contents) {
try {System.out.println((String) clipboard.getData(DataFlavor.stringFlavor));}
catch (UnsupportedFlavorException e) {}
catch (IOException e) {}
gainOwnership(contents);
}
}
public class myApp {
public static void main(String[] args){
ClipboardListener listener = new ClipboardListener();
listener.start();}
}
It works, but the application will need focus to get the event from the clipboard. [I'm not Mac OS X developer so I don't how to fix this, actually I have posted a question about it...]
Have you looked at this. You could watch for command + c (and x) and manually get the clipboard.

JApplet/JPanel not receiving KeyListener events!

I cannot get my JPanel within my JApplet to receive keyboard events. I CANNOT FATHOM why!
Note that...
Clicking the panel (with mouse) before typing makes no difference. This is by far the most common advice I see given on the Net.
I have tried using the 'low-level' java.awt.KeyEventDispatcher interface. That makes no different either!
However, if I use Applet instead of JApplet, then the Applet DOES receive keyboard events. But even here, the moment I add a Panel to this Applet (the Panel is really where all my app/painting logic is), I once again stop receiving kb events (in my Panel)!
Now, I cannot simply use Applet (instead of JApplet) because, among other things, its onPaint gets a Graphics (instead of a Graphics2D object). So, #3 is NOT a solution for me.
Things work like a charm in AppletViewer that comes with JDK.
I desperately need someone's help here. Spent last 2-3 days trying all kinds of permutations I don't even recall now.
My platform details:
Firefox 3.5.3
Fedora 11 on x86 (with latest updates/patches)
Java Plugin: tried both of these, made no difference.
3.1 IcedTea Java Web Browser Plugin 1.6 (fedora-29.b16.fc11-i386)
3.2 jdk1.6.0_16/jre/plugin/i386/ns7/libjavaplugin_oji.so
Used the above jdk1.6.0_16 to compile my applet source.
Here's my code. Will greatly appreciate to hear from my fellow programmers... as I'm completely stuck!
Thanks,
/SD
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
class MyAppletKeyListener implements KeyListener, MouseListener {
public void keyPressed(KeyEvent e) {
System.out.println("panel:keyPressed" + e.getKeyChar());
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
System.out.println("panel:keyTyped" + e.getKeyChar());
}
public void mouseClicked(MouseEvent e) {
System.out.println("panel:mouseClicked");
}
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mousePressed(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
}
public class TestApplet extends JApplet implements MouseListener {
public void init() {
System.out.println("applet:init");
MyAppletKeyListener listener = new MyAppletKeyListener();
// Panel related
// Note: I'd like this red panel to handle
// all my keyboard and mouse events.
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
panel.add(new JButton("test"));
panel.add(new JButton("test2"));
panel.setFocusable(true);
panel.requestFocus();
panel.setBackground(new Color(200, 0, 0));
panel.addKeyListener(listener);
panel.addMouseListener(listener);
// applet related
// Note: Added this only for debugging. I do NOT want
// to handle my mouse/kb events in the applet.
addMouseListener(this);
getContentPane().setLayout(new FlowLayout());
getContentPane().add(panel);
}
public void mouseClicked(MouseEvent e) {
System.out.println("applet:mouseClicked");
}
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mousePressed(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
}
The HTML:
<html>
<head>
</head>
<body>
<applet id="myApplet" code="TestApplet.class"
width="425"
height="150" >
</applet>
</body>
</html>
I found this on the net, and it solves the issue for me:
As for the fact that KeyListener does
not work for JApplet as it does for
Applet you should use the
KeyEventDispatcher interface.
public class AppletMain extends JApplet implements
java.awt.KeyEventDispatcher
Furthermore you have to set the
KeyboardFocusManager to the Panel
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
Afterwards override the
dispatchKeyEvent function of the
interface:
#Override
public boolean dispatchKeyEvent(KeyEvent e);
This allows you to catch the KeyEvents
as it is done with KeyListener.
I investigated the problem connected to my current project and explored some problems with focusability of JApplet class.
It is because why setFocusable(true);decided the problem.
You also may eventually need to add focus-capture call such as requestFocusInWindow(); to make it work propertly.
I had this problem with the sun-java-6 packages and the openjdk packages in both Ubuntu 9.04 and 10.10 with firefox version 3.6.11 and 3.6.14. I've discovered two workarounds: use Applet rather than JApplet, or implement a MouseListener which calls "requestFocus()" in the mousePressed(..) function.

Resources