Processing Java - 如何使滑块与文件内容成比例

Processing Java - how to make slider proportional to contents of file

我已将 Processing 的示例 Scrollbar/Slider class 修改为垂直方向,并使滑块从顶部而不是中间开始。滑块长度与滚动条的比率最大行数文本区域可以容纳的行数与最大行数的比率文件。滚动条在移动文本方面工作得很好,但这是一个小问题:

打开比较大的文件时,滚动条走得太远,当滚动条到尽头时,应该到文档的末尾。然而,滚动条走得更远,有额外的空行。文本框的定位可能是错的,因为我从我正在制作的文本编辑器中转移了代码。

我测试的文件是 554 行长度

这是主文件:

Scrollbar bar;
String content = "";
float scrollbarRatio;
String absolutePath;
int line;

void setup()
{
  // Background and size
  background(0);
  size(int(displayWidth * 4/5), int(displayHeight * 4/5));

  // Resizable Window
  if (frame != null) {
    frame.setResizable(true);
  }

  // Scrollbar
  bar = new Scrollbar(width-12, 55, 24, height - 79, 1);

  // Input
  selectInput("Select a file to process:", "openFile");
}

// Create set of line numbers given starting number and number of lines
void createLineNumbers(int startingNumber, int numberOfLines)
{
  textAlign(LEFT);
  String lineText = "";
  textLeading(22);

  for (int i = startingNumber; i <= startingNumber + numberOfLines; i++)
  {
    lineText += (str(i) + "\n");
  }

  text(lineText, width/5 + 12.5, 75);
  textAlign(CENTER);
}

void draw()
{
  String[] adjustedLines = content.split("\n");

  int maxLines = floor((height - 80) / 22);

  if (adjustedLines.length > maxLines)
  {
    scrollbarRatio = ((float) maxLines) / ((float) adjustedLines.length);
  }

  // Text Box
  fill(80);
  rect(width/5, 55, width*4/5, height-55);

  textAlign(LEFT);
  textLeading(22);
  fill(225);

  String[] contentLines = content.split("\n");
  String display = "";

  int lineDifference = bar.getLineDifference();

  if (adjustedLines.length > maxLines)
  {
    for (int i = lineDifference; i < maxLines + lineDifference; i++)
    {
      if (i < adjustedLines.length)
      {
        display += adjustedLines[i];
        display += "\n";
      }
    }
  } else
  {
    display = content;
  }

  text(display, width/5+55, 75);

  fill(240);

  if (maxLines < adjustedLines.length)
  {
    createLineNumbers(lineDifference, lineDifference + maxLines);
  } else if (maxLines >= adjustedLines.length)
  {
    createLineNumbers(1, adjustedLines.length);
  }

  bar.resizeScrollbar(width-12, 55, 24, height - 79);
  bar.update(scrollbarRatio);
  bar.display(scrollbarRatio);
}

// File - Open
void openFile(File selection)
{
  if (selection != null)
  {
    try
    {
      // Read content of file
      absolutePath = selection.getAbsolutePath();
      String lines[] = loadStrings(absolutePath);

      // Reset content and line numbers
      content = "";
      line = 0;

      for (int i = 0; i < lines.length; i++) {
        String lineContent = lines[i] + "\n";
        content += lineContent;
        line++;
      }
    }
    catch (Exception exc)
    {
      println(exc.getMessage());
    }
  }
}

这里是 滚动条 class:

class Scrollbar
{
  float swidth, sheight;    // width and height of bar
  float xpos, ypos;         // x and y position of bar
  float spos, newspos;      // x position of slider
  float sposMin, sposMax;   // max and min values of slider
  int loose;                // how loose/heavy
  boolean over;             // is the mouse over the slider?
  boolean locked;           // is the mouse clicked over the slider
  int lineDifference;       

  Scrollbar (int xp, int yp, int sw, int sh, int l) {
    swidth = sw;
    sheight = sh;
    xpos = xp-swidth/2;
    ypos = yp;
    spos = ypos;
    newspos = spos;
    sposMin = ypos;
    sposMax = ypos + sheight;
    loose = l;
  }

  void resizeScrollbar(int xp, int yp, int sw, int sh)
  {
    xpos = xp - swidth/2;
    ypos = yp;
    swidth = sw;
    sheight = sh;
  }

  void update(float ratio) {
    if (over()) {
      over = true;
    } else {
      over = false;
    }
    if (mousePressed && over) {
      locked = true;
    }
    if (!mousePressed) {
      locked = false;
    }
    if (locked) {
      sposMax = ypos + sheight;
      newspos = constrain(mouseY-swidth/2, sposMin, sposMax - sheight * ratio);
      lineDifference = ceil((newspos - 55)/22 * (1/ratio));

      if (abs(newspos - spos) > 1) {
        spos = spos + (newspos-spos)/loose;
      }
    }
  }

  float constrain(float val, float minv, float maxv) {
    return min(max(val, minv), maxv);
  }

  boolean over() {
    if (mouseX > xpos && mouseX < xpos+swidth &&
      mouseY > ypos && mouseY < ypos+sheight) {
      return true;
    } else {
      return false;
    }
  }

  void display(float ratio) {
    fill(220);
    rect(xpos, ypos, swidth, sheight);

    if (over || locked) {
      fill(80);
    } else {
      fill(190);
    }

    // Removes whitespace between slider and beginning of scrollbar
    if (spos != 55 && floor(spos) == 55)
    {
      spos = 55;
    }

    // Removes whitespace between slider and end of scrollbar
    if ((spos + sheight * ratio) != (sheight + ypos) && ceil(spos + sheight * ratio) == (sheight + ypos))
    {
      spos = sheight + ypos - (sheight * ratio);
    }

    rect(xpos, spos, swidth, sheight * ratio);
  }

  int getLineDifference()
  {
    return lineDifference;
  }
}

首先检索滚动到页面底部时与开头的行差异,然后将其添加到可能出现的最大行数中存储在区域,减去文档的长度,我得到了必须从比率的分母中减去的额外数量