Bonjour,
J'ai essayé de créer une classe pour les boutons dans une GUI. Mais j'ai quelques soucis avec std::function qu'on ma conseillé d'utiliser.
Tout d'abord voici le log du compilo :
||=== Build: Debug in MWindow (compiler: GNU GCC Compiler 4.7.1) ===|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional||In instantiation of 'static void std::_Function_handler<void(_ArgTypes ...), _Member _Class::*>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Class = TWindow; _Member = void(); _ArgTypes = {}]':|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|2298|required from 'std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = void (TWindow::*)(); _Res = void; _ArgTypes = {}; typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function<void()>::_Useless]'|
C:\Users\Jules\Desktop\Documents\C++\Projets SFML\MWindow\main.cpp|13|required from here|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|2013|error: no match for call to '(std::_Mem_fn<void (TWindow::*)()>) ()'|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|525|note: candidates are:|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|548|note: _Res std::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = void; _Class = TWindow; _ArgTypes = {}]|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|548|note: candidate expects 1 argument, 0 provided|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|553|note: _Res std::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = void; _Class = TWindow; _ArgTypes = {}]|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|553|note: candidate expects 1 argument, 0 provided|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|559|note: template<class _Tp> _Res std::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Tp&, _ArgTypes ...) const [with _Tp = _Tp; _Res = void; _Class = TWindow; _ArgTypes = {}]|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|559|note: template argument deduction/substitution failed:|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|2013|note: candidate expects 1 argument, 0 provided|
||=== Build failed: 1 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|
Et le code source :
Code MWindow.h : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 #ifndef MWINDOW_H #define MWINDOW_H #include <SFML/Graphics.hpp> #include <functional> #include <vector> class MWindow; class Button : public sf::Sprite { friend class MWindow; public: Button(std::string const& adress, std::string const& adressO=std::string(), std::string const& adressL=std::string(), std::string const& adressD=std::string()); virtual ~Button(); MWindow* getParent(); // Returns 'parent' member. virtual void setEnabled(bool yay); // Sets the 'enabled' value to yay and changes de texture in consequences. An hidden button cannot be enabled. bool getEnabled(); // Returns the 'enabled' member value virtual void setHidden(bool hide); // Sets the 'hidden' member to hide. If true, texture is set to 'texture', else to an empty texture. // An hidden button is also disabled. Unhidde a button automatically re-enables it. bool getHidden(); // Returns the 'hidden' member value void changeTexture(std::string const& adress); // texture.loadFromFile(adress); void changeTextureOver(std::string const& adress=std::string()); // Give it an empty string and textureOver will be set with 'texture' void changeTextureLeaned(std::string const& adress=std::string()); // Give it an empty string and textureLeaned will be set with 'texture' void changeTextureDisabled(std::string const& adress=std::string()); // Give it an empty string and textureDisabled will be set with 'texture' protected: void checkClicked(); // Uses the sf::Event 'event' member of parent to verify if the mouse is over the button and if the user clicks on MWindow *parent; sf::Texture texture, textureOver, textureLeaned, textureDisabled; bool enabled, mouseOver, leaned, hidden, triggered; int ID; }; /////////////////////////////////////// MWindow /////////////////////////////////////// class MWindow { friend class Button; public: MWindow(int x = 800, int y = 600, std::string const& title = "Main Window", bool deletebuttons = true, sf::ContextSettings const& settings = sf::ContextSettings()); /* Arguments : * 'title' is simply the title of the window. * 'deletebuttons' : if true, the buttons in the vector 'buttons' will be deleted in the destructor. * 'x' ans 'y' are respectively the width and the height of the window */ MWindow(sf::RenderWindow *windowPtr, bool deletebuttons = true); virtual ~MWindow(); virtual void startEventLoop(); bool addButton(Button *button, std::function<void()> &func); // Returns true if the button is successfully added, false if the button was already in the window or if the button already has a parent. bool removeButton(Button *button); // Returns true if the button is successfully removed from the window, false if the button was not in the window. // Note that this function does NOT delete the button. bool removeButton(int index); // Overload of removeButton(). Remove the Button at the 'index' position. Return true if successful, false if the 'index' position does not exist. bool changeFunction(int index, std::function<void()> &func); // Change the function pointer at the index 'index' of 'functions'. Returns true if successful, false if the 'index' position does not exist. protected: virtual void update(); // clear-draw-display function virtual void checkButtons(); // Checks if the buttons are clicked, each one in its own thread. The threads are hold in the checkButtons() function itself. sf::RenderWindow *window; sf::Thread checkBtnsThrd; std::vector<Button*> buttons; std::vector<std::function<void()>> functions; bool checkBtns, deleteButtons; sf::Event event; }; #endif // MWINDOW_H
Code MWindow.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161 #include "MWindow.h" MWindow::MWindow(int x, int y, std::string const& title, bool deletebuttons, ContextSettings const& settings) : \ window(new sf::RenderWindow(sf::VideoMode(x,y), title, sf::Style::Titlebar | sf::Style::Close, settings)), \ checkBtnsThrd(&MWindow::checkButtons, this), buttons(), functions(), buttons(), checkBtns(false), deleteButtons(deletebuttons) { checkBtns=true; checkBtnsThrd.launch(); } MWindow::MWindow(sf::RenderWindow *windowPtr, bool deletebuttons) : window(windowPtr), checkBtns(&MWindow::checkButtons, this), buttons(), deleteButtons(deletebuttons) { checkBtns=true; checkBtnsThrd.launch(); } MWindow::~MWindow() { window->close(); if(deleteButtons) { for(int i(0) ; i < (int)buttons.size() ; i++) delete buttons[i]; } else { for(int i(0) ; i < (int)buttons.size() ; i++) if(buttons[i] != nullptr) buttons[i].ID=-1; } delete window; } void MWindow::startEventLoop() { while(window->isOpen()) { update(); while(window->pollEvent(event)) { if(event.type == sf::Event::MouseButtonPressed || event.type == sf::Event::MouseButtonReleased || event.type == sf::Event::MouseMoved) { for(int i(0) ; i < (int)buttons.size() ; i++) if(buttons[i] != nullptr && buttons[i]->getEnabled()) buttons[i]->checkClicked(event); } } } } bool MWindow::addButton(Button *button, std::function<void()> &func) { if(button->parent != nullptr) return false; for(int i(0) ; i < (int)buttons.size() ; i++) if(buttons[i] == button) return false; if(!buttons.empty()) { for(int i(0) ; i < (int)buttons.size() ; i++) { if(buttons[i] == nullptr) { buttons[i]=button; button->ID=i; button->parent=this; functions[i]=func; return true; } } } buttons.push_back(button); button->ID=buttons.size()-1; button->parent=this; functions.push_back(func); return true; } bool MWindow::removeButton(Button *button) { checkBtns=false; for(int i(0) ; i < (int)buttons.size() ; i++) { if(buttons[i] == button) { buttons[i]->parent=nullptr; buttons[i] = nullptr; functions.at(index)=nullptr; checkBtns=true; checkBtnsThrd.launch(); return true; } } checkBtns=true; checkBtnsThrd.launch(); return false; } bool MWindow::removeButton(int index) { checkBtns=false; try { buttons.at(index)->parent=nullptr; buttons.at(index) = nullptr; functions.at(index) = nullptr; } catch (std::out_of_range const& exc) { checkBtns=true; checkBtnsThrd.launch(); return false; } checkBtns=true; checkBtnsThrd.launch(); return true; } bool changeFunction(int index, std::function<void()> &func) { checkBtns=false; try { functions.at(index) = func; } catch (std::out_of_range const& exc) { checkBtns=true; checkBtnsThrd.launch(); return false; } checkBtns=true; checkBtnsThrd.launch(); return true; } void MWindow::update() { window->clear(); for(int i(0) ; i < (int)buttons.size(); i++) if(buttons[i]!=nullptr) window->draw(*buttons[i]); window->display(); } void MWindow::checkButtons() { int i(-1); while(checkBtns) { i++; if(i == buttons.size()) i=0; buttons[i]->checkClicked(); } }
Code Button.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121 #include "MWindow.h" Button::Button(std::string const& adress, std::string const& adressO, std::string const& adressL, std::string const& adressD) : \ parent(nullptr), texture(), textureOver(), textureLeaned(), textureDisabled(), \ enabled(false), mouseOver(false), leaned(false), hidden(false), ID(-1) { changeTexture(adress); changeTextureOver(adressO); changeTextureLeaned(adressL); changeTextureDisabled(adressD); } Button::~Button() { } MWindow* Button::getParent() { return parent; } void Button::setEnabled(bool yay) { if((enabled && yay) || hidden) { return; } else if(yay) { enabled=true; } else { enabled=false; setTexture(textureDisabled); } } bool Button::getEnabled() { return enabled; } void Button::setHidden(bool hide) { if(hide) { setEnabled(false); setTexture(sf::Texture()); hidden=true; } else { hidden=false; setEnabled(true); } } bool Button::getHidden() { return hidden; } void Button::changeTexture(std::string const& adress) { texture.loadFromFile(adress); } void Button::changeTextureOver(std::string const& adress) { textureOver.loadFromFile(adress); } void Button::changeTextureLeaned(std::string const& adress) { textureLeaned.loadFromFile(adress); } void Button::changeTextureDisabled(std::string const& adress) { textureDisabled.loadFromFile(adress); } void Button::checkClicked() { if(!enabled) return; if(parent->event.type == sf::Event::MouseMoved) { if(getGlobalBounds().contains(sf::Vector2<float>(parent->event.mouseMove.x, parent->event.mouseMove.y))) {//if the mouse is in the button... mouseOver=true; setTexture(textureOver); } else { mouseOver=false; setTexture(texture); } } else if(parent->event.type == sf::Event::MouseButtonPressed && parent->event.mouseButton.button == sf::Mouse::Right && mouseOver) { leaned=true; setTexture(textureLeaned); } else if(parent->event.type == sf::Event::MouseButtonReleased && parent->event.mouseButton.button == sf::Mouse::Right && leaned) { if(getGlobalBounds().contains(sf::Vector2<float>(parent->event.mouseButton.x, parent->event.mouseButton.y))) { setTexture(textureOver); parent->functions[ID](); } else { setTexture(texture); mouseOver=false; } leaned=false; } }
Merci d'avance pour vos éclarcissements.
Partager