I'm making a simple tool with Processing 3.
I want my sketch to not close when the "X" button is pressed. I found a question here on StackOverflow, but when I try doing that, I have this error: ClassCastException: processing.core.PApplet$8 cannot be cast to javax.swing.JFrame
I've tried adding more libraries, but now the error says is non a library error.
Here a piece of code:
import javax.swing.JFrame;
void setup() {
size(640, 360);
((JFrame)frame).setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
}
void draw() {
textSize(50);
text("some text", width/2, height/2)
}
void exit() {
println("Not exiting");
}
When I try to run the sketch I have the error ClassCastException: processing.core.PApplet$8 cannot be cast to javax.swing.JFrame
The answer you linked to is for Processing 2, but you're using Processing 3.
Your error says it all: frame cannot be cast to JFrame, which is what you're trying to do here:
((JFrame)frame).setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
To understand the source of this error, you can look at the source for the PApplet class here.
Do a search for "frame" in that file to see that the frame variable is now a java.awt.Frame instead of a javax.swing.JFrame. Processing also overrides some of the functions in the java.awt.Frame to provide Processings-specific behavior and warning messages.
You could start researching how to prevent a java.awt.Frame from closing, but I'd also consider rethinking whether you want to do this at all. Preventing windows from closing is a bit of an anti-pattern, so you should think carefully about whether you really need to do this. You could also consider other options, such as using a full-screen window rather than an uncloseable one.
Related
I'm working on a Java project in Eclipse that has a class extending PApplet to run a Processing sketch.
First I have a JFrame login screen, and after the user logs in there, I call
PApplet.main("Game"); //"Game" is the class that extends PApplet
to start the sketch.
Now when the game ends I want to close the sketch window, but not the original JFrame window.
Normally I would call
exit();
in Processing but this closes the entire application (ie all windows).
I have also tried
dispose();
but this does nothing.
I guess I'm looking for something like
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
but for PApplet.
First, you have to get the instance holding your sketch. That means using the runSketch() function instead of calling main() directly:
Game game = new Game();
String[] args = {};
PApplet.runSketch(args, game);
Now that you have a reference to your sketch instance, you can use it to get to the internal window. How you do this depends on which renderer you're using, but you can figure it out using a mix of the Processing JavaDoc and the Processing source code.
Here's an untested example using the default renderer:
PSurface surface = game.getSurface();
SmoothCanvas smoothCanvas = (SmoothCanvas)surface.getNative();
JFrame frame = (JFrame) smoothCanvas.getFrame();
Now that you have the parent window, you can do whatever you want with it, including:
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setVisible(false);
Like I said I haven't tested this code, and this is going to depend on exactly which renderer you're using, but this process of using the source code and JavaDoc to figure out what's going on under the hood to get to the underlying window is what you have to do.
I use NetBeans for Java programming, and whenever I try to make an Applet, it doesn't work. The code is completely correct and I did not make any mistakes on it. When I hit "Run" a message appears in the output box that says, "BUILD SUCCESSFUL (total time: 0 seconds)" There are no error messages and no errors in the code, the Applet doesn't appear. The code is:
import java.applet.*;
import java.awt.*;
public class myProject extends Applet
{
public void init()
{
}
public void paint(Graphics g)
{
setSize(500,500);
}
public static void main(String[] args)
{
}
}
Get rid of the main method. If you're running the code as an applet, main will just confuse you and the IDE.
Make sure that you're telling NetBeans to run it as an applet, not as an application. Again, removing main should help you with this, since without main it can't run it as an app.
Consider not creating applets since they're considered somewhat dead technology.
Don't have setSize(...) within a paint method. Ever. GUI painting methods, such as paint(...) for AWT components and paintComponent(...) for Swing components derived from JComponent, should just do painting and nothing else.
Check out the Java Swing tutorials which can be found here: Swing Info
I am having trouble getting message boxes and to a degree dialog boxes to show/function properly in Mac (v10.9.5).
I just updated the JRE and JDK to the latest version (8u31). A "java -version" from a terminal window shows that I am indeed using 8u31. (I was previously using 8u20, which exhibited the same behavior.)
The code below works perfectly in Windows and a couple of different versions of Linux that I tested, no issues. I just have issues on a Mac. I streamlined my code, which is SWT based, but this example uses Swing, to the following:
package myTest;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class EntryCode
{
public static EntryCode oEntryCode;
public EntryCode()
{
// TODO Auto-generated constructor stub
}
public static void main(String[] args)
{
oEntryCode = new EntryCode();
oEntryCode.open();
}
public void open()
{
JPanel panel = new JPanel();
panel.setMinimumSize(new Dimension(200,200));
JFrame frame = new JFrame("JOptionPane showMessageDialog component example");
System.out.println("open(): entry - With frame");
JOptionPane.showConfirmDialog(frame, "Wow, works on the Mac!", "Inside open()", JOptionPane.YES_NO_OPTION);
System.out.println("Point 1");
System.exit(0);
}
}
I see the first system out line, and the code hangs on the message box request. In the real code, I simply use a null as the first argument. The original version of this test code used a null too, just I was experimenting with specifying a component. I thought that might be the problem. It is not.
When displaying SWT dialog boxes, there is a tendency that clicking on a button will hang the interface. The hang is somewhere between the button being depressed and the event handler firing. The event handler never fires.
I did not include a dialog box here. I figure that since my confirmation/message box exhibits the same problem that solve one, get the other for free.
I did a search on Google for displaying java applications on a Mac, but nothing turned up.
I would think that updating the JRE/JDK to the latest version would solve any OS related issues.
I compile the code to a jar and use the following to run from a terminal window. I to press Ctrl+C to quite the hung app.
java -XstartOnFirstThread -jar myTest.jar
Thoughts?
UPDATE:
I deleted the original update but am leaving the original question, now that I understand the problem better.
The real problem is how to initiate a proper Mac OSX Cocoa restriction friendly SWT application, which uses dialog and message boxes. (To the best of my knowledge, the only way to display message boxes is to use JOptionPane.show*, which is a Swing thing, thereby sort of mixing Swing and SWT.
It is interesting to note that the problem always relates to buttons, be it on a dialog box (a purely SWT implementation) or message boxes. In the former, the issue is a hang calling the event handler and the latter displaying a message box (null first argument, as no Swing frame exists in a SWT application).
The problem may be that you are not starting the GUI in the EDT. Try this:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
oEntryCode = new EntryCode();
oEntryCode.open();
}
});
}
More info: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
Another issue is using -XstartOnFirstThread with Swing. Swing does the equivalent of what -XstartOnFirstThread is doing, but in its own way. You should not use -XstartOnFirstThread with Swing, just as it's not a good idea to mix SWT and Swing.
If you add SwingUtilities.invokeLater() and remove -XstartOnFirstThread, your example should run normally.
Not quite sure if this might be the error since I can't test it on my Mac at the moment. But you never setting visibility of the JFrame to true. When you pass the frame as a parameter to the JOptionPane the pane tries to show the pane in the frame.
So try :
public void open()
{
JFrame frame = new JFrame("JOptionPane showMessageDialog component example");
System.out.println("open(): entry - With frame");
frame.setSize(300,300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
JOptionPane.showConfirmDialog(frame, "Wow, works on the Mac!", "Inside open()", JOptionPane.YES_NO_OPTION);
System.out.println("Point 1");
System.exit(0);
}
Also why do you create the JPanel the panel is never used as far as I can see ?
Since the frame is not visible this could cause problems. Just a guess...
This would also explain why it looks like your application is "freezing". Its because it is waiting for you to make the selection in your JOptionPane but you can't make that selection because you can't see the JOptionPane.
I know you wrote you also tried with passing null as argument but I could think this could also cause problems when there is no other JFrame shown. As i said just a guess. Just try it out and come back here to provide further information.
EDIT
Just tested and looks like your code is fine. Your error has to lie in your mac or java setup.
EDIT 2
I think I found your answer. Looks like the startOnFirstThread is the problem here. I just tested via javac and java on command line. Have a look at this:
Swing stops working, because -XstartOnFirstThread implies that that
someone else (very likely the SWT) is going to come around, and start
pumping the event loop on thread 0 with CFRunLoop or the like
This could explain why your JOptionPane struggles to show up. (Taken from: here
Also a bit older but describes your problem:
The AWT problems generally come down to which thread the jvm was started on. When using the java launcher (as pde does) on Mac, java by default starts on the second thread (which is what AWT wants) unless you specify -XstartOnFirstThread (which is what SWT wants).
(https://bugs.eclipse.org/bugs/show_bug.cgi?id=212617)
I'll start by saying that I'm a bit new to java, so if it's a stupid mistake, that's the reason.
I was messing with applets in java, and I've run into a problem when setting the size of the window, and using JOptionPane, whether it's just showing a message, or getting input through it, it displays three or more panes, rather than simply one. I'm on Ubuntu 12.04(x64), and here is my test code that still encounters the problem:
import javax.swing.JOptionPane;
import java.awt.Graphics;
import java.applet.Applet;
public class Main extends Applet{
public void paint(Graphics g)
{
//setup screen size
setSize((int)500,(int)500);
//print test message
JOptionPane.showMessageDialog(null, "There Should Be One Of Me!");
}
}
That's expected: there are as many option panes as number of calls to the paint method :-) the latter is not controllable by application code, neither in AWT nor in Swing.
As a general rule, never-ever change any component state in methods called during the paint cycle
remove setSize(.. and JOptionPane.sh... from public void paint(Graphics g)
for Applet I miss there method init()
(J)Applet tutorial shows a few examples
maybe better could be to use Swing JFrame instead of (J)Applet
Greetings,
I'm trying to get a JFrame drawing in a non screen device. The JFrame constructor has a
JFrame(GraphicsConfiguration)
to seemingly allow this:
My First attempt was to create my own GraphicsConfiguration, who's GraphicsDevice reported GraphicsDevice.TYPE_IMAGE_BUFFER when getType() was called.
However JFrame.init specifically looks for the type and throws an exception if the type isn't TYPE_RASTER_SCREEN:
if (graphicsConfig.getDevice().getType() !=
GraphicsDevice.TYPE_RASTER_SCREEN) {
throw new IllegalArgumentException("not a screen device");
}
Next i tried to make the GraphicsDevice i returned report GraphicsDevice.TYPE_RASTER_SCREEN. This allowed the JFrame to be initialized correctly, but when it went to display it, I got
Exception in thread "main" java.lang.ClassCastException: TestGraphicsConfiguration cannot be cast to sun.awt.X11GraphicsConfig
So i've run out of ideas, on how to draw a JFrame that doesn't show up on the screen, but is never the less fully layed out and functional.
Am going down a rabbit hole here, or can this be done?
A Java top-level container such as JFrame requires access to a peer component native to the host platform, typically via JNI. Alternatively, you may be able to use a BufferedImage or java.awt.headless mode, as discussed here.
Addendum:
I wonder if "any human" can replace how peers are selected.
I don't know how to replace a particular peer component, but it's possible to evoke platform-specific native components; Java Native Access (JNA) is one such avenue. As an extreme example, this 6502 JVM runs in 128K on an 8-bit processor running at 1 MHz. The demos, including source for the lower right screenshot, were compiled using javac.