I am having a problem accessing an object or its methods in fltk.
I have a Class named MyWindow which is a child class of Fl_Window.
so basically i would like to use an object which is either declared int the main or Mywindow in private section. My problem is that I can't use it that way. It only lets me to use the object if it is declared global. Can i somehow put it on the heap like this: Classname *pointer = new Classname(); ? IF i can where do I do that?
How would the callback function work if i need that object or its functions in the callback?
Should i use a pointer to it in the callback arguements?
lets say i want to click on the button and I need it to do something with the object and change a value.
lots of questions I know, I am really lost.
Can someone just point me to the right direction? Thank you! :)
Simple case for passing data to the GUI
class MyData
{
// The data model
};
class MyWindow: public FL_Window
{
MyData* m_data;
public:
void Data(MyData* data) { m_data = data; }
...
};
int main()
{
MyWindow gui;
MyData data;
// Tell the gui about the data
gui.Data(data);
...
// Setup the dialog
gui.begin();
...
gui.end();
gui.show();
return FL::run();
}
For the callbacks, do it in two stages
class NeedingACallback
{
public:
void Setup()
{
...
FL_xxx* w = new FL_xxx(xpos, ypos, wid, hgt, name);
...
// v Pass the instance to the static
w->callback(_EventCB, this);
}
// The callback
static void _EventCB(FL_Widget* w, void* client)
{
// Convert the void* back to the instance
NeedingACallback* self = reinterpret_cast<NeedingACallback*>(client);
self->EventCB();
}
// Make life simple so you don't have to put self-> in front of
// all the instance data accessed
void EventCB()
{
// Callback for this instance of the class
}
};
EDIT It sounds like you're having multiple instances of data. An alternative technique is to have data as a reference. This must be done in the constructor. This way, m_data and the data in main both refer to the same area of memory.
class MyWindow: public FL_Window
{
MyData& m_data;
public:
MyWindow(int wid, int hgt, MyData& data, const char* title=0)
: FL_Window(wid,hgt,title)
, m_data(data)
{
...
}
};
int main()
{
MyData data;
MyWindow gui(100, 100, data, "Call me Mr");
...
// Setup the dialog
gui.begin();
...
gui.end();
gui.show();
return FL::run();
}
Related
I am creating a spirograph application, and have a simple GUI class, which produces and manages buttons - you can call this functions with a custom function pointer upon clicking on them.
I also have an Engine class, which manages the drawing of my spirograph, and the GUI buttons.
I would like to create a button that has a pointer to a member function from within the engine class, but I keep getting an error.
The error is coming when I try to create a button with a function pointer from the Engine class.
Here is the problem in a nutshell, as suggested by Frank in the comments (thank you)
class Engine;
typedef void(Engine::*enginefunc)(void);
class Engine
{
void cb();
void register_callback(enginefunc ptr);
void foo() {
register_callback(cb);
}
};
Here is my engine class:
Engine.h
class Engine : public GUI
{
private:
//....
public:
Engine(sf::Vector2f* mousepos);
//...
//...inherited a function from GUI called addbutton.
};
Engine::Engine(sf::Vector2f* mousepos)
:GUI(mousepos)
{
//THIS IS THE LINE WHICH PRODUCES THE ERROR. I AM TRYING TO PASS THE CHANGE POINT FUNCTION INTO THE GUI BUTTON.
addbutton(sf::Vector2f{ 100,50 }, sf::Vector2f{ 200,100 }, "Button", sf::Color::Red, sf::Color::Blue, changepoint);
}
Here is the GUI.h (Contains the addbutton function which is causing the error)
class Engine;
typedef void(Engine::* enginefunc)(void);
class GUI : public sf::Drawable
{
private:
//...
public:
GUI(sf::Vector2f* mousepos);
void addbutton(const sf::Vector2f& position, const sf::Vector2f& dimension, const std::string& text, sf::Color initcolor, sf::Color highlightcolor, enginefunc ptr);
//other member funcs..
};
Here is the GUI::addbutton function
void GUI::addbutton(const sf::Vector2f& pos, const sf::Vector2f& size, const std::string& text, sf::Color before, sf::Color after, enginefunc ptr)
{
buttons.emplace_back(pos, size, text, before, after, ptr);
}
So the addbutton function creates a GUIButton class, which stores the function ptr. When the button is clicked, that function pointer is called via std::invoke.
Here is my GUIButton.h
class Engine;
typedef void(Engine::*enginefunc)(void);
class GUIButton : public sf::RectangleShape
{
public:
GUIButton(const sf::Vector2f& position, const sf::Vector2f& size, const std::string& text, sf::Color initcolor, sf::Color highlightcolor, enginefunc ptr);
void action(Engine& e);
//other members...
private:
//other members...
enginefunc actionptr;
};
As you can see, the enginefunc GUIButton::actionptr is the function pointer which will be actioned when the button is pressed.
Here is the GUIButton::action() function which calls the function:
void GUIButton::action(Engine& e)
{
if (actionptr != nullptr)
{
std::invoke(actionptr, e);
}
}
I do not understand what I am doing wrong. I understand that a pointer to member function must be tied to a specific object, which is why I have taken in the Engine object as reference.
Any suggestions?
You should just use a std::function instead. In this case, best practices here would call for using a lambda to bind this.
The equivalent of your code:
class Engine;
typedef void(Engine::*enginefunc)(void);
class Engine
{
Engine();
void changepoint();
void addbutton(enginefunc ptr);
};
Engine::Engine() {
addbutton(changepoint);
}
Becomes:
class Engine
{
Engine();
void changepoint();
void addbutton(std::function<void()> ptr);
};
Engine::Engine() {
addbutton([this](){changepoint();});
}
I'm writing a basic GUI framework as a school project and I'm trying to create an object (think a button) that, when interacted with, will call a particular function.
To explain my setup simply, I have a button class and a window manager class. The window manager is instantiated once from main and many buttons are instantiated from the window manager, with all 3 being in separate files. Nothing should go in main.
I'm a bit of a C++ noob, but as far as I can see, it would be best to use function pointers for this. My idea is to instantiate my button object then to pass it a function pointer to a function that when called would edit another object.
Firstly, I presume that the best way to do this would be to have the functions be defined locally to the window manager otherwise I'd have trouble with access? I had wanted to initially not have them listed in the header to make things easier (with a view to creating a kind of drag and drop editor in the future).
Second, how would I pass (from the window manager) a pointer to a function (which would exist within the window manager) to an instance of a button object? I thought I'd be able to treat it similarly to any other variable and do something as:
Button btn1 = new Button();
btn1->SetText("Button 1");
btn1->SetOnClick(functionpointer);
But, after looking through various tutorials I don't quite understand how I'd implement this. For example, how do I even define somewhere to store the function pointer in my button class?
Would appreciate any insight, I think I've confused myself enough for one day.
EDIT: Seems I should add that my Button and WindowManager classes are in separate files and my entry point so to speak is an instance of WindowManager. All the setup of my GUI including assigning a function to a button would be done in the constructor of WindowManager.
Here is one approach by using function pointers. However using std::function makes the code more flexible. For example you can use lambda expressions.
To use std::function you can simply change the typedef to typedef std::function<void(Button*)> EventCallback; and add the include #include <functional>
#include <iostream>
class Button
{
public:
// Typedef of the event function signature
typedef void(*EventCallback)(Button* button);
Button() : onClick(nullptr) {}
// Set the function to call
void SetOnClick(EventCallback func) { onClick = func; }
// Call the function if exists
void OnClick() {
if (onClick)
onClick(this);
}
private:
// This stores the function pointer for the button
EventCallback onClick;
};
// just some example function that has the same signature as Button::EventCallback
void MyEventFunc(Button* button)
{
std::cout << "Triggered" << std::endl;
}
int main() {
Button button;
button.SetOnClick(&MyEventFunc);
button.OnClick();
return 0;
}
http://ideone.com/x5O49B
You can do it with pointer to member function like this (in this case Button has to know WindowManager);
class WindowManager
{
public:
typedef void (WindowManager::* TypeOnClickFunc)( void );
void anyfunction( void ) {}
};
class Button
{
public:
Button( WindowManager * wm ) :_windowmanager( wm ) {}
void SetOnClick( WindowManager::TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(_windowmanager->*_onclickfptr )( ); // indirect call WindowManager::anyfunction
}
private:
WindowManager *_windowmanager;
WindowManager::TypeOnClickFunc _onclickfptr;
};
WindowManager wm;
Button *btn1 = new Button( &wm );
btn1->SetOnClick( &WindowManager::anyfunction );
... or with pointer to static function like this ...
class WindowManager
{
public:
typedef void (*TypeOnClickFunc)( void );
static void anyfunction( void ) {}
};
class Button
{
public:
Button() {}
void SetOnClick( WindowManager::TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(*_onclickfptr )( ); // indirect call static WindowManager::anyfunction
}
private:
WindowManager::TypeOnClickFunc _onclickfptr;
};
Button *btn1 = new Button();
btn1->SetOnClick( &WindowManager::anyfunction );
... with typdef in Button instead of WindowManager ...
class WindowManager
{
public:
static void anyfunction( void ) {}
};
class Button
{
public:
typedef void (*TypeOnClickFunc)( void );
Button() {}
void SetOnClick( TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(*_onclickfptr )( ); // indirect call
}
private:
TypeOnClickFunc _onclickfptr;
};
Button *btn1 = new Button();
btn1->SetOnClick( &WindowManager::anyfunction );
I'm having trouble figuring out what to return to the user of my Manager class in order to express the fact that I own the resource (in my example a Window). I want to pass to the client an interface IWindow exposing only a limited set of methods from the actual Window implementation. What should I return a reference or a pointer? Better Manager class implementation?
class IWindow
{
public:
virtual ~IWindow(){}
virtual void setMember() = 0;
protected:
IWindow(){}
};
class Window : public IWindow
{
public:
Window(){}
virtual ~Window(){test_ = 0;}
virtual void setMember() final { test_++; }
private:
int test_ = 11;
};
class Manager
{
public:
Manager():window_{ std::make_unique<Window>() } {}
virtual ~Manager(){}
// ownership not obvious
IWindow* getWindowPtr() const { return window_.get(); }
// ownership clear but is this the right thing to do?
IWindow& getWindowRef() const { return *window_.get(); }
private:
std::unique_ptr<IWindow> window_ = nullptr;
};
int main(void)
{
Manager manager; // Owner of the window.
IWindow* iWindowPtr = manager.getWindowPtr(); // Client get's an interface pointer.
iWindowPtr->setMember(); // Call some method (only interface methods visible).
// Basically now he could delete the pointer and crash the Manager he has no idea that Manager owns this pointer
// delete iWindow;
// Crash when manager goes out of scope!
IWindow& iWindowRef = manager.getWindowRef(); // Client get's an interface ref.
iWindowRef.setMember(); // Call some method (only interface methods visible).
// Now client knows that he does not have ownership, but I'm returning a ref from a raw pointer...
return 0;
}
I am seeing new Window{} which is not right, it should be new Window().
Now i suggest you use more advanced options
{ std::make_unique<Window>(); }
Edit: For the first part it appears i was wrong new Window{} is a correct sintax
I'm planning out a design for my Window class. The goal is to provide an abstraction for creating a platform agnostic window ready for OpenGL rendering. I'm thinking of having a class 'Window' be the public interface, and a 'WindowImpl' class handle the work. Would making Window a friend of WindowImpl and calling WindowImpl functions inside Window cause issues? Technically, WindowImpl wouldn't be instantiated correct? So the destructor wouldn't be called which means the Window destructor wouldn't be called so a destroy function would be needed. Ex.
class MyWindow
{
public:
void create(width, height, title)
{
WindowImpl::create(width, height, title);
open = true;
}
void close()
{
WindowImpl::destroy();
open = false;
}
bool isOpen()
{
return open;
}
private:
bool open;
};
class WindowImpl
{
friend class MyWindow;
private:
static void create(width, height, title) {} // Creates the window
static void destroy()
{
XCloseDisplay(display);
}
static Display* display;
static Window window;
static GLXContext context;
};
I don't know if I'm going in the right way with this, or if I'm making things more complicated then they need to be. Since a different WindowImpl will be compiled depending on the target platform, I want to keep as much of it away from the user as possible, keeping all data like the window title and resolution inside of the Window class and any changes that are necessary can be made without the WindowImpl keeping track of anything more then the implementation specific stuff.
If it really has to be platform-agnostic, then my suggestion is to use something like this:
class WindowImpl
{
public:
virtual void setOwner(Window* pOwner) = 0
virtual void create(width, height, title) = 0;
virtual void close() = 0;
};
class Window
{
public:
void create(width, height, title)
{
mImpl->create(width, height, title);
open = true;
}
void close()
{
open = false;
mImpl->destroy();
}
Window(std::unique_ptr<WindowImpl> pImpl)
: mImpl(pImpl)
{
}
private:
std::unique_ptr<WindowImpl> mImpl;
};
// Then off somewhere else...
class WindowImplX11 : public WindowImpl
{
public:
void setOwner(Window* pOwner) {
mOwner = pOwner;
}
void destroy() {
XCloseDisplay(display);
}
private:
// Pointer back to the owner just in case (e.g. event
// delivery); if weak_ptr worked with unique_ptr, that
// would be better.
Window* mOwner;
Display* display;
GLXContext context;
};
This is a light version of the Bridge pattern, which is commonly used when you have two incompatible object hierarchies which you need to link together. This is a degenerate case (since the "hierarchy" has only one class in it), but it's still a useful technique to think about. Probably the most famous example of this is Java AWT (however AWT calls it "Peer" rather than "Impl").
Exactly how you split the responsibilities between the front end and back end is, of course, something that you need to decide for yourself, and there will probably be some back-and-forth. You may, for example, decide that an OpenGL context is a sufficiently important concept that you need to expose it to clients. The same goes for things like vsync fences which aren't fully supported in the standard way yet. Yes, I'm looking at you, OS X.
The only catch is how you construct a Window and its Impl. The traditional way is to use an abstract factory:
class Toolkit
{
public:
std::unique_ptr<Window> createWindow() = 0;
};
// then elsewhere...
// Should have been in the library, only left out by oversight.
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
class ToolkitX11 : public Toolkit
{
public:
std::unique_ptr<Window>
createWindow() {
return make_unique<Window>(make_unique<WindowImplX11>());
}
};
There are other ways which are a little more Modern.
I'm trying to access a dialog item from a function that is not in the same class as the dialog class. How can I do that?
Example:
class AnotherClass : CClas
{
AnotherClass();
public:
void MyFunction();
};
void AnotherClass::MyFunction() //Message overwriting, can't change parameters
{
CClass* temp = (CClass*)GetDlgItem(IDC_ID); //Reference to dialog item IDC_ID
temp->DoSomething(); //This gives me an assertion error
}
I know I can use "this" if it is the same dialog item than the message, but I want to access another dialog item.
Thanks for your attention.
Solution:
As suggested by Moo-Juice, you can simply pass the dialog when you instantiate the class. In my case, I couldn't do that. For some reason subclassing didn't work that way. If you face the same issue when doing an application in MFC , you can create a pointer to a CDialog and pass it your main dialog at OnInitDialog():
Example (Class):
class AnotherClass : CClass
{
AnotherClass();
public:
void MyFunction();
CDialog * mainDialog;
};
void AnotherClass::MyFunction() //Message overwriting, can't change parameters
{
CClass* temp = (CClass*)mainDialog->GetDlgItem(IDC_ID); //Reference to dialog item IDC_ID
temp->DoSomething(); //This gives me an assertion error
}
Example (OnInitDialog()):
MyMainDialog::OnInitDialog()
{
...
AnotherClass obj; //Instantiate class
obj->mainDialog = this;
return true;
}
In this example simply passing it as a parameter when creating the object makes more sense. It just didn't work with me for what I was doing.
Hope it helps anyone with a similar question.
When you instantiate AnotherClass, pass it the dialog class:
class AnotherClass
{
private:
CDialog& dialog_;
public:
AnotherClass(CDialog& dialog) : dialog_(dialog) { }
void MyFunction();
};
void AnotherClass::MyFunction()
{
CClass* temp = (CClass*)dialog_.GetDigItem(IDC_ID);
temp->doSOmething();
}