目前我正在努力解决我的 Java Processing 程序的一个大问题。我正在制作一个程序,因此当您单击一个按钮时,它会打开一个新草图(一个新窗口)并关闭前一个草图。在新窗口中,有一个后退按钮,您可以在其中返回到上一个窗口。
如果我第二次点击“后退按钮”,当它打开前一个窗口时,程序崩溃并给出以下错误:
handleDraw() called before finishing
奇怪的是,程序只有在我点击按钮几次后才会崩溃。每次,程序在总共单击 5 个按钮后崩溃。我当然应该能够反复打开和关闭两个不同的草图(窗口),而不是崩溃。
我已经确保 draw();方法不能同时运行。
注意事项: “Knap”类是一个按钮类。 “Fitness”、“Main”和“Morgenmad”类都从 PApplet 扩展而来,因此我可以为每个类创建一个实例,然后运行 draw();和设置();每个类中的方法使用 PApplet.runSketch();每当我想,为了打开一个新窗口。我知道这不是最好的方法,但我正在为一个项目写这个,现在完全重写已经太晚了。
代码如下: (请记住,我的程序实际上比我提供的代码大得多,但我删除了所有与展示我遇到的问题无关的代码。我还把 GUI 和Knap 类在同一个文件中,所以在这里显示我的代码更容易)
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);
}
}
}
我做了一个调试系统,以确保 draw() 方法不会同时运行。有趣的是,它看起来像 openPreviousWindow();当你在某个时候点击按钮时,方法运行两次,然后程序崩溃。我已经这样做了,当这个方法被调用时程序会打印出一些东西,你可以在这里看到它运行了两次然后程序崩溃了。
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
一个选项是在 Processing startup() 时创建所有窗口,但只显示主窗口并在创建时使用 surface.setVisible(false) 隐藏其他窗口。当需要它们时,使用 .setVisible(true) 来显示它们并使用 .setVisible(false) 隐藏其他的。我认为显示/隐藏技术比处理它们然后尝试重新实例化它们造成的麻烦更少。下面是一个简单的演示;请注意,默认情况下会实例化原始处理窗口,但不会使用。这两个 PApplet 窗口每个只实例化一次。
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
}