Processing中调用外部绘图命令

Calling drawing commands externally in Processing

我正在尝试在 Processing 中使用 g4p-controls 库来创建一个按钮,该按钮在另一个 window 中执行绘图命令。在这个库中,一个 child window 是由代码

创建的
GWindow window = GWindow.getWindow(this, "Main", 100, 50, 500, 500, JAVA2D);

其中 this 是主小程序,其他参数指定名称、位置和渲染器。 GWindow 是 PApplet 的一个子类,所以我应该能够从我的代码中的任何地方调用绘图命令,例如 window.background(0);,将 window 涂成黑色。但是,这不起作用,我不明白为什么。毕竟,当我将它放入处理程序函数并将其添加到 window:

时,相同的代码会起作用
window.addDrawHandler(this, "windowDraw");

windowDraw方法是

public void windowDraw(PApplet app, GWinData data) {
  app.background(0);
}

查看源代码,GWindow object 使用第一个参数 this 调用绘制处理程序方法 windowDraw,这正是所引用的 object到我尝试 window.background(0); 的时候。所以 window 应该是 object 其 background() 方法被调用以将 canvas 涂黑。

如果我对 event-driven 编程的某些基本知识有误解,请告诉我。处理程序似乎确实出于某种原因将相关小程序作为参数,但我真的看不出处理程序函数内部和外部调用有什么不同。

一些附加说明:调用 window.background(0); 如果它在主 draw() 函数内则有效。如果它在 setup() 函数中,它就不起作用,不幸的是,如果它在按钮处理程序方法中,它就不起作用:

public void handleButtonEvents(GButton button, GEvent event) {
  if (this.button == button) {
    if (event == GEvent.PRESSED) {
      window.background(0);
    }
  }
}

显然,我已确保当我按下按钮时此代码实际运行。

更奇怪的是,如果我将上面对 window 的绘图调用替换为 window.strokeWeight(10) 之类的内容,则实际发生了变化,并且 canvas 中的后续线条绘制得更粗.它只是无法实际绘制东西。我只是不知所措。

以后请尽量post一个MCVE而不是一堆断断续续的代码片段。这是一个例子:

import g4p_controls.*;

GWindow window;

void setup(){
  window = GWindow.getWindow(this, "Main", 100, 50, 500, 500, JAVA2D);
}

void draw(){
   background(255, 0, 0); 
   window.ellipse(mouseX, mouseY, 25, 25);
   window.draw();
}

void mousePressed(){
  window.background(0, 255, 0); 
}

当我在第一个 window 中按下鼠标时,我希望此代码在第二个 window 中绘制圆圈,并在第二个 window 中绘制绿色。然而,它似乎只是非常零星地画那些东西。

事实上,这里有相同类型的程序,在 "pure Processing" 中没有使用 G4P 库:

SecondApplet sa;

void setup() {
  String[] args = {"TwoFrameTest"};
  sa = new SecondApplet();
  PApplet.runSketch(args, sa);
}

void settings() {  
  size(200, 200);
}

void draw() {
  background(0);
  sa.ellipse(mouseX, mouseY, 25, 25);
}   

void mousePressed() {
  sa.background(255, 0, 0);
}

public class SecondApplet extends PApplet {

  public void settings() {
    size(200, 200);
  }

  void draw() {
  }
}

我也希望这能起作用,但我们看到第二个草图有类似的灰色 window。我已经提交了一个错误 here 以从处理开发人员那里获得关于这是否是预期行为的反馈。

与此同时,如果你这样做的话,你的运气会更好:

SecondApplet sa;

float drawMouseX;
float drawMouseY;
color drawBackground = #0000ff;

void setup() {
  String[] args = {"TwoFrameTest"};
  sa = new SecondApplet();
  PApplet.runSketch(args, sa);
}

void settings() {  
  size(200, 200);
}

void draw() {
  background(0);
  drawMouseX = mouseX;
  drawMouseY = mouseY;
}   

void mousePressed() {
  drawBackground = #00ff00;
}

public class SecondApplet extends PApplet {

  public void settings() {
    size(200, 200);
  }

  void draw() {
    background(drawBackground);
    ellipse(drawMouseX, drawMouseY, 25, 25);
  }
}

我们现在设置一些变量,然后在第二个小程序的 draw() 函数中使用,而不是直接调用绘图函数。有很多方法可以做到这一点,但想法是一样的:只是不要直接调用绘图函数,而是从 draw() 函数中调用它们。

更新: 我收到了 Ben Fry(Processing 的创始人)和 codeanticode(Processing 的开发者)关于 the bug 的回复 我提交于 GitHub,我现在更清楚为什么这行不通了。

之所以不起作用是因为每个草图都有自己的UI线程,负责绘制和处理事件。您不能从不同的线程绘制草图,否则会发生奇怪的事情。但是你试图从第一个草图的事件线程绘制到第二个草图,不是第二个草图的绘图线程,这就是它不起作用的原因。

查看错误以讨论替代方法,但老实说,您最好的选择可能是采用我概述的方法,即在草图之间共享变量。