英文:
How to avoid field glitch with mouse focus
问题
当我将鼠标指针拖出处理窗口时,我的程序会以意想不到的方式做出反应。如何重现:
-
将鼠标指针悬停在“MIN”字段上,并尝试在按住左键的情况下更改字段中的数字值。
-
以中等速度或迅速将鼠标指针向左拖动,然后向右拖动,超出应用程序窗口的区域,但不要释放左键。
-
现在不满足以下条件:
- MIN < MAX
- 始终使 MIN 从 MAX 减去 500 单位。
- MAX > MIN
- MAX 从 MIN 加上 500 单位。
请注意,只有当鼠标指针移出应用程序窗口区域时才会观察到这种效果。是否有任何选项可以消除此效果或如何避免它?
如果不将鼠标指针移动到窗口大小区域上方,那么一切都可以正常工作!
代码:
import controlP5.*;
ControlP5 cp5;
// 范围常数
final float RANGE_MIN = 7.4;
final float RANGE_MAX = 16.8;
// 最小允许的最小/最大值之间的差异
final float RANGE_MIN_DIFFERENCE = 1;
final float RANGE_MID = RANGE_MIN + ((RANGE_MAX - RANGE_MIN) / 2);
float minValue;
float maxValue;
Numberbox inputMin;
Numberbox inputMax;
void setup() {
size(700, 400);
PFont font = createFont("arial", 18);
cp5 = new ControlP5(this);
inputMin = cp5.addNumberbox("minValue")
.setPosition(360, 240)
.setSize(80, 30)
.setColorValue(0xffffff00)
.setFont(font)
.setScrollSensitivity(1.1)
// 设置初始可接受范围
.setMin(RANGE_MIN)
.setMax(RANGE_MAX)
// 设置默认值
.setMultiplier(0.01)
.setDirection(Controller.HORIZONTAL)
.setValue(7.4);
Label labelinputMin = inputMin.getCaptionLabel();
labelinputMin.setFont(font);
labelinputMin.setColor(color(#00ffff));
labelinputMin.toUpperCase(false);
labelinputMin.setText("MIN");
labelinputMin.align(ControlP5.LEFT_OUTSIDE, CENTER);
labelinputMin.getStyle().setPaddingLeft(-100);
inputMax = cp5.addNumberbox("maxValue")
.setPosition(360, 300)
.setSize(80, 30)
.setColorValue(0xffffff00)
.setFont(font)
.setScrollSensitivity(1.1)
// 设置初始可接受范围
.setMin(RANGE_MIN)
.setMax(RANGE_MAX)
// 设置默认值
.setMultiplier(0.01)
.setDirection(Controller.HORIZONTAL)
.setValue(RANGE_MID + 1);
Label labelinputMax= inputMax.getCaptionLabel();
labelinputMax.setFont(font);
labelinputMax.setColor(color(#00ffff));
labelinputMax.toUpperCase(false);
labelinputMax.setText("МAX");
labelinputMax.align(ControlP5.LEFT_OUTSIDE, CENTER);
labelinputMax.getStyle().setPaddingLeft(-93);
textFont(font);
}
void draw() {
constrainRangeInputs();
background(0);
fill(255);
text("minValue: " + minValue + "\n" +
"maxValue: " + maxValue, 10, 15);
}
void controlEvent(ControlEvent event) {
println(event.getController().getName(), "changed value to", event.getValue(), "RANGE_MIN =", minValue, "RANGE_MAX =", maxValue);
}
void constrainRangeInputs() {
float rangeMinInt = (float)inputMin.getValue();
float rangeMaxInt = (float)inputMax.getValue();
//
if (abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE) {
if (rangeMaxInt > RANGE_MID) {
inputMin.setValue(rangeMaxInt - RANGE_MIN_DIFFERENCE);
} else {
inputMax.setValue(rangeMinInt + RANGE_MIN_DIFFERENCE);
}
}
}
英文:
When I drag the mouse pointer outside the processing window, my program reacts in unexpected ways. How to reproduce:
- Hover the mouse pointer over the "MIN" field and try to change the value of the numbers in the field, while holding the left mouse button.
- Drag the mouse pointer at an average speed or sharply to the left and then to the right, beyond the area of the application window without releasing the left button mouse.
- Now the following conditions are not met:
- MIN < MAX
- Always MIN - 500 units from MAX.
- MAX > MIN
- MAX + 500 units from MIN.
Attention, this effect is observed only when the mouse pointer moves out of the area of the application window. Are there any options to eliminate this effect or how to avoid it?
If you do not move the mouse pointer over the window size area, then everything works without problems!
Сode:
import controlP5.*;
ControlP5 cp5;
// range constants
final float RANGE_MIN = 7.4;
final float RANGE_MAX = 16.8;
// the smallest allowed difference between min/max values
final float RANGE_MIN_DIFFERENCE = 1;
final float RANGE_MID = RANGE_MIN + ((RANGE_MAX - RANGE_MIN) / 2);
float minValue;
float maxValue;
Numberbox inputMin;
Numberbox inputMax;
void setup() {
size(700, 400);
PFont font = createFont("arial", 18);
cp5 = new ControlP5(this);
inputMin = cp5.addNumberbox("minValue")
.setPosition(360, 240)
.setSize(80, 30)
.setColorValue(0xffffff00)
.setFont(font)
.setScrollSensitivity(1.1)
// set initial acceptable range
.setMin(RANGE_MIN)
.setMax(RANGE_MAX)
// set default value
.setMultiplier(0.01)
.setDirection(Controller.HORIZONTAL)
.setValue(7.4);
Label labelinputMin = inputMin.getCaptionLabel();
labelinputMin.setFont(font);
labelinputMin.setColor(color(#00ffff));
labelinputMin.toUpperCase(false);
labelinputMin.setText("MIN");
labelinputMin.align(ControlP5.LEFT_OUTSIDE, CENTER);
labelinputMin.getStyle().setPaddingLeft(-100);
inputMax = cp5.addNumberbox("maxValue")
.setPosition(360, 300)
.setSize(80, 30)
.setColorValue(0xffffff00)
.setFont(font)
.setScrollSensitivity(1.1)
// set initial acceptable range
.setMin(RANGE_MIN)
.setMax(RANGE_MAX)
// set default value
.setMultiplier(0.01)
.setDirection(Controller.HORIZONTAL)
.setValue(RANGE_MID + 1);
Label labelinputMax= inputMax.getCaptionLabel();
labelinputMax.setFont(font);
labelinputMax.setColor(color(#00ffff));
labelinputMax.toUpperCase(false);
labelinputMax.setText("МAX");
labelinputMax.align(ControlP5.LEFT_OUTSIDE, CENTER);
labelinputMax.getStyle().setPaddingLeft(-93);
textFont(font);
}
void draw() {
constrainRangeInputs();
background(0);
fill(255);
text("minValue: " + minValue + "\n" +
"maxValue: " + maxValue, 10, 15);
}
void controlEvent(ControlEvent event) {
println(event.getController().getName(), "changed value to", event.getValue(), "RANGE_MIN = ", minValue, "RANGE_MAX = ", maxValue);
}
void constrainRangeInputs() {
float rangeMinInt = (float)inputMin.getValue();
float rangeMaxInt = (float)inputMax.getValue();
//
if (abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE) {
if (rangeMaxInt > RANGE_MID) {
inputMin.setValue(rangeMaxInt - RANGE_MIN_DIFFERENCE);
} else {
inputMax.setValue(rangeMinInt + RANGE_MIN_DIFFERENCE);
}
}
}
答案1
得分: 2
这个问题是由你编写的某些内容以及Processing的draw()
循环的限制引起的,可能在你的情况下限制为60,因为你尚未设置它。
constrainRangeInputs
方法由draw()
循环调用,但不会由Numberbox.updateInternalEvents
方法调用。如果你的FPS非常低,在draw()
方法的两次循环之间,Numberbox可能会更新多次,即使我们看不到它,因为它没有在视觉上更新。
然后,当draw()
循环开始运行时,它会调用你的constrainRangeInputs()
方法。
问题出在这里:
if (abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE) {
绝对值使得rangeMinInt
可能比rangeMaxInt
更大,如果足够大的话。这里是一个会发生这种情况的例子:
假设这些值:
rangeMinInt = 15
rangeMaxInt = 10
RANGE_MIN_DIFFERENCE = 1
// 读取这些数字,你已经知道这应该由constrainRangeInputs()方法进行校正,但是...
// 做一下数学计算就会发现:
rangeMaxInt - rangeMinInt = -5
// 但是:
abs(rangeMaxInt - rangeMinInt) = 5
// 所以:
abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE // false
// 程序将这视为绝对正常!
这与超出窗口无关(如果你改变窗口的大小使其非常宽,你将能够复现这个问题,我进行了实验)。问题在于,当constrainRangeInputs()
完成其工作时,当前的数字已经足够高,以符合你的条件。
这是因为鼠标移动得足够快,以在两次draw()
循环迭代之间的时间内覆盖超过RANGE_MIN_DIFFERENCE
。
你可以通过摆脱abs()
来轻松解决这个问题。我不知道为什么它一开始会相关,但由于你从现有代码进行了调整,它可能是原始代码中的遗留物。
所以:将这行代码
if (abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE) {
改成这样:
if (rangeMaxInt - rangeMinInt < RANGE_MIN_DIFFERENCE) {
希望对你有帮助,这比看起来要棘手。玩得开心!
英文:
This problem arises from a mix of something you wrote and the way Processing's draw()
loop is limited by it's FPS, probably 60 in your case as you haven't set it.
The constrainRangeInputs
method is called by the draw()
loop, but not the Numberbox.updateInternalEvents
method. If your FPS were veeery low, the numberbox could update several time between two loops of the draw()
method, even if we wouldn't see it as it's not visually updated.
Then, when it's time for the draw()
loop to do it's thing, it calls your constrainRangeInputs()
method.
The problem is here:
if (abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE) {
The absolute number makes it possible that a rangeMinInt
be higher than a rangeMaxInt
if it's high enough. Here's an example of when it would happens:
Assuming these values:
rangeMinInt = 15
rangeMaxInt = 10
RANGE_MIN_DIFFERENCE = 1
// Reading these numbers, you already know that this is supposed to be corrected by the constrainRangeInputs() method, but...
// Doing the math reveals that:
rangeMaxInt - rangeMinInt = -5
// yet:
abs(rangeMaxInt - rangeMinInt) = 5
// So:
abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE // false
// The program sees this as absolutely normal!
This has nothing to do with going out of the window (if you change the window's size to make it very wide you'll be able to reproduce the problem, I did it experimentally). The problem is that, when the constrainRangeInputs()
did it's job, the current number was already high enough to be conform to your conditions.
That's because the mouse moved fast enough to cover more than the RANGE_MIN_DIFFERENCE
in the time between two iterations of the draw()
loop.
You can fix this easily by getting rid of the abs()
. I have no idea why it would be relevant in the first place, but as you adapted this from existing code it's probably an artifact from the original code.
So: change this line
if (abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE) {
for this instead:
if (rangeMaxInt - rangeMinInt < RANGE_MIN_DIFFERENCE) {
Hope it helps, that was trickier than it seems. Have fun!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论