如何在单击按钮时调用函数?
How to call function on button click?
我有一个名为 Button 的 Processing class,它具有以下功能 onClick
:
class Button() {
// Extra code
void onClick() {
// Run function here
}
}
应该会在单击按钮时触发函数调用,并且该函数是从参数中获取的,如下所示:
Button test = new Button(..., callFunction())
其中 callFunction()
保证是 void
函数。单击 test
后如何调用函数 callFunction()
?我可以检查按钮是否被单击,但我不知道如何将其连接到参数提供的函数调用。
我不确定这是否符合您的目的。但是外部处理程序会很方便。
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.
}
});
注意:大概Java8支持通过lambdas引用回调函数
使用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();
}
}
没有封装成一个class,那要看你自己实现了,
但它确实说明了如何使用 Processing 的内置 draw()
和 mousePressed()
方法处理事件。
如果有帮助,这里有一个按钮 class 我在一些 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.
这是上述按钮 class 的修改版本,它采用包含回调方法和回调方法名称的 class 作为参数:
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 反射和方法 class。
我假设您正在使用 Java 8。如果您没有,您应该!作为它对旧版本的主要改进之一是精确地将函数作为参数。
要将函数对象(即 lambda)作为参数传递,您首先需要定义一个函数接口以某种方式 "hold" 实现您的函数。函数式接口可以是任何只有一种方法的接口,像这样:
interface MyFunction {
public void call();
}
在任何你想要的地方声明它,甚至在你的 Button
class 中。只要 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
class,也不需要覆盖任何内容。 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());
但最好先了解基础知识!
我有一个名为 Button 的 Processing class,它具有以下功能 onClick
:
class Button() {
// Extra code
void onClick() {
// Run function here
}
}
应该会在单击按钮时触发函数调用,并且该函数是从参数中获取的,如下所示:
Button test = new Button(..., callFunction())
其中 callFunction()
保证是 void
函数。单击 test
后如何调用函数 callFunction()
?我可以检查按钮是否被单击,但我不知道如何将其连接到参数提供的函数调用。
我不确定这是否符合您的目的。但是外部处理程序会很方便。
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.
}
});
注意:大概Java8支持通过lambdas引用回调函数
使用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();
}
}
没有封装成一个class,那要看你自己实现了,
但它确实说明了如何使用 Processing 的内置 draw()
和 mousePressed()
方法处理事件。
如果有帮助,这里有一个按钮 class 我在一些 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.
这是上述按钮 class 的修改版本,它采用包含回调方法和回调方法名称的 class 作为参数:
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 反射和方法 class。
我假设您正在使用 Java 8。如果您没有,您应该!作为它对旧版本的主要改进之一是精确地将函数作为参数。
要将函数对象(即 lambda)作为参数传递,您首先需要定义一个函数接口以某种方式 "hold" 实现您的函数。函数式接口可以是任何只有一种方法的接口,像这样:
interface MyFunction {
public void call();
}
在任何你想要的地方声明它,甚至在你的 Button
class 中。只要 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
class,也不需要覆盖任何内容。 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());
但最好先了解基础知识!