首页 > 解决方案 > 如何在 mousePress() 上更改单行的颜色

问题描述

我有一小段代码用于原型。

我试图让它在 mousePressed() 或 mouseClicked() 上单击的行的颜色会改变。

我这辈子都想不通!

任何帮助将非常感激!

到目前为止我设法编写的代码如下,它应该可以正常工作。

int value = 0;
ArrayList<Line> l = new ArrayList<Line>();

void setup() {
   size(500,500);
   background(57, 76, 222);
   //noLoop();
   stroke(255);
   strokeWeight(3);
}

void draw() {
    for (int i = 1; i< 20; i++) {
        l.add(new Line());   
        for (int a=0; a< l.size(); a++){
            l.get(a).display();
            noLoop();
        }
    }
    int total = l.size();
    println("The total number of lines is: " + total);
}


class Line {
    int ranX1, ranX2, ranY1, ranY2;

    Line() {
        ranX1 = int(random(50,450));
        ranX2 = int(random(50,450));
        ranY1 = int(random(50,450));
        ranY2 = int(random(50,450));
    }

    void update() {
        //
    }

    void display() {
        line(ranX1,ranX2,ranY1,ranY2);
    }
}

标签: javaprocessing

解决方案


如果你有一条线,由一个点 ( O) 和一个方向 ( D) 给出,那么线上到点 p 的最近点可以计算如下

X = O + D * dot(P-O, D);

2 个向量的点积等于 2 个向量之间的夹角的余弦乘以两个向量的大小(长度)。

在此处输入图像描述

dot( A, B ) == | A | * | B | * cos( alpha ) 

V和的点积D等于线 ( O, D) 与向量之间的夹角的余弦V = P - O乘以 的量(长度)V,因为D单位向量(的长度D为 1.0)。

用于PVector获取从 ( ranX1, ranY1) 到 ( ranX2, ranY2) 的方向,并将方向向量通过 转化为单位向量.normalize()。向量的长度由 验证.mag()

PVector D = new PVector(ranX2 - ranX1, ranY2 - ranY1);
if ( D.mag() > 0.0 )
    D.normalize();

使用上述算法计算到一条无限线的法线距离,其中点 ( ranX1, ranY1) 和 ( ranX2, ranY2) 位于其中。为此,使用方法.mult()、和:.add().dist().dot()

PVector X = new PVector(ranX1, ranY1);
X.add( D.mult( D.dot( vP1 ) ) );
boolean hit = X.dist(new PVector(x, y)) < hit_dist;

使用点积验证X直线与法线的交点 ( x)y是否在 ( ranX1, ranY1) 和 ( ranX2, ranY2) 之间。如果两条亚麻布之间的角度大于 90 度或小于 -90 度,则点积小于 0.0:

PVector vP1 = new PVector(x - ranX1, y - ranY1);
if ( D.dot( vP1 ) < 0.0 )
    hit = false;

PVector vP2 = new PVector(x - ranX2, y - ranY2);
if ( D.dot( vP2 ) > 0.0 )
    hit = false;

isHit向类添加一个方法,该方法Line检查输入位置 ( x, y) 是否在线。可以通过 设置识别线上点击的可接受准确度hit_dist。如果必须准确地击中线,请减小此值。增加它以允许击中线旁边但也靠近线。添加一个颜色属性col和一个可以改变颜色的方法:

class Line {

    // [...]

    color col;

    // [...]

    void setColor(color c) {
        col = c;
    }

    boolean isHit(int x, int y) {

        final int hit_dist = 5;

        // [...]

        return hit;
    }
}

使用鼠标按下事件mousePressed()遍历循环中的所有行。鼠标按下时改变每行颜色为2hit":

void mousePressed() {

    for (int i = 0; i < l.size(); ++i) {

        if (l.get(i).isHit(mouseX, mouseY)) {
            l.get(i).setColor(color(255, 0, 0) );
        }
    } 
}

请参阅示例,该示例实现了算法并对您的代码进行了一些进一步的改进和错误修复:

int value = 0;
ArrayList<Line> l = new ArrayList<Line>();

void setup() {
    size(500,500);

   for (int i = 0; i < 20; ++i) {
       l.add(new Line());  
   }
}

void draw() {

    background(57, 76, 222);

    strokeWeight(3);
    for (int i = 0; i < l.size(); ++i) {
       l.get(i).display();
    }
}

void mousePressed() {

    for (int i = 0; i < l.size(); ++i) {

        if (l.get(i).isHit(mouseX, mouseY)) {
            l.get(i).setColor(color(255, 0, 0) );
        }
    } 
}

class Line {
    int ranX1, ranX2, ranY1, ranY2;
    color col;

    Line() {
        col = color(255);
        ranX1 = int(random(50,450));
        ranX2 = int(random(50,450));
        ranY1 = int(random(50,450));
        ranY2 = int(random(50,450));
    }

    void setColor(color c) {
        col = c;
    }

    boolean isHit(int x, int y) {

        final int hit_dist = 5;

        PVector D = new PVector(ranX2 - ranX1, ranY2 - ranY1);
        if ( D.mag() > 0.0 )
            D.normalize();

        PVector vP1 = new PVector(x - ranX1, y - ranY1);
        if ( D.dot( vP1 ) < 0.0 )
            return false;

        PVector vP2 = new PVector(x - ranX2, y - ranY2);
        if ( D.dot( vP2 ) > 0.0 )
            return false;

        PVector X = new PVector(ranX1, ranY1);
        X.add( D.mult( D.dot( vP1 ) ) );
        boolean hit = X.dist(new PVector(x, y)) < hit_dist; 

        return hit;
    }

    void display() {
        stroke(col);
        line(ranX1, ranY1, ranX2, ranY2);
    }
}

推荐阅读