gpt4 book ai didi

处理 - 将一起形成一个圆的多个图像按钮

转载 作者:行者123 更新时间:2023-12-04 17:13:08 33 4
gpt4 key购买 nike

我有几个这样创建的按钮:

setup()

PImage[] imgs1 = {loadImage("AREA1_1.png"),loadImage("AREA1_2.png"),loadImage("AREA1_3.png")};
cp5.addButton("AREA_1") // The button
.setValue(128)
.setPosition(-60,7) // x and y relative to the group
.setImages(imgs1)
.updateSize()
.moveTo(AreaRingGroup); // add it to the group
;

之后 draw()

void AREA_1(){
println("AREA_1");
if (port != null){
port.write("a\n");
}

现在,我必须从将被视为 1 个圆圈的图像中添加大约 24 个小按钮。但是我认为我应该创建一个类,而不是像上面那样使用 cp5.addButton 添加它们。

我想扩展现有的 CP5 按钮类,因为我希望能够达到 cp5 参数;就像使用 .setImages() 按钮图像中的 3 个 mouseClick 条件。

我的问题是,我想不通

  • 如何扩展 CP5 按钮类,以便我可以使用角度(因为我想以圆形方式放置按钮)而不是给出 x、y 位置。

  • 如何使用这个类来写串口,如上面void(AREA_1)的例子。

这是我愚蠢的尝试:

class myButton extends Button
{
myButton(ControlP5 cp5, String theName)
{
super(cp5, cp5.getTab("default"), theName, 0,0,0, autoWidth, autoHeight);
}

PVector pos = new PVector (0,0);
PVector center = new PVector(500,500);
PImage[] img = new PImage[3];
String lable;
int sizeX = 10, sizeY=10;
color imgColor;
Boolean pressed = false;
Boolean clicked = false;

//Constructor
myButton(float a, String theName)
{

//Angle between the center I determined and the position of the
button.
a = degrees (PVector.angleBetween(center, pos));

//Every button will have 3 images for the 3 mouseClick conditions.
for (int i = 0; i < 2; ++i)
(img[i] = loadImage(lable + i + ".png")).resize(sizeX, sizeY);

}
}

最佳答案

Laancelot 的想法不错,但是,由于 controlP5 的 OOP 架构,扩展 controlP5 的 Button 类以从 controlP5 草图实现您的目标可能是不可能的,或者至少是微不足道的。

我假设这与您此时发布的其他 LED 环相关问题有关(例如 this one)。

这可能是错误的(我很想看到一个解决方案),但是如果不 fork /修改 controlP5 库本身,继承链会变得有点棘手。

理想情况下,您只需要扩展 Button 并完成它,但是用于告知状态(如果按钮被按下/按下等)的方法是 Controller 父类(super class)的 inside()方法。要使用您的图像,您需要覆盖此方法并交换逻辑,以便它考虑到您的 png 按钮皮肤的 alpha 透明度(例如,如果光标下的像素是不透明的,那么它在里面,否则它不是)

这是您被迫使用处理草图的粗略说明:

public abstract class CustomController< T > extends Controller< T> {

public CustomController( ControlP5 theControlP5 , String theName ) {
super( theControlP5 , theControlP5.getDefaultTab( ) , theName , 0 , 0 , autoWidth , autoHeight );
theControlP5.register( theControlP5.papplet , theName , this );
}

protected CustomController( final ControlP5 theControlP5 , final ControllerGroup< ? > theParent , final String theName , final float theX , final float theY , final int theWidth , final int theHeight ) {
super(theControlP5, theParent, theName, theX, theY, theWidth, theHeight);
}

boolean inside( ) {
/* constrain the bounds of the controller to the dimensions of the cp5 area, required since PGraphics as render
* area has been introduced. */
//float x0 = PApplet.max( 0 , x( position ) + x( _myParent.getAbsolutePosition( ) ) );
//float x1 = PApplet.min( cp5.pgw , x( position ) + x( _myParent.getAbsolutePosition( ) ) + getWidth( ) );
//float y0 = PApplet.max( 0 , y( position ) + y( _myParent.getAbsolutePosition( ) ) );
//float y1 = PApplet.min( cp5.pgh , y( position ) + y( _myParent.getAbsolutePosition( ) ) + getHeight( ) );
//return ( _myControlWindow.mouseX > x0 && _myControlWindow.mouseX < x1 && _myControlWindow.mouseY > y0 && _myControlWindow.mouseY < y1 );
// FIXME: add alpha pixel logic here
return true;
}

}

public class CustomButton<Button> extends CustomController< Button > {

protected CustomButton( ControlP5 theControlP5 , ControllerGroup< ? > theParent , String theName , float theDefaultValue , int theX , int theY , int theWidth , int theHeight ) {
super( theControlP5 , theParent , theName , theX , theY , theWidth , theHeight );
_myValue = theDefaultValue;
_myCaptionLabel.align( CENTER , CENTER );
}

// isn't this fun ?
//public CustomButton setImage( PImage theImage ) {
// return super.setImage( theImage , DEFAULT );
//}

}

我会建议一个更简单的解决方法:只需在环形布局中添加较小的按钮(使用 polar to cartesian coordinate conversion ):

import controlP5.*;

ControlP5 cp5;

void setup(){
size(600, 600);
background(0);

cp5 = new ControlP5(this);

int numLEDs = 24;
float radius = 240;
for(int i = 0; i < numLEDs; i++){
float angle = (TWO_PI / numLEDs * i) - HALF_PI;
cp5.addButton(nf(i, 2))
.setPosition(width * 0.5 + cos(angle) * radius, height * 0.5 + sin(angle) * radius)
.setSize(30, 30);
}
}

void draw(){}

enter image description here

当然,没有那么漂亮,但要简单得多。希望将绘制在后面的环形图像渲染为背景并更改按钮颜色可能足以让人们明白这一点。

完全跳过 ControlP5 并为此类自定义行为创建您自己的按钮类可能会更简单。

假设您希望在环形布局中有一个方形按钮,该按钮也可以沿环旋转。这种轮换将使检查边界变得更棘手,但并非不可能。您可以使用 PMatrix2D 来跟踪按钮的二维变换矩阵。 ) 渲染按钮,但使用此变换矩阵的逆矩阵在 Processing 的全局坐标系与按钮的局部坐标系之间进行转换。这将使检查按钮是否再次悬停变得微不足道(因为转换为本地坐标的鼠标将在按钮的边界框内)。这是一个例子:

TButton btn;

void setup(){
size(600, 600);
btn = new TButton(0, 300, 300, 90, 90, radians(45));
}
void draw(){
background(0);
btn.update(mouseX, mouseY, mousePressed);
btn.draw();
}
class TButton{

PMatrix2D transform = new PMatrix2D();
PMatrix2D inverseTransform;

int index;
int x, y, w, h;
float angle;

boolean isOver;
boolean isPressed;

PVector cursorGlobal = new PVector();
PVector cursorLocal = new PVector();

color fillOver = color(192);
color fillOut = color(255);
color fillOn = color(127);

TButton(int index, int x, int y, int w, int h, float angle){
this.index = index;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.angle = angle;

transform.translate(x, y);
transform.rotate(angle);
inverseTransform = transform.get();
inverseTransform.invert();

}



void update(int mx, int my, boolean mPressed){
cursorGlobal.set(mx, my);
inverseTransform.mult(cursorGlobal, cursorLocal);
isOver = ((cursorLocal.x >= 0 && cursorLocal.x <= w) &&
(cursorLocal.y >= 0 && cursorLocal.y <= h));
isPressed = mPressed && isOver;
}

void draw(){
pushMatrix();
applyMatrix(transform);
pushStyle();
if(isOver) fill(fillOver);
if(isPressed) fill(fillOn);
rect(0, 0, w, h);
popStyle();
popMatrix();
}


}

如果你可以画一个按钮,你可以画很多按钮,在环形布局中:

int numLEDs = 24;
TButton[] ring = new TButton[numLEDs];

TButton selectedLED;

void setup(){
size(600, 600);
float radius = 240;
float ledSize= 30;
float offsetX = width * 0.5;
float offsetY = height * 0.5;
for(int i = 0 ; i < numLEDs; i++){
float angle = (TWO_PI / numLEDs * i) - HALF_PI;
float x = offsetX + (cos(angle) * radius);
float y = offsetY + (sin(angle) * radius);
ring[i] = new TButton(i, x, y, ledSize, ledSize, angle);
}
println("click to select");
println("click and drag to change colour");
}

void draw(){
background(0);
for(int i = 0 ; i < numLEDs; i++){
ring[i].update(mouseX, mouseY);
ring[i].draw();
}
}

void onButtonClicked(TButton button){
selectedLED = button;
println("selected", selectedLED);
}

void mouseReleased(){
for(int i = 0 ; i < numLEDs; i++){
ring[i].mouseReleased();
}
}

void mouseDragged(){
if(selectedLED != null){
float r = map(mouseX, 0, width, 0, 255);
float g = map(mouseY, 0, height, 0, 255);
float b = 255 - r;
selectedLED.fillColor = color(r, g, b);
}
}

class TButton{

PMatrix2D transform = new PMatrix2D();
PMatrix2D inverseTransform;

int index;
float x, y, w, h;
float angle;

boolean isOver;

PVector cursorGlobal = new PVector();
PVector cursorLocal = new PVector();

color fillColor = color(255);

TButton(int index, float x, float y, float w, float h, float angle){
this.index = index;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.angle = angle;

transform.translate(x, y);
transform.rotate(angle);
inverseTransform = transform.get();
inverseTransform.invert();

}



void update(int mx, int my){
cursorGlobal.set(mx, my);
inverseTransform.mult(cursorGlobal, cursorLocal);
isOver = ((cursorLocal.x >= 0 && cursorLocal.x <= w) &&
(cursorLocal.y >= 0 && cursorLocal.y <= h));
}

void mouseReleased(){
if(isOver) onButtonClicked(this);
}

void draw(){
pushMatrix();
applyMatrix(transform);
pushStyle();
if(isOver) {
fill(red(fillColor) * .5, green(fillColor) * .5, blue(fillColor) * .5);
}else{
fill(fillColor);
}
rect(0, 0, w, h);
popStyle();
popMatrix();
}

String toString(){
return "[TButton index=" + index + "]";
}

}

这还不错,但很容易变得复杂,对吧?您在 draw() 中应用什么全局转换:可能需要由按钮处理?如果在调用 .draw() 时按钮嵌套在一堆 pushMatrix()/popMatrix() 调用中怎么办?等等……

这可以更简单吗?当然,LED 在环形布局上显示为旋转的正方形,但点亮的重要部分是圆形的。无论角度如何,旋转的圆看起来都一样。检查鼠标是否悬停是微不足道的,正如您在 Processing RollOver example 中看到的那样: 简单地检查圆的位置和光标之间的距离是否小于圆的半径。

这是一个使用圆形按钮的示例(无需处理坐标空间转换):

int numLEDs = 24;
CButton[] ring = new CButton[numLEDs];

CButton selectedLED;

void setup(){
size(600, 600);
float radius = 240;
float ledSize= 30;
float offsetX = width * 0.5;
float offsetY = height * 0.5;
for(int i = 0 ; i < numLEDs; i++){
float angle = (TWO_PI / numLEDs * i) - HALF_PI;
float x = offsetX + (cos(angle) * radius);
float y = offsetY + (sin(angle) * radius);
ring[i] = new CButton(i, x, y, ledSize);
}
println("click to select");
println("click and drag to change colour");
}

void draw(){
background(0);
for(int i = 0 ; i < numLEDs; i++){
ring[i].update(mouseX, mouseY);
ring[i].draw();
}
}

void onButtonClicked(CButton button){
selectedLED = button;
println("selected", selectedLED);
}

void mouseReleased(){
for(int i = 0 ; i < numLEDs; i++){
ring[i].mouseReleased();
}
}

void mouseDragged(){
if(selectedLED != null){
float r = map(mouseX, 0, width, 0, 255);
float g = map(mouseY, 0, height, 0, 255);
float b = 255 - r;
selectedLED.fillColor = color(r, g, b);
}
}
class CButton{

int index;
float x, y, radius, diameter;

boolean isOver;

color fillColor = color(255);

CButton(int index, float x, float y, float radius){
this.index = index;
this.x = x;
this.y = y;
this.radius= radius;

diameter = radius * 2;
}

void update(int mx, int my){
isOver = dist(x, y, mx, my) < radius;
}

void mouseReleased(){
if(isOver) onButtonClicked(this);
}

void draw(){
pushMatrix();
pushStyle();
if(isOver) {
fill(red(fillColor) * .5, green(fillColor) * .5, blue(fillColor) * .5);
}else{
fill(fillColor);
}
ellipse(x, y, diameter, diameter);
popStyle();
popMatrix();
}

String toString(){
return "[CButton index=" + index + "]";
}

}

enter image description here

在你的 NeoPixel 环形图像上使用这些圆形按钮,也许还有一点发光可能看起来非常好,并且在 Processing 草图中比采用 ControlP5 路线更容易实现。不要误会我的意思,这是一个很棒的库,但对于自定义行为,有时使用您自己的自定义代码更有意义。

要考虑的另一个方面是整体交互。如果此接口(interface)将用于设置 LED 环的颜色一次,那么它可能没问题,尽管需要 numLEDs * 3 交互才能将所有 LED 设置为自定义颜色。如果这是用于自定义逐帧 LED 动画工具,那么交互会在几帧后变得疲惫不堪。

关于处理 - 将一起形成一个圆的多个图像按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69128147/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com