如何在 Processing 中允许可编程键输入?
How can I allow programmable key inputs in Processing?
我正在编写一个处理脚本,想检测一个键(使用 key
变量)是否是用户提前选择的一组键中的一个(例如,在设置 JSON 文件或其他方法)。我使用 switch/case 语句来设置它,但事实证明我不能将变量用作 case 表达式。
我使用 final
关键字将它们标记为常量,这适用于定义为直接变量的那些,但不适用于存储在数组中的那些。
有没有办法避免使用长 if
/elseif
语句或将数组拆分为多个变量?
如果不清楚(双关语不是故意的),这是我当前的代码:
// constants
final char[] teamHotkeys = {'b', 'y', 'p', 'o', 'r'};
final char animationHotkey = ' ';
final char doAllHotkey = 'a';
...
// keyPressed handler
void keyPressed(){
float[] chartArea = {gridSizeHeight * 2, gridSizeHeight * 22, gridSizeWidth * 1, gridSizeWidth * 23};
// check which key has been pressed
switch (key){
case teamHotkeys[0]:
drawBar(0, chartArea);
break;
case teamHotkeys[1]:
drawBar(1, chartArea);
break;
case teamHotkeys[2]:
drawBar(2, chartArea);
break;
case teamHotkeys[3]:
drawBar(3, chartArea);
break;
case teamHotkeys[4]:
drawBar(4, chartArea);
break;
case animationHotkey:
runAnimation();
break;
case doAllHotkey:
showFinalScores();
break;
}
}
编译器可以访问 animationHotkey
和 doAllHotkey
很好,现在它们是常量,但它不能访问 teamHotkeys[]
的索引,因为只有数组是常量,但是它的成员在技术上可能已经改变,但编译器不知道他们永远不会改变。
我只会使用 if
语句。有时最愚蠢的代码是最好的。是最容易理解的,写完了就可以放在某个函数里,不用太看。
但是如果你真的想避免 if
语句,你可以采取的一种方法是创建一个 HashMap
将字符键映射到可运行的操作。这是一个非常基本的例子:
HashMap<Character, Runnable> keyRunnableMap = new HashMap<Character, Runnable>();
void setup() {
Runnable aRunnable = new Runnable() {
public void run() {
println("A pressed.");
}
};
Runnable bRunnable = new Runnable() {
public void run() {
println("B pressed.");
}
};
keyRunnableMap.put('a', aRunnable);
keyRunnableMap.put('b', bRunnable);
}
void draw() {
}
void keyPressed() {
if (keyRunnableMap.containsKey(key)) {
keyRunnableMap.get(key).run();
}
}
这可以让您的 keyPressed()
逻辑非常简短,但是需要更多的代码来设置。您可以使用 Java 8 个 lambda 将其缩短一点,但如果您使用的是 Processing 编辑器的当前版本,那将不起作用。我实际上并不推荐这种方法。坚持使用 if
语句。
编辑: 您还可以依赖这样一个事实,即在幕后,key
变量是一个 char
类型,实际上是一个数字.小写 'a'
是数字 97
。更多信息 here。这是一个例子:
Runnable[] runnableArray = new Runnable[2];
void setup() {
Runnable aRunnable = new Runnable() {
public void run() {
println("A pressed.");
}
};
Runnable bRunnable = new Runnable() {
public void run() {
println("B pressed.");
}
};
runnableArray[0] = aRunnable;
runnableArray[1] = bRunnable;
}
void draw() {
}
void keyPressed() {
// a = 97, b = 98
if(key >= 'a' && key <= 'b'){
int index = key - 97;
runnableArray[index].run();
}
}
同样,我实际上并不推荐这种方法,因为它并不比 if
语句更具可读性。
好吧,在 C# 中,一个长开关基本上是一个 HashMap,但在 Java 中,它只是...很多 if/else,所以我通常更喜欢 HashMap,因为我可以使用它。
如果您只想知道您的密钥是否属于某个组(比方说,"teamHotkeys"),您可以使用 HashMap<Character, String>
或 HashMap<Character, KeyType>
(将 KeyType 作为枚举) , 将多个键映射到同一操作。在最坏的情况下它仍然是 O(n),但由于键被分组,它应该比很多 if/else 更好。
HashMap<Character, KeyType> keyTypePairs = new HashMap<Character, KeyType>();
switch(keyTypePairs.get(key)) {
case teamHotkeys:
// ...
break;
}
enum KeyType { teamHotkeys, otherType1, otherType2 }
仅此而已,如果我确实理解了问题,它应该可以工作。
编辑:通过快速测试,我可以说在最坏的情况下,HashMap 占用的 space 在 2.3 到 3.5 KB 之间。大约 300 个条目 = 空保留 space、120 个 (int) 键和 KeyType(每个枚举使用 4 或 8 字节地址,具体取决于 CPU)。不是那么多,但如果我是你,我会考虑在内。另外,我说 300 作为近似值;我没有 120 把钥匙,所以可能会更少或更多。
我正在编写一个处理脚本,想检测一个键(使用 key
变量)是否是用户提前选择的一组键中的一个(例如,在设置 JSON 文件或其他方法)。我使用 switch/case 语句来设置它,但事实证明我不能将变量用作 case 表达式。
我使用 final
关键字将它们标记为常量,这适用于定义为直接变量的那些,但不适用于存储在数组中的那些。
有没有办法避免使用长 if
/elseif
语句或将数组拆分为多个变量?
如果不清楚(双关语不是故意的),这是我当前的代码:
// constants
final char[] teamHotkeys = {'b', 'y', 'p', 'o', 'r'};
final char animationHotkey = ' ';
final char doAllHotkey = 'a';
...
// keyPressed handler
void keyPressed(){
float[] chartArea = {gridSizeHeight * 2, gridSizeHeight * 22, gridSizeWidth * 1, gridSizeWidth * 23};
// check which key has been pressed
switch (key){
case teamHotkeys[0]:
drawBar(0, chartArea);
break;
case teamHotkeys[1]:
drawBar(1, chartArea);
break;
case teamHotkeys[2]:
drawBar(2, chartArea);
break;
case teamHotkeys[3]:
drawBar(3, chartArea);
break;
case teamHotkeys[4]:
drawBar(4, chartArea);
break;
case animationHotkey:
runAnimation();
break;
case doAllHotkey:
showFinalScores();
break;
}
}
编译器可以访问 animationHotkey
和 doAllHotkey
很好,现在它们是常量,但它不能访问 teamHotkeys[]
的索引,因为只有数组是常量,但是它的成员在技术上可能已经改变,但编译器不知道他们永远不会改变。
我只会使用 if
语句。有时最愚蠢的代码是最好的。是最容易理解的,写完了就可以放在某个函数里,不用太看。
但是如果你真的想避免 if
语句,你可以采取的一种方法是创建一个 HashMap
将字符键映射到可运行的操作。这是一个非常基本的例子:
HashMap<Character, Runnable> keyRunnableMap = new HashMap<Character, Runnable>();
void setup() {
Runnable aRunnable = new Runnable() {
public void run() {
println("A pressed.");
}
};
Runnable bRunnable = new Runnable() {
public void run() {
println("B pressed.");
}
};
keyRunnableMap.put('a', aRunnable);
keyRunnableMap.put('b', bRunnable);
}
void draw() {
}
void keyPressed() {
if (keyRunnableMap.containsKey(key)) {
keyRunnableMap.get(key).run();
}
}
这可以让您的 keyPressed()
逻辑非常简短,但是需要更多的代码来设置。您可以使用 Java 8 个 lambda 将其缩短一点,但如果您使用的是 Processing 编辑器的当前版本,那将不起作用。我实际上并不推荐这种方法。坚持使用 if
语句。
编辑: 您还可以依赖这样一个事实,即在幕后,key
变量是一个 char
类型,实际上是一个数字.小写 'a'
是数字 97
。更多信息 here。这是一个例子:
Runnable[] runnableArray = new Runnable[2];
void setup() {
Runnable aRunnable = new Runnable() {
public void run() {
println("A pressed.");
}
};
Runnable bRunnable = new Runnable() {
public void run() {
println("B pressed.");
}
};
runnableArray[0] = aRunnable;
runnableArray[1] = bRunnable;
}
void draw() {
}
void keyPressed() {
// a = 97, b = 98
if(key >= 'a' && key <= 'b'){
int index = key - 97;
runnableArray[index].run();
}
}
同样,我实际上并不推荐这种方法,因为它并不比 if
语句更具可读性。
好吧,在 C# 中,一个长开关基本上是一个 HashMap,但在 Java 中,它只是...很多 if/else,所以我通常更喜欢 HashMap,因为我可以使用它。
如果您只想知道您的密钥是否属于某个组(比方说,"teamHotkeys"),您可以使用 HashMap<Character, String>
或 HashMap<Character, KeyType>
(将 KeyType 作为枚举) , 将多个键映射到同一操作。在最坏的情况下它仍然是 O(n),但由于键被分组,它应该比很多 if/else 更好。
HashMap<Character, KeyType> keyTypePairs = new HashMap<Character, KeyType>();
switch(keyTypePairs.get(key)) {
case teamHotkeys:
// ...
break;
}
enum KeyType { teamHotkeys, otherType1, otherType2 }
仅此而已,如果我确实理解了问题,它应该可以工作。
编辑:通过快速测试,我可以说在最坏的情况下,HashMap 占用的 space 在 2.3 到 3.5 KB 之间。大约 300 个条目 = 空保留 space、120 个 (int) 键和 KeyType(每个枚举使用 4 或 8 字节地址,具体取决于 CPU)。不是那么多,但如果我是你,我会考虑在内。另外,我说 300 作为近似值;我没有 120 把钥匙,所以可能会更少或更多。