перетаскивание объектов в обработке

У меня возникла проблема с реализацией замечательного примера в моем эскизе. Я использовал его раньше, и это здорово, однако я пытаюсь использовать его с некоторой «причудливостью» для зацикливания, чтобы применить его к нескольким объектам (в данном случае к тексту), но безрезультатно. Все работает правильно, за исключением того, что объекты не перетаскиваются, когда должны. Логически это происходит потому, что свойства offsetX и offsetY в классе Line продолжают обновляться, заставляя объект оставаться неподвижным. Я уверен, что есть решение, но я не могу понять его. Возможно, я слишком долго смотрел на это. Я очень ценю помощь!

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

person Brannon    schedule 09.03.2013    source источник


Ответы (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 для for, используемая в этом коде.

person Mike 'Pomax' Kamermans    schedule 09.03.2013
comment
Я очень ценю ваш ответ. Ваш код намного чище и эффективнее моего. Тем не менее, я работал над расширением проекта, чтобы добавить функциональность (и, в конечном итоге, включить логику в словесную игру), и у меня возникли проблемы с интерпретацией части кода. Я не знаком с некоторым синтаксисом, который вы используете, например, с циклом for с четырьмя параметрами, (int), for(Line l: lines) и другими вещами. Я извиняюсь за отсутствие у меня опыта программирования, и мне интересно, есть ли способ решить мою проблему, используя как можно больше моего (плохого) кода? - person Brannon; 13.03.2013
comment
это стандартный синтаксис java/Processing, так что я, конечно, могу объяснить вам непонятные моменты. Начиная с java 1.5 (что ДОВОЛЬНО давно = D) есть два способа зацикливания. Первый for(int i=0; i‹things.length; i++) { Moo m = Things[i]; [...используйте m здесь...] }. Если вам нужно использовать этот индекс, это полезно. Если вы этого не сделаете, вместо этого вы можете использовать это: for(Moo m: Things) { [...use m here...] }. Они делают то же самое, но второй не беспокоится о значении итерации int, что может значительно облегчить чтение. - person Mike 'Pomax' Kamermans; 13.03.2013