Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Solved] Button Class | Problem with Method to execute when clicked  (Read 2082 times)

0 Members and 1 Guest are viewing this topic.

ThatBit

  • Newbie
  • *
  • Posts: 3
    • View Profile
Hi ,
I'm new to C++ and i am working on a Simple Game.
I have coded a Button Class but now i got Problems with it because i want to give the Button a Method to execute when it is clicked.
Like this:
button.setExecuteMethod( ExecuteMethod );

I found an Artikel about  std::function's but i isnt working for me.  :-\
Hope you can help me  ;)

Here is my Code (sry it is not that good):

Button.hpp :
#ifndef BUTTON_HPP
#define BUTTON_HPP

//Includes
#include <SFML/Graphics.hpp>
#include <string>
#include <functional>

//Button Class
class Button
{
    public:
        Button();
        Button(int posx , int posy , float sizex , float sizey , std::string text);
        virtual ~Button();
        void initialize(int posx , int posy , float sizex , float sizey , std::string text);

        void draw(sf::RenderWindow &window);
        void update(sf::RenderWindow& window , sf::Event event);

        //Setter
        void setPosition(float x , float y);
        void setString(std::string text);
        void setExecuter(std::function<void()> executer);
        //Getter
        sf::Vector2f getPosition(){return bpos;}
        sf::Vector2f getSize(){return bsize;}
    protected:
    private:
        //Positions
        sf::Vector2f bpos;
        sf::Vector2f bsize;
        sf::Vector2i mpos;

        //Shape
        sf::RectangleShape shape;

        //Text
        sf::Font font;
        sf::Text btext;

        std::function<void()> execute;

};

#endif // BUTTON_HPP
 

Button.cpp:
#include "ui/Button.hpp"

Button::Button()
{

}

Button::Button(int posx ,  int posy , float sizex , float sizey,std::string text)
{
    //ctor
    initialize(posx,posy,sizex,sizey,text);
}

Button::~Button()
{

}

void Button::initialize(int posx , int posy , float sizex , float sizey , std::string text)
{
    shape.setOutlineColor(sf::Color::Yellow);
    shape.setFillColor(sf::Color::Red);

    if(posx >= 0 && posy >= 0)
    {
        bpos.x = posx;
        bpos.y = posy;
        shape.setPosition(bpos);
    }
    if(sizex >= 0 && sizey >= 0)
    {
        bsize.x = sizex;
        bsize.y = sizey;
        shape.setSize(bsize);
    }
    font.loadFromFile("res/sansation.ttf");
    btext.setFont(font);
    btext.setPosition(bpos.x+10,bpos.y+10);
    btext.setCharacterSize(20);
    btext.setString(text);
}

void Button::update(sf::RenderWindow& window , sf::Event event)
{
    mpos = sf::Mouse::getPosition(window); //Get Position relativ to the window


    if(mpos.x >= bpos.x && mpos.y >= bpos.y && mpos.x <= (bsize.x + bpos.x) && mpos.y <= (bsize.y + bpos.y)) //Mouse Over
    {
        shape.setOutlineThickness(2);
        btext.setColor(sf::Color::Yellow);
    }else                           //Mouse not Over
    {
        shape.setOutlineThickness(0);
        btext.setColor(sf::Color::White);
    }
    if(event.type == sf::Event::EventType::MouseButtonReleased)
    {
        if(event.mouseButton.button == sf::Mouse::Left)
        {
            execute();
        }
    }

}
void Button::draw(sf::RenderWindow& window)
{
    window.draw(shape);
    window.draw(btext);
}

void Button::setPosition(float x , float y)
{
    shape.setPosition(x,y);
    btext.setPosition(x+10,y+10);
}

void Button::setExecuter(std::function<void()> executer)
{
    this->execute = executer;
}
 

« Last Edit: December 07, 2013, 11:22:33 pm by ThatBit »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Button Class | Problem with Method to execute when clicked
« Reply #1 on: December 07, 2013, 10:53:03 pm »
Since you don't say anything about your problem, we'll have to waste some time trying to guess ;)

If it's a compiler error, it's probably because you're not using a C++11 compiler.

If the function is not executed, then it's probably not related to std::function; your code looks ok. You should check your algorithm first: for example, the function will always be executed when you release the mouse button, because you don't test if the mouse cursor is over the button or not.
Laurent Gomila - SFML developer

ThatBit

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Button Class | Problem with Method to execute when clicked
« Reply #2 on: December 07, 2013, 10:58:27 pm »
Ohh sry i forgot to explain my Error :D

It compiles all well but when i click on the Button the program crashes and I get this Error Message:

terminate called after throwing an instance of 'std::bad_function_call'
  what():  std::exception

Process returned -1 (0xFFFFFFFF)   execution time : 1.301 s

Edit:  Fixed it. I put the MouseButtonReleased Event check inside the MouseOver like you said it. Now the Error is gone. Thank you :)

But now it executes the Method more than one time. Can you give me an Example how to prozess a Mouse click right ?

« Last Edit: December 07, 2013, 11:04:11 pm by ThatBit »

ThatBit

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Button Class | Problem with Method to execute when clicked
« Reply #3 on: December 07, 2013, 11:21:54 pm »
Since you don't say anything about your problem, we'll have to waste some time trying to guess ;)

If it's a compiler error, it's probably because you're not using a C++11 compiler.

If the function is not executed, then it's probably not related to std::function; your code looks ok. You should check your algorithm first: for example, the function will always be executed when you release the mouse button, because you don't test if the mouse cursor is over the button or not.

Now it all works! Thanks! :)

For all here is the Mouse Input Process:
  bool mouseDown;
      if(event.type == sf::Event::EventType::MouseButtonPressed)
        {
            if(event.mouseButton.button == sf::Mouse::Left)
            {
                mouseDown = true;
            }
        }
        if(event.type == sf::Event::EventType::MouseButtonReleased)
        {
            if(event.mouseButton.button == sf::Mouse::Left)
            {
                if(mouseDown)
                {
                    mouseDown = false;
                    execute();
                }
            }
        }