2

我在将 Daniel Shiffman 的超棒拖动示例应用到我的草图中时遇到问题。我以前用过它,它很棒,但是我试图用一些“花哨的”循环将它应用到多个对象(在本例中为文本),但无济于事。一切正常,除了对象不应该拖动。从逻辑上讲,这是因为Line类中的 offsetX 和 offsetY 属性不断更新,从而迫使对象保持静止。我确信有一个解决方案,但我无法弄清楚。也许我已经盯着它太久了。我真的很感激帮助!

String[] doc; //array of Strings from each text documents line
int tSize; //text size
float easing; //easing
int boundaryOverlap; //value for words to overlap edges by
PFont font; //font
Lines lines;
boolean clicked = false;

void setup(){
  size(displayWidth/2,displayHeight); 
  background(255);
  fill(0);

  boundaryOverlap = 20; //value for words to overlap edges by
  tSize = 32; //text size

  //loads and formats text
  doc = loadStrings("text.txt"); 
  font = loadFont("Times-Roman-48.vlw");
  textFont(font, tSize);

  //lines object
  lines = new Lines(doc);

  //populate xAddition and yAddition arrays
  lines.populateArrays();
}

void draw(){
  background(255);
  fill(0);

  //loops through each line in .txt
  for(int i = 0; i <= doc.length-1; i++){
    if(clicked) lines.clicked(i);
    lines.move(i, clicked); //update doc[i] positions //deletes 
    lines.display(i); //draws text for each line of text in text.txt
   }
}

void mousePressed(){
   clicked = true;
}

void mouseReleased(){
   clicked = false; 
   lines.dragging = false;
}

这是线类:

class Lines{
  //class properties
  float[] x; //array holding random values to be added to x for placement
  float[] y; //array holding random values to be added to y for placement
  float offsetX;
  float offsetY;
  String[] doc;

  boolean dragging = false; //boolean for dragging

  //construct
  Lines(String[] tempDoc){
    doc = tempDoc;
  }

  //fills x and y arrays
  void populateArrays(){
    x = new float[doc.length];
    y = new float[doc.length];

    //populates x and y arrays
    for(int i = 0; i <= doc.length-1; i++){   
      x[i] = int(random(0-boundaryOverlap, width-boundaryOverlap));
      y[i] = int(random(0, height-boundaryOverlap));
      }
  }

  //draws text
  void display(int i){
       text(doc[i], x[i], y[i]); //draw text
       //if(addition[i] != null) text(addition[i], x[i], y[i]+20);
  }


  void clicked(int i){
    if(mouseX > x[i] &&
       mouseX < x[i]+textWidth(doc[i]) &&
       mouseY < y[i] &&
       mouseY > y[i]-tSize){
       dragging = true;
       offsetX = x[i] - mouseX;
       offsetY = y[i] - mouseY;  
    }
  }

  //updates text positions
  void move(int i, boolean clicked){

       //if mouseOver text hover gray
       if( mouseX > x[i] &&
       mouseX < x[i]+textWidth(doc[i]) &&
       mouseY < y[i] &&
       mouseY > y[i]-tSize){

         fill(100); //gray text fill

         if(dragging){
           x[i] = mouseX + offsetX;
           y[i] = mouseY + offsetY;
         }

       }

       else{
         fill(0); //if not text not mouseOver fill is black
         dragging = false;
       }
  }

  //delete 
  void delete(int i){
    //if "delete" is pressed 
    if (keyPressed){
      if(key == 8){
        doc[i] = ""; // doc[line String that is being hovered over] is replaced with null
        keyCode = 1;
      }
    }
  }
}
4

1 回答 1

1

首先,不要使用 vlw 字体。当每个人都安装了 Times New Roman 时,实际上没有理由使用位图图像文件。只需使用 createFont("Times New Roman",48)。现在您甚至可以更改文本大小而不会看起来很糟糕,因为您只是加载了字体,而不是位图图像。

也就是说,这段代码并不是那么好......但是使用它,问题就在这里:

  for(int i = 0; i <= doc.length-1; i++){
    if(clicked) lines.clicked(i);
    lines.move(i, clicked); //update doc[i] positions //deletes 
    lines.display(i); //draws text for each line of text in text.txt
  }

您检查是否已单击,如果是,则将该行标记为已单击。然后你完全忽略它并移动所有行,而不查看“单击”状态(它根本不用于移动功能)。

也就是说,你想要做的事情可以做得更好,更干净:

LineCollection lines;
float textSize;

void setup(){
  size(400,400);
  // fix the text size, reference a real font
  textSize = 32; 
  textFont(createFont("Times New Roman", textSize));
  // parse strings, construct Lines container
  String[] textValues = new String[]{"lol","cat"};
  lines = new LineCollection(textValues);
  // Do not loop! only update when events warrant,
  // based on redraw() calls  
  noLoop();
}
// fall through drawing
void draw() { background(255); lines.draw(); }
// fall through event handling
void mouseMoved() { lines.mouseMoved(mouseX,mouseY); redraw(); }
void mousePressed() { lines.mousePressed(mouseX,mouseY); redraw(); }
void mouseDragged() { lines.mouseDragged(mouseX,mouseY); redraw(); }
void mouseReleased() { lines.mouseReleased(mouseX,mouseY); redraw(); }


/**
 * A collection of lines. This is *only* a collecton,
 * it is simply responsible for passing along events.
 */
class LineCollection {
  Line[] lines;
  int boundaryOverlap = 20;

  // construct
  LineCollection(String[] strings){
    lines = new Line[strings.length];
    int x, y;
    for(int i=0, last=strings.length; i<last; i++) {
      x = (int) random(0, width);
      y = (int) random(0, height);
      lines[i] = new Line(strings[i], x, y);   
    }
  }

  // fall through drawing   
  void draw() {

    // since we don't care about counting elements
    // in our "lines" container, we use the "foreach"
    // version of the for loop. This is identical to
    // "for(int i=0; i<lines.size(); i++) {
    //    Line l = lines[i];
    //    [... use l here ...]
    //  }"
    // except we don't have to unpack our list manually.

    for(Line l: lines) { l.draw(); }
  }

  // fall through event handling
  void mouseMoved(int mx, int my) { for(Line l: lines) { l.mouseMoved(mx,my); }} 
  void mousePressed(int mx, int my) { for(Line l: lines) { l.mousePressed(mx,my); }} 
  void mouseDragged(int mx, int my) { for(Line l: lines) { l.mouseDragged(mx,my); }}
  void mouseReleased(int mx, int my) { for(Line l: lines) { l.mouseReleased(mx,my); }}
}

/**
 * Individual lines
 */
class Line {
  String s;
  float x, y, w, h;
  boolean active;
  color fillColor = 0;
  int cx, cy, ox=0, oy=0;

  public Line(String _s, int _x, int _y) {
    s = _s;
    x = _x;
    y = _y;
    w = textWidth(s);
    h = textSize;
  }

  void draw() {
    fill(fillColor);
    text(s,ox+x,oy+y+h);
  }

  boolean over(int mx, int my) {
    return (x <= mx && mx <= x+w && y <= my && my <= y+h);
  }

  // Mouse moved: is the cursor over this line?
  // if so, change the fill color
  void mouseMoved(int mx, int my) {
    active = over(mx,my);
    fillColor = (active ? color(155,155,0) : 0);
  }

  // Mouse pressed: are we active? then
  // mark where we started clicking, so 
  // we can do offset computation on
  // mouse dragging.
  void mousePressed(int mx, int my) {
    if(active) {
      cx = mx;
      cy = my;
      ox = 0;
      oy = 0; 
    }
  }

  // Mouse click-dragged: if we're active,
  // change the draw offset, based on the
  // distance between where we initially
  // clicked, and where the mouse is now.
  void mouseDragged(int mx, int my) {
    if(active) {
      ox = mx-cx;
      oy = my-cy;
    }
  }

  // Mouse released: if we're active,
  // commit the offset to this line's
  // position. Also, regardless of
  // whether we're active, now we're not.  
  void mouseReleased(int mx, int my) {
    if(active) {
      x += mx-cx;
      y += my-cy;
      ox = 0;
      oy = 0;
    }
    active = false;
  }
}

更新

解释了此代码中使用的“for”的 foreach 版本。

于 2013-03-09T02:21:39.407 回答