2

当我将鼠标指针拖到处理窗口之外时,我的程序会以意想不到的方式做出反应。如何重现:

  1. 将鼠标指针悬停在“MIN”字段上并尝试更改字段中数字的值,同时按住鼠标左键。
  2. 在不松开鼠标左键的情况下,将鼠标指针以平均速度或向左然后向右急剧拖动,超出应用程序窗口的区域。
  3. 现在不满足以下条件:
  • 最小值 < 最大值
  • 总是 MIN - MAX 起 500 个单位。
  • 最大值 > 最小值
  • MAX + 500 个单位从 MIN。

注意,只有当鼠标指针移出应用程序窗口区域时才会观察到这种效果。有什么办法可以消除这种影响或如何避免它?

如果您不将鼠标指针移到窗口大小区域上,那么一切正常!

在此处输入图像描述

代码:

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);
    }
  }
}
4

1 回答 1

2

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!

于 2020-10-15T18:37:05.320 回答