gpt4 book ai didi

c++ - 如何实现一个在点击时执行不同功能的通用按钮类?

转载 作者:搜寻专家 更新时间:2023-10-31 01:57:16 27 4
gpt4 key购买 nike

好的,我正在使用 SDL 和 C++,并开始为我的 map 编辑器开发一个简单的 GUI。从单个按钮的工作原型(prototype),我编写了一个通用 GUIObject 类和一个通用 Button 类。但是我现在有一个问题,为了让这个类可以重用,我需要能够为每个按钮设置它调用的函数(即帮助!打开帮助窗口,打开打开文件对话框,它们是同一个Button类,但是执行的功能不同)。

现在,我前段时间使用了一个简单的 Ruby GUI 库,它的语法使用了一些被标记为“ block 运算符”的东西:

例子:

@login_button = Button.new(@window, 98, 131, Network_Data::LOGIN_BUTTON){execute_login}

最后一部分 {} 是您放置自己的函数的地方,类以某种方式提取它并在单击时执行该函数。我也听说 Java 有类似的东西:

onClick = new Function() { }

那么我将如何在 C++ 程序(使用 SDL 库)中实现它。我不想使用任何 GUI 库,因为它们看起来太复杂,而且我很难将这些库插入到我已经构建的代码中。

最佳答案

您可以使用函数/仿函数/方法指针来完成。 (功能应该够用,比较简单)

您可以在按钮构造函数中传递一个指向回调函数的指针。

这是一个使用函数指针的基本示例。

class Button
{
typedef void(*eventFunction)();

Button( eventFunction funcPtr ) : m_funcPtr( funcPtr ){}
///< A constructor.
/// @param funcPtr The function pointer to register.

~Button(){ m_funcPtr = NULL; }
///< A destructor.

void operator() () const
{
(m_funcPtr)();
}
///< Invokes the registered function.

private:
eventFunction m_funcPtr;
};

你可以这样使用它:

void myFunction1() { /* do something */ }
void myFunction2() { /* do something else */ }

Button myButton1( &myFunction1 );
myButton1(); // invoke the function registered

Button myButton2( &myFunction2 );
myButton2(); // invoke the function registered

这是一个使用可变参数模板 (C++0x) 的更复杂的示例

template < class Tr, class... Args >
class Button
{
typedef Tr(*eventFunction)(Args...);

Button( eventFunction funcPtr ) : m_funcPtr( funcPtr ){}
///< A constructor.
/// @param funcPtr The function pointer to register.

~Button(){ m_funcPtr = NULL; }
///< A destructor.

void operator() ( Args&... args ) const
{
(m_funcPtr)(args...);
}
///< Invokes the registered function with the provided arguments.
/// @param args The arguments to transmit to the invoked function.

private:
eventFunction m_funcPtr;
};

你可以这样使用它:

void myFunction1( int, double ) { /* do something */ }
void myFunction2() { /* do something */ }

Button<void, int, double> myButton1( &myFunction1 );
myButton1( 10, 20.5 ); // invoke the function registered with two arguments

Button<void> myButton2( &myFunction2 );
myButton1(); // invoke the function registered without argument

Tr模板可以删除并替换为 void如果您从不打算使用除返回 void 的函数之外的其他函数。

因此 Button<void, int, double> myButton1( &myFunction1 );将更改为 Button<int, double> myButton1( &myFunction1 );

Button<void> myButton2( &myFunction2 );将更改为 Button<> myButton2( &myFunction2 );


你几乎可以用方法做同样的事情(你需要注册一个指向要调用的类的实例的指针和指向方法的指针)和仿函数(你需要注册一个指向仿函数实例的指针打电话)。


根据您的要求,这里是用同一个类来完成它的方法。您需要找到一种方法让您的 Button 类同时接受函数、仿函数和方法(想想虚拟 ^^)。这是C++0x版本

template < class C, class Tr, class... Args >
class Button
{
typedef Tr(C::*eventMethod)(Args...);
~Button(){}

Button( C& target, eventMethod method ) : m_target(target), m_method(method) {}
///< A constructor.
/// @param target The class member instance used to call the method.
/// @param method The class member method pointer to register.

bool operator () ( Args&... args ) const
{
(m_target.*(m_method))(args...);
}
///< Invokes the registered method with the provided arguments.
/// @param args The arguments to transmit to the invoked method.

private:
eventMethod m_method;
C& m_target;
};

你可以这样使用它:

class MyClass
{
void method1(){};
void method2( int, double ){};
};

MyClass myC1;

Button<MyClass, void> myButton1( myC1, &MyClass::method1 );
myButton1(); // invoke the registered method using the registered class instance.

Button<MyClass, void, int, double> myButton2( myC1, &MyClass::method2 );
myButton2( 15, 170.5 ); // invoke the registered method using the registered class instance.

如果您需要从该方法所属的类内部调用它,请使用 this作为目标参数而不是 myC1 .

关于c++ - 如何实现一个在点击时执行不同功能的通用按钮类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5859455/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com