Как очистить холст и кнопки (и их функциональность) после нажатия кнопки?

#processing

#обработка

Вопрос:

Я пытаюсь создать программу визуализации данных, из которой, когда пользователь нажимает на одну из кнопок главного экрана, они переходят к визуализации данных. Я не могу понять, как это сделать правильно. Пока я могу вроде как очистить холст, но кнопки все еще функционируют, даже если вы их не видите. Я хочу иметь возможность нажать одну из кнопок главного экрана, чтобы перевести пользователя на совершенно новую страницу (это все еще продолжается, поэтому единственная кнопка, с которой я начал это делать, — ‘pieChartButton’).

Вот мой код обработки на данный момент:

 Button pieChartButton, bubbleGraphButton, scatterGraphButton, homeButton; //button to be used
Button homeButtonBar, PCDescriptionBox, BGDescriptionBox, SGDescriptionBox; //design features that use same attributes as buttons
int buttonClicked = 1; //check to see if button works

void setup() {
  size(1200,800);
  pixelDensity(2); //function to make the render of the program Apple Retina displays and Windows High-DPI displays look smoother and less pixelated
  smooth();
  
  //creating the button object
  pieChartButton = new Button("Pie Chart", 5, 5, 590, 340);
  bubbleGraphButton = new Button("Bubble Graph", 5, 355, 590, 340);
  scatterGraphButton = new Button("Scatter Graph", 605, 5, 590, 340);
  
  //design features
  PCDescriptionBox = new Button("Pie chart will show this and that and other stuff n test", 605, 355, 590, 340);
  BGDescriptionBox = new Button("Bubble graph with nice bubbles, mucho colours and information with useful stuff", 605, 355, 590, 340);
  SGDescriptionBox = new Button("Scatter Graph n n n nThis Scatter represents the data about video game publishers and what genres they publish", 605, 355, 590, 340);
}

void draw() {
  //DRAWING BUTTONS   DISPLAY DESCRIPTION 
  //if mouse is hovering over button, button title amp; description will appear, but now a square will appear to cheack it works
  if (pieChartButton.mouseHoverOver()){
    fill(225,0,0);
    rect(700, 400, 50, 50);
    PCDescriptionBox.drawDesign(); //display of what is in the pie chart window
  } else if (bubbleGraphButton.mouseHoverOver()){
      fill(0,0,225);
      rect(700, 400, 50, 50);
      BGDescriptionBox.drawDesign(); //show description for bubble graph window
  } else if (scatterGraphButton.mouseHoverOver()){
    fill(0,225,0);
    rect(700, 400, 50, 50);
    SGDescriptionBox.drawDesign(); //show description for scattter graph window
  } else{
    homePage();
  }
}

//mouse clicked on button
void mousePressed(){
   if (pieChartButton.mouseHoverOver()){   //check if pie chart button clicked
     println("Clicked PC: "  buttonClicked  );
     pieChartPage();
   } else if (bubbleGraphButton.mouseHoverOver()) {  //check if bubble graph button clicked
     println("Clicked BG: "  buttonClicked  );
   } else if (scatterGraphButton.mouseHoverOver()){ //checks if scatter graph button clicked
     println("Clicked SG: "  buttonClicked  );
   } else {
     homePage();
   }
}


//The different pages of the program
//main home screen page
void homePage(){
  background(225);
  //noStroke();
  //fill(255);
  //rect(0, 725, 1200, 100);
  pieChartButton.Draw();  //draw Pie chart button in home screen
  bubbleGraphButton.Draw();  //draw bubble graph button in home screen
  scatterGraphButton.Draw(); //draw scatter graph button in home screen
  homeButtonBar = new Button("", 5, 710, 1190, 200);
  homeButtonBar.Draw();
}

void pieChartPage(){
  background(175,0,225);
  homeButtonBar = new Button("", 5, 710, 1190, 200);
  homeButtonBar.Draw(); 
}
 

Класс кнопки для кода:

  class Button {

 String label;
 float x, y, w, h; //top left corner x position, top left corner y position, button width, button height

 Button(String labelButton, float xpos, float ypos, float widthButton, float heightButton){
   label=labelButton;
   x=xpos;
   y=ypos;
   w=widthButton;
   h=heightButton;
 }

 void Draw(){
   fill(170);
   stroke(170);
   rect(x, y, w, h, 40);
   textAlign(CENTER, CENTER);
   fill(0);
   text(label, x (w/2), y (h/2));
 }

  void drawDesign(){
   fill(225);
   stroke(170);
   rect(x, y, w, h, 40);
   textAlign(LEFT, BASELINE);
   fill(0);
   text(label, x 20, y 40);
 }

 boolean mouseHoverOver(){
   if (mouseX>x amp;amp; mouseX<(x w) amp;amp; mouseY>y amp;amp; mouseY<(y h)){ //if mouse within button, return true, if not return false
     return true;
   }
   return false;
 }

}
 

Любая помощь будет оценена, спасибо.

Ответ №1:

Приятным шаблоном проектирования, который мог бы помочь вам решить эту проблему, был бы конечный автомат. FSM позволяет определить контекст, который может привести к другому контексту, и ограничить некоторые действия некоторым контекстом. Хорошим примером этого является Super Mario Bros: когда он маленький, получение волшебного гриба превратит его в Супер Марио. Когда он Супер, получение цветка превратит его в Огненного Марио. Но пока маленький, получение цветка только превратит его в Супер Марио, а не в Огонь Марио. Это потому, что у каждого из этих состояний есть правила, и он не может просто переходить от одного к другому, не обращая на них внимания.

Вот приблизительная схема для FSM, которая может напоминать то, что вы делаете: у вас есть меню, и, находясь в меню, вы можете использовать его, но когда вы выбираете опцию, вы меняете состояние на что-то другое и получаете разные опции и визуальные эффекты. Я предполагаю, что вы также можете вернуться из этого графика в меню и выбрать что-то еще.

Конечные состояния

Я покажу вам, как реализовать это в вашем коде.


Меню

в вашей ситуации меню является ключом к тому, чтобы все остальное встало на свои места. В бизнес-правилах будет указано, что пользователь видит и может использовать 3 кнопки.

Сначала мы добавим глобальную переменную:

 int state = 1;
 

1 будет означать «Меню», так как в схеме это STATE 1 . В draw() методе мы установим переключатель, который будет решать, что рисовать:

 void draw() {
  switch(state) {
  case 2:
    // pie chart
    break;
  case 3:
    // pie chart
    break;
  case 4:
    // pie chart
    break;
  default:
    // menu
    // the default case means "everything else" and in our case it will be the menu so you cannot have an impossible case
    drawMenu();
  }
}
 

Как насчет кода, который был ранее в draw() методе? Мы создадим void menu() метод и поместим его туда. Это тот, который вызывается, когда вы находитесь в состоянии «меню», поэтому, пока вы находитесь в меню, кнопки будут видны и доступны для использования.

 void drawMenu() {
  // DRAWING BUTTONS
  homePage();

  // show graph previews
  if (pieChartButton.mouseHoverOver()) {
    fill(225, 0, 0);
    rect(700, 400, 50, 50);
    PCDescriptionBox.drawDesign(); //display of what is in the pie chart window
  } else if (bubbleGraphButton.mouseHoverOver()) {
    fill(0, 0, 225);
    rect(700, 400, 50, 50);
    BGDescriptionBox.drawDesign(); //show description for bubble graph window
  } else if (scatterGraphButton.mouseHoverOver()) {
    fill(0, 225, 0);
    rect(700, 400, 50, 50);
    SGDescriptionBox.drawDesign(); //show description for scattter graph window
  }
}
 

Теперь мы добавим, что нажатие кнопки также соответствующим образом изменит состояние. Для этого мы внедрим state переключатель в mousePressed() метод. Это тот же принцип, что и то, что мы только что сделали. Обратите внимание, что я удалил вызов «Домашняя страница» и добавил state изменение после того, как щелчок выбрал одно из других состояний:

 //mouse clicked on button
void mousePressed() {
  switch(state) {
  case 2:
    // pie chart
    break;
  case 3:
    // bubble graph
    break;
  case 4:
    // scatter graph
    break;
  default:
    // menu
    ClickMenu();
  }
}

void ClickMenu() {
  if (pieChartButton.mouseHoverOver()) {   //check if pie chart button clicked
    println("Clicked PC: "  buttonClicked  );
    pieChartPage();
    state = 2;
  } else if (bubbleGraphButton.mouseHoverOver()) {  //check if bubble graph button clicked
    println("Clicked BG: "  buttonClicked  );
    state = 3;
  } else if (scatterGraphButton.mouseHoverOver()) { //checks if scatter graph button clicked
    println("Clicked SG: "  buttonClicked  );
    state = 4;
  }
}
 

Я вижу, что у вас есть pieChartPage() способ нарисовать страницу круговой диаграммы (отличное соглашение об именах, чтобы сделать все очевидным, кстати). Это то, что должно быть включено в переключатель draw() метода. Теперь, чтобы вы могли протестировать игру с ним, я добавлю, что при случайном нажатии на странице круговой диаграммы вы возвращаетесь на страницу меню, добавив state изменение в mousePressed() методе.

Кроме того, обратите внимание, что если вы выберете любой другой график, кроме круговой диаграммы, вы застряли там навсегда (и кнопки теперь не будут работать). Это потому, что у нас ничего не запрограммировано для этих состояний. Вот полный код для этого примера, а остальное я оставляю вам:

 Button pieChartButton, bubbleGraphButton, scatterGraphButton, homeButton; //button to be used
Button homeButtonBar, PCDescriptionBox, BGDescriptionBox, SGDescriptionBox; //design features that use same attributes as buttons
int buttonClicked = 1; //check to see if button works
int state = 0;

void setup() {
  size(1200, 800);
  pixelDensity(2); //function to make the render of the program Apple Retina displays and Windows High-DPI displays look smoother and less pixelated
  smooth();

  //creating the button object
  pieChartButton = new Button("Pie Chart", 5, 5, 590, 340);
  bubbleGraphButton = new Button("Bubble Graph", 5, 355, 590, 340);
  scatterGraphButton = new Button("Scatter Graph", 605, 5, 590, 340);

  //design features
  PCDescriptionBox = new Button("Pie chart will show this and that and other stuff n test", 605, 355, 590, 340);
  BGDescriptionBox = new Button("Bubble graph with nice bubbles, mucho colours and information with useful stuff", 605, 355, 590, 340);
  SGDescriptionBox = new Button("Scatter Graph n n n nThis Scatter represents the data about video game publishers and what genres they publish", 605, 355, 590, 340);
}

void draw() {
  switch(state) {
  case 2:
    // pie chart
    pieChartPage();
    break;
  case 3:
    // pie chart
    break;
  case 4:
    // pie chart
    break;
  default:
    // menu
    // the default case means "everything else" and in our case it will be the menu so you cannot have an impossible case
    drawMenu();
  }
}

void drawMenu() {
  // DRAWING BUTTONS
  homePage();

  // show graph previews
  if (pieChartButton.mouseHoverOver()) {
    fill(225, 0, 0);
    rect(700, 400, 50, 50);
    PCDescriptionBox.drawDesign(); //display of what is in the pie chart window
  } else if (bubbleGraphButton.mouseHoverOver()) {
    fill(0, 0, 225);
    rect(700, 400, 50, 50);
    BGDescriptionBox.drawDesign(); //show description for bubble graph window
  } else if (scatterGraphButton.mouseHoverOver()) {
    fill(0, 225, 0);
    rect(700, 400, 50, 50);
    SGDescriptionBox.drawDesign(); //show description for scattter graph window
  } else {
    homePage();
  }
}

//mouse clicked on button
void mousePressed() {
  switch(state) {
  case 2:
    // pie chart
    println("Going back to state 1!");
    state = 1;
    break;
  case 3:
    // pie chart
    break;
  case 4:
    // pie chart
    break;
  default:
    // menu
    ClickMenu();
  }
}

void ClickMenu() {
  if (pieChartButton.mouseHoverOver()) {   //check if pie chart button clicked
    println("Clicked PC: "  buttonClicked  );
    state = 2;
  } else if (bubbleGraphButton.mouseHoverOver()) {  //check if bubble graph button clicked
    println("Clicked BG: "  buttonClicked  );
    state = 3;
  } else if (scatterGraphButton.mouseHoverOver()) { //checks if scatter graph button clicked
    println("Clicked SG: "  buttonClicked  );
    state = 4;
  }
}

//The different pages of the program
//main home screen page
void homePage() {
  background(225);
  //noStroke();
  //fill(255);
  //rect(0, 725, 1200, 100);
  pieChartButton.Draw();  //draw Pie chart button in home screen
  bubbleGraphButton.Draw();  //draw bubble graph button in home screen
  scatterGraphButton.Draw(); //draw scatter graph button in home screen
  homeButtonBar = new Button("", 5, 710, 1190, 200);
  homeButtonBar.Draw();
}

void pieChartPage() {
  background(175, 0, 225);
  homeButtonBar = new Button("PIE CHART BUTTON", 5, 710, 1190, 200);
  homeButtonBar.Draw();
}
 

Не стесняйтесь обращаться, если есть что-то, чего вы не понимаете. Получайте удовольствие!

Комментарии:

1. вау, я не могу отблагодарить вас за вашу помощь. Я очень ценю это, а также за подробное объяснение ваших реализаций. Большое вам спасибо

2. Рад, что вам понравилось! Сегодня утром я исправил пару ошибок копирования и вставки. Не забудьте пометить его как решение, если оно решает вашу проблему, чтобы будущим пользователям с аналогичными проблемами было легче найти его при поиске по сайту.

3. как бы я добавил кнопку «Домой», чтобы, когда пользователь находится на другой странице, он мог вернуться в главное меню. Как бы я изменил переключатель (состояние) {} по умолчанию: в draw(), чтобы его домашняя кнопка переходила в главное меню? Спасибо

4. Я бы создал DrawMenuButton() метод, который отображает только кнопку «Назад» или «Меню», и добавлял бы ее к draw() переключателю в каждом случае, когда вы этого хотите (возможно, все они, кроме default ). Затем я бы добавил ClickMenuButton() метод для добавления в mouseClicked() swich в тех же случаях. Если вы написали опубликованный вами код, вы должны быть в состоянии адаптировать его, поскольку он может быть вдохновлен тем, что вы уже сделали (если нет, найдите время, чтобы прочитать свой код, вы можете вдохновиться им).

5. Отличный ответ ( 1). Недавно мне понравились ваши подробные ответы.