在 Qt 中管理 GUI 状态的 RAII 类型

发布于 2024-11-27 08:57:32 字数 557 浏览 3 评论 0原文

我想知道您是否认为在 Qt 中使用类似于 RAII 的模式来管理 GUI 状态是否合理。通过 GUI 状态,我的意思是:我有一些小部件(包括鼠标光标状态),我想在离开某些方法后变得(不)可见/启用/更改,并且我不想将我所做的一切都放在其中一个巨大的 try catch 以这种方式:

widget1->show();
...
widgetN->show();

try {
   ...
}
catch(...) {
   widget1->hide();
   ... 
   widgetN->hide();

   throw;
}

widget1->hide();
... 
widgetN->hide();

如果我创建一个对象,允许我在其构造函数上关联 hide/setEnabled/setCursor 函数(可能是 boost 函子),并在其析构函数上调用此关联函数(前提是此函数的所有异常可以扔在析构函数中被吃掉/丢失)我可以有一个更干净的代码。这合理吗?我没有看到什么?

任何评论/建议都将受到真正的欢迎。

预先感谢,

费德里科

I would like to know if you think it is reasonable to use a pattern similar to RAII to manage GUI state in Qt. By GUI state I mean the following: I've some widgets (including the mouse cursor state) I want to go (not) visible/enabled/changed after I leave some method, and I don't want to put everything I do in a giant try catch in this way:

widget1->show();
...
widgetN->show();

try {
   ...
}
catch(...) {
   widget1->hide();
   ... 
   widgetN->hide();

   throw;
}

widget1->hide();
... 
widgetN->hide();

If I create an object that allows me to associate the hide/setEnabled/setCursor function (maybe a boost functor) on its constructor and that calls this associated function on its destructor (provided that all exceptions this function can throw are eaten/lost in the destructor) I can have a much cleaner code. Is this reasonable? what I'm not seeing?

Any comment/suggestion will be really welcomed.

Thanks in advance,

Federico

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烟花易冷人易散 2024-12-04 08:57:32

这是完全合理的。您所追求的技术称为 ScopeGuard,在 Boost 中称为 ScopeExit。

这个想法是,当您第一次进行更改时,定义一些想要在范围末尾运行的代码,然后处理其余的代码。如果需要,您可以“关闭”该代码。

我想输入一个示例,但我正在使用手机。

It's completely reasonable. The technique you're after is called ScopeGuard, called ScopeExit in Boost.

The idea is that you define some code you want to run at the end of the scope when you first make your changes, and the rest is handled. You can "dismiss" the code if desired.

I'd type an example but I'm on my phone.

贪恋 2024-12-04 08:57:32

RAII 用于处置资源,这并不像某些人可能认为的那样受限制。在许多情况下,“资源”可以用“状态”代替。

如果您将控件的可见性与存储的状态等同起来,并且需要安全地回收该状态(将其设置为不可见),那么在析构函数中重置它是可行的方法。

您正确使用 RAII。

确保为您的类命名,使其清楚地表明您将可见性视为一次性资源 - 也许像 VisibleStateIsVisibleContext 这样简单。

RAII is for disposing resources, which isn't as constrained a concept as some might have you believe. "resource" can be substituted with "state" in many contexts.

If you equate a control's visibility with a stored state, and you need to safely reclaim that state (set it invisible), then resetting it in a destructor is the way to go.

You are using RAII correctly.

Be sure to name your class something that makes it plainly obvious that you are treating visibility as a disposable resource - maybe something as simple as VisibleState or IsVisibleContext.

此刻的回忆 2024-12-04 08:57:32

我已经完成了 C++ lambda 和 2 个宏:

#include <functional>

struct _Scope_Exit_ {
        inline _Scope_Exit_(const std::function<void ()> f): _f(f) {}
        inline ~_Scope_Exit_() { _f(); }
        const std::function<void ()> _f;
};

#define SCOPE_EXIT_CAT2(x, y) x##y
#define SCOPE_EXIT_CAT1(x, y) SCOPE_EXIT_CAT2(x, y)
#define SCOPE_EXIT _Scope_Exit_ SCOPE_EXIT_CAT1(_scope_Exit_, __COUNTER__)([this](){
#define SCOPE_EXIT_END });

要使用它,您必须在 SCOPE_EXITSCOPE_EXIT_END 之间的方法末尾定义要执行的块

。你的样本是:

widget1->show();
...
widgetN->show();

SCOPE_EXIT
   widget1->hide();
   ... 
   widgetN->hide();
SCOPE_EXIT_END

... (code inside your try)

I've done with C++ lambda and 2 macros:

#include <functional>

struct _Scope_Exit_ {
        inline _Scope_Exit_(const std::function<void ()> f): _f(f) {}
        inline ~_Scope_Exit_() { _f(); }
        const std::function<void ()> _f;
};

#define SCOPE_EXIT_CAT2(x, y) x##y
#define SCOPE_EXIT_CAT1(x, y) SCOPE_EXIT_CAT2(x, y)
#define SCOPE_EXIT _Scope_Exit_ SCOPE_EXIT_CAT1(_scope_Exit_, __COUNTER__)([this](){
#define SCOPE_EXIT_END });

To use it, you must define the block that you want to execute at the end of the method between SCOPE_EXIT and SCOPE_EXIT_END

In your sample would be:

widget1->show();
...
widgetN->show();

SCOPE_EXIT
   widget1->hide();
   ... 
   widgetN->hide();
SCOPE_EXIT_END

... (code inside your try)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文