如何避免鼠标焦点的字段故障

How to avoid field glitch with mouse focus

当我将鼠标指针拖出处理 window 时,我的程序以意想不到的方式做出反应。复现方式:

  1. 将鼠标指针悬停在“MIN”字段上并尝试更改字段中数字的值,同时按住鼠标左键。
  2. 以平均速度或急剧向左然后向右拖动鼠标指针,超出应用程序区域window而不松开鼠标左键。
  3. 现在不满足以下条件:

注意,只有当鼠标指针移出应用程序区域时才会观察到此效果window。是否有任何选项可以消除这种影响或如何避免这种影响?

如果您不将鼠标指针移到 window 尺寸区域,则一切正常!

代码:

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

这个问题是由你写的东西和 Processing 的 draw() 循环受其 FPS 限制的方式混合引起的,在你的情况下可能是 60,因为你没有设置它。

constrainRangeInputs方法被draw()循环调用,而不是Numberbox.updateInternalEvents方法。如果您的 FPS 非常低,数字框可能会在 draw() 方法的两次循环之间更新几次,即使我们看不到它,因为它没有在视觉上更新。

然后,当 draw() 循环执行它的任务时,它会调用您的 constrainRangeInputs() 方法。

问题在这里:

if (abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE) {

如果足够高,绝对数使得 rangeMinInt 可能高于 rangeMaxInt。这是何时发生的示例:

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!

这与离开 window 无关(如果您更改 window 的大小使其非常宽,您将能够重现该问题,我做到了它是实验性的)。问题是,当 constrainRangeInputs() 完成它的工作时,当前数字已经足够高以符合您的条件。

那是因为鼠标移动得足够快,在 draw() 循环的两次迭代之间的时间里覆盖了超过 RANGE_MIN_DIFFERENCE

您可以通过删除 abs() 轻松解决此问题。我不知道为什么它首先会相关,但是当你从现有代码中改编它时,它可能是原始代码的产物。

所以:更改此行

if (abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE) {

为此:

if (rangeMaxInt - rangeMinInt < RANGE_MIN_DIFFERENCE) {

希望对您有所帮助,这比看起来要棘手。玩得开心!