我有一个名为Button的Processing类,它具有以下函数onClick
:
class Button() {
// Extra code
void onClick() {
// Run function here
}
}
应该在单击按钮时触发函数调用,并且函数从参数中获取,如下所示:
Button test = new Button(..., callFunction())
callFunction()
保证为void
函数。单击callFunction()
后如何调用函数test
?我可以检查按钮是否被单击,但我不知道如何将它连接到参数提供的函数调用。
答案 0 :(得分:3)
使用 Runnable 。
Button test = new Button(..., new Runnable(){
public void run() {
// your stuff.
callFunction();
}
});
然后:
class Button() {
private Runnable runnable;
public Button (... Runnable runnable ){
this.runnable = runnable;
}
// Extra code
void onClick() {
runnable.start();
}
}
答案 1 :(得分:1)
我不确定这是否符合你的目的。但是外部处理程序可以很方便。
class Button {
// Extra code
private ClickHandler handler;
//Constructor
Button(..., ClickHandler handler) {
this.handler = handler;
}
void onClick() {
// Run function here
handler.handle();
}
}
interface ClickHandler {
void handle();
}
现在您可以创建对象,如:
Button test = new Button(..., new ClickHandler() {
public void handle() {
//do your stuff.
}
});
注意:可能Java 8通过lambdas支持回调函数引用。
答案 2 :(得分:0)
它没有封装到一个类中,由你来实现,
但它确实说明了如何使用Processing的内置draw()
和mousePressed()
方法处理事件。
如果有帮助,这是我在my sketches中使用的按钮类:
int numButtons = 3;
Button[] buttons = new Button[numButtons];
void setup(){
size(180,200);
int buttonWidth = 150;
int buttonHeight = 50;
int buttonSpacing = 15;
for(int i = 0 ; i < numButtons; i++){
buttons[i] = new Button("button "+(i+1),buttonSpacing,(buttonHeight+buttonSpacing) * i,buttonWidth,buttonHeight);
}
}
void draw(){
background(255);
for(int i = 0 ; i < numButtons; i++){
buttons[i].update(mouseX, mouseY, mousePressed);
buttons[i].draw();
}
}
//hacky way callback the main sketch from a button - look into callbacks
void onButtonClicked(Button b){
println(b.label,"was pressed at",new java.util.Date());
}
class Button{
float w,h,x,y;//width, height and position
color bg = color(200);//background colour
color fg = color(0);//foreground colour
String label;//button label
boolean isOver,wasPressed;
int pw = 10;
Button(String label,float x,float y,float w,float h){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.label = label;
}
//mouseY,mouseY,mouseDown
void update(int mx,int my,boolean md){
//it's over if it's within the button's bounding box
isOver = ((mx >= x && mx <= (x+w))&&(my >= y && my <= (y+h)));
//if it's over and pressed it's a click
if(isOver && md){
//if it wasn't pressed before, trigger click callback
if(!wasPressed){
onButtonClicked(this);
wasPressed = true;
}
}else wasPressed = false;
}
void draw(){
pushStyle();
noStroke();
fill(isOver ? fg : bg);
rect(x,y,w,h);
fill(isOver ? bg : fg);
text(label,x+pw,y+h*.75);
popStyle();
}
}
您可能需要以不同方式实施,但希望这会给您一些想法。
<强>更新强> 如果感觉回调是你追求的主要事情。 如果是这种情况,一种选择是使用Java Reflection to invoke a Method。
这是上面Button类的修改版本,它将包含回调方法的类和回调方法的名称作为参数:
import java.lang.reflect.*;
int numButtons = 3;
Button[] buttons = new Button[numButtons];
void setup(){
size(180,200);
int buttonWidth = 150;
int buttonHeight = 50;
int buttonSpacing = 15;
for(int i = 0 ; i < numButtons; i++){
buttons[i] = new Button(this,"onButton"+(i+1)+"Clicked","button "+(i+1),buttonSpacing,(buttonHeight+buttonSpacing) * i,buttonWidth,buttonHeight);
}
}
void draw(){
background(255);
for(int i = 0 ; i < numButtons; i++){
buttons[i].update(mouseX, mouseY, mousePressed);
buttons[i].draw();
}
}
public void onButton1Clicked(){
println("button 1 clicked");
}
public void onButton2Clicked(){
println("button 2 clicked");
}
public void onButton3Clicked(){
println("button 3 clicked");
}
class Button{
float w,h,x,y;//width, height and position
color bg = color(200);//background colour
color fg = color(0);//foreground colour
String label;//button label
boolean isOver,wasPressed;
int pw = 10;
Object parent;
Method callback;
Button(Object parent,String callbackName,String label,float x,float y,float w,float h){
this.parent = parent;
try{
callback = parent.getClass().getMethod(callbackName);
}catch(Exception e){
e.printStackTrace();
}
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.label = label;
}
//mouseY,mouseY,mouseDown
void update(int mx,int my,boolean md){
//it's over if it's within the button's bounding box
isOver = ((mx >= x && mx <= (x+w))&&(my >= y && my <= (y+h)));
//if it's over and pressed it's a click
if(isOver && md){
//if it wasn't pressed before, trigger click callback
if(!wasPressed){
//onButtonClicked(this);
if(callback != null){
try{
callback.invoke(parent);
}catch(Exception e){
e.printStackTrace();
}
}
wasPressed = true;
}
}else wasPressed = false;
}
void draw(){
pushStyle();
noStroke();
fill(isOver ? fg : bg);
rect(x,y,w,h);
fill(isOver ? bg : fg);
text(label,x+pw,y+h*.75);
popStyle();
}
}
这是解决问题的一种方法。如果需要这些回调的参数,请务必深入研究java反射和Method类。
答案 3 :(得分:0)
我将假设您使用的是Java 8.如果您不是,那么您应该这样做!由于其对旧版本的主要改进之一就是将函数作为参数进行精确处理。
要传递一个函数对象(即lambda)作为参数,首先需要定义一个功能界面以某种方式&#34; hold&#34;你的功能的实现。功能界面可以是只有一种方法的任何界面,如下所示:
interface MyFunction {
public void call();
}
即使在Button
课程内,也可以在任何地方声明它。只要Button
可以访问它就无所谓。
然后你告诉你的Button
构造函数最后一个参数是一个函数,将它存储为私有字段,并在单击该按钮后调用它:
class Button() {
MyFunction buttonFunction;
public Button(..., MyFunction myFunction) {
// ... other initialization ...
buttonFunction = myFunction;
}
// Extra code
void onClick() {
// Run function here
buttonFunction.call();
}
}
要将您的函数作为参数传递,请执行以下操作:
Button test = new Button(..., () -> callFunction());
您不需要创建匿名MyFunction
类,也不需要覆盖任何内容。 Java 8为您提供了所有这些。它知道Button
构造函数需要MyFunction
参数,并且它知道MyFunction
只有一个方法,call()
没有参数;因此,当您提供没有参数的函数体时,Java知道它是MyFunction#call()
的实现。
事实上,您甚至不需要定义界面:您只需将MyFunction
替换为Runnable
,将call()
替换为run()
,一切都会按预期工作,因为Runnable
也是一个功能界面:
class Button() {
Runnable buttonFunction;
public Button(..., Runnable myFunction) {
// ... other initialization ...
buttonFunction = myFunction;
}
// Extra code
void onClick() {
// Run function here
buttonFunction.run();
}
}
Button test = new Button(..., () -> callFunction());
但首先要了解基础知识会更好!