currently I'm struggling with a massive problem with my Java Processing program. I'm making a program so when you click a button, it opens a new sketch (a new window) and closes the previous one. In the new window, there's a back button where you can go back to the previous window.
If I click the "back button" for the 2nd time, when it opens the previous window, the program crashes and gives the following error:
handleDraw() called before finishing
The weird thing is that the program only crashes after I click the buttons a couple of times. Every time, the program crashes after clicking a total of 5 buttons. Instead of crashing, I should of course be able to open and close the two different sketches (windows) repeatedly.
I've made sure that the draw(); methods can't run at the same time.
Notes: The "Knap" class is a button class. The "Fitness", "Main" and "Morgenmad" classes all extends from PApplet so I can create an instance of each class and then run the draw(); and settings(); method in each class by using PApplet.runSketch(); whenever I want to, in order to open a new window. I know this is not the best way to do it, but I'm writing this for a project and it's too late to completely rewrite.
Here is the code: (Keep in mind that my program is actually much bigger than the code I've provided, but I've removed all the code that is not relevant in terms of showcasing the issue I'm having. I've also put the GUI and Knap class in the same file, so it's easier to show my code in here)
import processing.core.PImage;
import java.awt.*;
public class Main extends PApplet {
GUI gui = new GUI(this);
boolean fitnessAppSportsUdøverWindow = false;
boolean morgenmadWindow = false;
boolean mainWindow = true;
PImage image;
String[] fitnessAppSportsUdøverArgs = {"FitnessAppSportsUdøver"};
String[] morgenmadArgs = {"Morgenmad"};
Knap morgenmadKnap;
FitnessAppSportsUdøver fasu = new FitnessAppSportsUdøver();
MorgenmadMenu mm = new MorgenmadMenu();
public static void main(String[] args) {
Main program = new Main();
String[] processingArgs = {"Teknologi FitnessApp"};
PApplet.runSketch(processingArgs, program);
}
public void settings() {
size(800, 800);
}
public void draw() {
if (mainWindow && !fitnessAppSportsUdøverWindow) {
windowTitle("Teknologi FitnessApp");
gui.draw();
System.out.println("main = " + mainWindow);
}
if (!mainWindow && fitnessAppSportsUdøverWindow) {
closePreviousWindow();
System.out.println("main = " + mainWindow);
stop();
}
}
private void closePreviousWindow() {
if (fitnessAppSportsUdøverWindow) {
Frame[] frames = Frame.getFrames();
for (Frame frame : frames) {
if (frame.getTitle().equals("Teknologi FitnessApp")) {
frame.dispose();
}
}
}
Frame[] frames = Frame.getFrames();
for (Frame frame : frames) {
if (frame.getTitle().equals("FitnessAppSportsUdøver") && morgenmadWindow) {
frame.dispose();
}
}
}
public void mousePressed() {
//gui.mousePosition();
if (gui.knap1.overKnap()) {
drawFitnessAppSportsUdøver();
}
}
void drawFitnessAppSportsUdøver() {
mainWindow = false;
fitnessAppSportsUdøverWindow = true;
System.out.println("FITNESSAPP DRAWN");
PApplet.runSketch(fitnessAppSportsUdøverArgs, fasu);
}
void drawMorgenmadMenu() {
fitnessAppSportsUdøverWindow = false;
morgenmadWindow = true;
System.out.println("MORGENMADMENU DRAWN");
PApplet.runSketch(morgenmadArgs, mm);
}
class FitnessAppSportsUdøver extends PApplet {
FitnessAppSportsUdøver() {
morgenmadKnap = new Knap(this, 722, 527, 50, 50, 0, 210);
}
public void settings() {
size(800, 800);
image = loadImage("teknologi fitnessapp2.png");
}
public void draw() {
if (fitnessAppSportsUdøverWindow && !morgenmadWindow) {
morgenmadKnap.draw();
System.out.println("fit = " + fitnessAppSportsUdøverWindow + " morgenmad = " + morgenmadWindow + " main = " + mainWindow);
}
if (!fitnessAppSportsUdøverWindow && morgenmadWindow) {
closePreviousWindow();
System.out.println("fit = " + fitnessAppSportsUdøverWindow + " morgenmad = " + morgenmadWindow + " main = " + mainWindow);
stop();
}
}
public void mousePressed() {
if (morgenmadKnap.overKnap()) {
drawMorgenmadMenu();
}
}
}
class MorgenmadMenu extends PApplet {
Knap tilbageKnap = new Knap(this, 20, 100, 100, 100, 0, 210);
public void settings() {
size(800, 800);
}
public void draw() {
if (morgenmadWindow && !fitnessAppSportsUdøverWindow) {
background(255, 255, 255);
tilbageKnap.draw();
System.out.println("morgenmad = " + morgenmadWindow + " fit = " + fitnessAppSportsUdøverWindow + " main = " + mainWindow);
}
if (!morgenmadWindow && fitnessAppSportsUdøverWindow) {
closePreviousWindow();
System.out.println("morgenmad = " + morgenmadWindow + " fit = " + fitnessAppSportsUdøverWindow + " main = " + mainWindow);
stop();
}
}
public void mousePressed() {
if (tilbageKnap.overKnap()) {
openPreviousWindow();
}
}
void openPreviousWindow() {
Frame[] frames = Frame.getFrames();
for (Frame frame : frames) {
if (frame.getTitle().equals("MorgenmadMenu")) {
//drawFitnessAppSportsUdøver();
System.out.println("FITNESSAPP DRAWN OPENPREVIOUS WINDOW");
morgenmadWindow = false;
fitnessAppSportsUdøverWindow = true;
PApplet.runSketch(fitnessAppSportsUdøverArgs, fasu);
frame.dispose();
}
}
}
}
class GUI {
PApplet p;
Knap knap1;
PImage image;
public GUI(PApplet p) {
this.p = p;
knap1 = new Knap(p, 319, 675, 190, 100, 255, 100);
}
void draw() {
knap1.draw();
displayTekst();
image = p.loadImage("girl healthy.jpg");
image.resize(600, 530);
p.image(image, p.width / 2 - 285, 122);
}
void displayTekst() {
p.fill(0);
p.textSize(40);
p.text("Velkommen til FitForSport", p.width / 2 - 210, 50);
p.smooth();
p.textSize(20);
p.text("Du har taget det første skridt for et bedre liv med sport", p.width / 2 - 210, 100);
p.smooth();
p.textSize(60);
p.text("Start", 355, 740);
p.smooth();
}
void mousePosition() {
System.out.println("X koordinat " + p.mouseX + " Y koordinat " + p.mouseY);
System.out.println("");
}
}
class Knap {
PApplet p;
int farve, hover;
float posX, posY, width, height;
public Knap(PApplet p, float posX, float posY, float width, float height, int f, int h) {
this.p = p;
this.posX = posX;
this.posY = posY;
this.width = width;
this.height = height;
farve = f;
hover = h;
}
boolean overKnap() {
if (p.mouseX >= posX && p.mouseX <= posX + width && p.mouseY >= posY && p.mouseY <= posY + height) {
return true;
}
return false;
}
void draw() {
if (overKnap())
p.fill(hover);
else
p.fill(farve);
p.rect(posX, posY, width, height);
}
}
}
I've made a debugging system in order to make sure that the draw() methods are not running at the same time. What is interesting to note is that it seems like the openPreviousWindow(); method runs twice when you click on the button at some point, and then the program crashes. I've done so the program prints something out when this method is being called, and you can see here that it runs twice and then the program crashes.
morgenmad = true fit = false main = false
morgenmad = true fit = false main = false
morgenmad = true fit = false main = false
FITNESSAPP DRAWN OPENPREVIOUS WINDOW
fit = true morgenmad = false main = false
FITNESSAPP DRAWN OPENPREVIOUS WINDOW
fit = true morgenmad = false main = false
fit = true morgenmad = false main = false
handleDraw() called before finishing
One option would be to create all the windows at Processing startup(), but only show the mainWindow and hide the others by using surface.setVisible(false) as they are created. When they are needed use .setVisible(true) to show them and hide the others with .setVisible(false). I think the show/hide technique would cause less trouble than disposing of them and then trying to re-instantiate them. A simple demo follows; note that the original Processing window is instantiated by default but not used. The two PApplet windows are each instantiated only once.
import java.awt.Frame;
import processing.awt.PSurfaceAWT;
int _btnX = 50;
int _btnY = 50;
int _btnW = 200;
int _btnH = 30;
WindowOne wndOne;
WindowTwo wndTwo;
processing.awt.PSurfaceAWT wnd1;
processing.awt.PSurfaceAWT wnd2;
class WindowTwo extends PApplet {
WindowTwo () {
PApplet.runSketch(new String[]{this.getClass().getName()}, this);
surface.setTitle("Window Two");
println("wnd2 = ",surface);
surface.setVisible(false);
wnd2 = (PSurfaceAWT)surface;
}
void settings() {
size(300, 200);
}
void setup() {
background(209);
}
void draw() {
fill(color(0, 255, 0));
rect(50, 50, 200, 30);
fill(0);
textSize(20);
textAlign(CENTER, CENTER);
text("Show Window One", _btnX, _btnY, _btnW, _btnH);
}
void mousePressed() {
if ((mouseX >= _btnX) && (mouseX <= _btnX + _btnW) && (mouseY >= _btnY) && (mouseY <= _btnY + _btnH)) {
surface.setVisible(false); // Hide this window
wnd1.setVisible(true); // Show the other one
}
}
}
class WindowOne extends PApplet {
WindowOne () {
PApplet.runSketch(new String[]{this.getClass().getName()}, this);
surface.setTitle("Window One");
surface.setLocation(400, 400);
println("wnd1 = ",surface);
wnd1 = (PSurfaceAWT)surface;
}
void settings() {
size(400, 200);
}
void setup() {
background(255);
}
void draw() {
fill(color(0, 255, 0));
rect(50, 50, 200, 30);
fill(0);
textSize(20);
textAlign(CENTER, CENTER);
text("Show Window Two", _btnX, _btnY, _btnW, _btnH);
}
void mousePressed() {
if ((mouseX >= _btnX) && (mouseX <= _btnX + _btnW) && (mouseY >= _btnY) && (mouseY <= _btnY + _btnH)) {
surface.setVisible(false); // Hide this window
wnd2.setVisible(true); // Show the other one
}
}
}
void setup() {
surface.setVisible(false);
println("default = ",surface);
wndOne = new WindowOne(); // Build two, but show only one
wndTwo = new WindowTwo(); // Originally not shown
}