英文:
How to display a button with an image only in the desired tab?
问题
import controlP5.*;
ControlP5 cp5;
ImageButton button;
Textlabel I;
Textlabel tempIn;
void setup() {
size(700, 420, P3D);
surface.setResizable(false);
smooth();
frameRate(30);
cp5 = new ControlP5(this);
PFont p = createFont("Times New Roman", 18);
ControlFont font = new ControlFont(p);
cp5.setFont(font);
cp5.addTab("okno2")
.setColorBackground(color(0, 160, 100))
.setColorLabel(color(255))
.setColorActive(color(255, 128, 0));
cp5.getTab("default")
.activateEvent(true)
.setLabel("okno1")
.setId(1);
cp5.getTab("okno2")
.activateEvent(true)
.setId(2);
tempIn = cp5.addTextlabel("Sostoyanie")
.setText("1")
.setFont(createFont("Times New Roman", 20))
.setColor(color(0xffffff00))
.setPosition(155, 35);
I = cp5.addTextlabel("Impuls")
.setText("2")
.setPosition(155, 35)
.setFont(createFont("Times New Roman", 20))
.setColor(color(0xffffff00))
.moveTo("okno2");
int w = 99;
int h = 25;
button = new ImageButton(112, 137, w, h,
new PImage[]{
loadImage("0.png"), // off
loadImage("1.png"), // 10
loadImage("2.png"), // 20
loadImage("3.png"), // 30
loadImage("4.png"), // 40
loadImage("5.png"), // 50
loadImage("6.png"), // 60
});
}
void draw() {
background(0);
button.draw();
}
void mousePressed() {
button.mousePressed(mouseX, mouseY);
println(button.min);
}
PImage getImage(int w, int h, int c) {
PImage img = createImage(w, h, RGB);
java.util.Arrays.fill(img.pixels, c);
img.updatePixels();
return img;
}
class ImageButton {
int min = 0;
PImage[] stateImages;
int stateIndex;
int x, y;
int w, h;
String label = "ВЫКЛ";
ImageButton(int x, int y, int w, int h, PImage[] stateImages) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.stateImages = stateImages;
}
void mousePressed(int mx, int my) {
boolean isOver = ((mx >= x && mx <= x + w) &&
(my >= y && my <= y + h)); // check vertical
if (isOver) {
min += 10;
stateIndex++;
if (min > 60) {
min = 0;
stateIndex = 0;
label = "ВЫКЛ";
} else {
label = min + " Мин";
}
}
}
void draw() {
if (stateImages != null && stateIndex < stateImages.length) {
image(stateImages[stateIndex], x, y, w, h);
} else {
println("error displaying button state image");
println("stateImages:");
printArray(stateImages);
println("stateIndex: " + stateIndex);
}
}
}
英文:
I have OKNO1 and OKNO2, I want to show a button with an image strictly in OKNO1.
At the moment, the button with the image is shown globally.
I used to use cp5.addButton
and there I did it with .moveTo("okno1");
Now the image button uses OOP/Java.
How to solve a tricky problem? What ways can you do the task. I think to use again void draw()
.
Complete code example:
import controlP5.*;
ControlP5 cp5;
ImageButton button;
Textlabel I;
Textlabel tempIn;
void setup() {
size(700, 420, P3D);
surface.setResizable(false);
smooth();
frameRate(30);
cp5 = new ControlP5(this);
PFont p = createFont("Times New Roman", 18);
ControlFont font=new
ControlFont(p);
cp5.setFont(font);
cp5.addTab("okno2")
.setColorBackground(color(0, 160, 100))
.setColorLabel(color(255))
.setColorActive(color(255, 128, 0));
cp5.getTab("default")
.activateEvent(true)
.setLabel("okno1")
.setId(1);
cp5.getTab("okno2")
.activateEvent(true)
.setId(2);
tempIn = cp5.addTextlabel("Sostoyanie")
.setText("1")
.setFont(createFont("Times New Roman", 20))
.setColor(color(0xffffff00))
.setPosition(155, 35);
I = cp5.addTextlabel("Impuls")
.setText("2")
.setPosition(155, 35)
.setFont(createFont("Times New Roman", 20))
.setColor(color(0xffffff00))
.moveTo("okno2");
int w = 99;
int h = 25;
button = new ImageButton(112, 137, w, h,
new PImage[]{
loadImage("0.png"), // off
loadImage("1.png"), // 10
loadImage("2.png"), // 20
loadImage("3.png"), // 30
loadImage("4.png"), // 40
loadImage("5.png"), // 50
loadImage("6.png"), // 60
});
}
void draw() {
background(0);
button.draw();
}
void mousePressed() {
button.mousePressed(mouseX, mouseY);
println(button.min);
}
PImage getImage(int w, int h, int c) {
PImage img = createImage(w, h, RGB);
java.util.Arrays.fill(img.pixels, c);
img.updatePixels();
return img;
}
class ImageButton {
int min = 0;
PImage[] stateImages;
int stateIndex;
int x, y;
int w, h;
String label = "ВЫКЛ";
ImageButton(int x, int y, int w, int h, PImage[] stateImages) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.stateImages = stateImages;
}
void mousePressed(int mx, int my) {
boolean isOver = ((mx >= x && mx <= x + w) &&
(my >= y && my <= y + h) ); // check vertical
if (isOver) {
min += 10;
stateIndex++;
if (min>60) {
min = 0;
stateIndex = 0;
label = "ВЫКЛ";
} else {
label = min + " Мин";
}
}
}
void draw() {
if (stateImages != null && stateIndex < stateImages.length) {
image(stateImages[stateIndex], x, y, w, h);
} else {
println("error displaying button state image");
println("stateImages: ");
printArray(stateImages);
println("stateIndex: " + stateIndex);
}
}
答案1
得分: 2
帮助他人(包括自己)来帮助你:
- 保持代码整洁(删除不必要的内容,比如
getImage
之类的) - 格式化代码以便于阅读。我无法强调这一点的重要性。
为了帮助自己,确保你完全理解自己的代码:
- 阅读代码
- 在脑海中想象它的运行过程
- 运行代码并观察实际行为
- 理解你的心理模型与计算机实际执行之间的差异。
这将帮助你进行代码调试。此外,可以查看Kevin Workman的调试教程。
关于你的问题:按钮在draw()
中始终被渲染。
你只希望在第一个选项卡处于活动状态时才绘制它,因此:
- 获取第一个选项卡
- 检查它是否处于活动状态
- 如果是,渲染按钮
例如,不要使用button.draw()
,而要使用:
if(cp5.getTab("default").isActive()){
button.draw();
}
这将解决问题,但随着界面变得更复杂,你可能会希望根据选项卡对要绘制的内容进行分组。以下是如何为每个选项卡组织更多控件的想法:
- 在代码顶部添加一个全局变量来跟踪当前选项卡:
int currentTab = 1;
- 在
draw()
中调用displayTabs();
,而不是button.draw()
来处理每个选项卡的绘制(有关displayTabs()
的更多内容见下文) - 使用
controlEvent()
来更新currentTab
示例如下:
void controlEvent(ControlEvent event) {
// 仅当当前事件来自选项卡时更新当前选项卡
if(event.isTab()){
currentTab = event.getId();
}
}
这个思路是,当点击/更新任何ControlP5组件(控制器)时,controlEvent
将被触发。如果是一个选项卡,你可以通过更新currentTab
来在draw()
中知道要绘制哪个内容,使用displayTabs()
来实现:
void displayTabs(){
switch(currentTab){
case 1:
displayTab1();
break;
case 2:
displayTab2();
break;
}
}
void displayTab1(){
button.draw();
}
void displayTab2(){
// 仅渲染选项卡2的内容
}
因此,有一个switch
语句,根据currentTab
的值调用一个函数或另一个函数。这样做的好处在于,将来可以轻松地为另一个选项卡复制另一个case
,每个选项卡的内容都被整齐地分隔出来。
英文:
Help others (including myself) help you:
- keep the code tidy (remove anything that is unnecessary, like the
getImage
for example) - format the code so it's easy to read. I can't stress this enough.
To help yourself always make sure you understand all your code completely:
- read it
- imagine in your head how it would run
- run it and observe the actual behaviour
- understand what was different between your mental model and what the computer did.
This will help you debug code in general. Also checkout Kevin Workman's Debugging tutorial.
Regarding your issue: the button is rendered all the time in draw()
.
You want to only draw it when the first tab is active hence:
- get the first tab
- check if it's active
- if so, render the button
e.g instead of button.draw()
you'd use:
if(cp5.getTab("default").isActive()){
button.draw();
}
That will do the trick, but as you interface gets more complex, you may want group what's being drawn per tab. Here's an idea on how to organise for a UI with more controls per tab:
- add a global variable (at the top of your code) to keep track of the current tab:
int currentTab = 1;
- call
displayTabs();
indraw()
instead ofbutton.draw()
to handle per tab drawing. (More aboutdisplayTabs()
bellow) controlEvent()
to update thecurrentTab
Like so:
void controlEvent(ControlEvent event) {
// update current tab only if the current event comes from a tab (and not other controllers)
if(event.isTab()){
currentTab = event.getId();
}
}
The idea is controlEvent
will get triggered when any ControlP5 component (controller) is clicked/updated. If it's a tab you can update currentTab
to know in draw()
which content to draw()
using displayTabs()
:
void displayTabs(){
switch(currentTab){
case 1:
displayTab1();
break;
case 2:
displayTab2();
break;
}
}
void displayTab1(){
button.draw();
}
void displayTab2(){
// render stuff for tab 2 only
}
So there's one switch with calls one function or another depending on the currentTab
value. The advantage of doing things this was is that you can easily replicate another case
for another tab in the future and each tab content is neatly compartmentalised.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论