【问题标题】:What's the standard way for UI animations?UI动画的标准方式是什么?
【发布时间】:2013-12-14 19:03:44
【问题描述】:

我正在开发一个 D2DDWriteWic 支持的 UI 库,用于 (SDK API) 本机 C++ 桌面应用程序 (如没有 XAML,没有WinRT,只是老式的 C++)。我已经准备好编写一个无窗口用户界面,为我的C++ 工具提供更现代的(如本世纪的外观)

我本质上是一名支持者,因此我在 UI 上花费的时间最少,并且主要与 Windows 标准和通用控件以及一些自定义绘制的 GDI 东西进行交互。总之,没什么好看的。

我目前正在尝试使用 D2D,我有兴趣了解 UI 动画的标准方式。就像当您将鼠标悬停在使边框有点发光的按钮上,或者 UI 元素由于交互而平滑移动时,或者某些东西从屏幕上消失时。 (想想 jQuery 淡入淡出、滑动和在 UX 经济中如此简短但有意义的动画)

想到这里,我想到了两种在 UI 中处理动画的方法:

  • 独立线程处理动画队列的计算,同时 UI 线程绘制结果。每次交互都会将动画作业放入队列中,线程会计算内容并在元素被绘制之前重新定位它们。
  • 使用 same-thread Timers 来调度和迭代动画。

alternate Thread Worker 方法似乎是一个不错的方法……但在更新视觉属性时需要一些互锁,因此在实际绘制时不会发生这种情况,以保持一致。

现在,对于单线程 UI...计时器似乎是解决方案。这确保绘图不能与动画计算重叠。但对我来说,这感觉很尴尬。我很不习惯单线程的生活方式。 :)

还有其他方法吗?或者推荐哪种方法?我希望能提供有关现有实现细节或阅读材料的任何信息。

PS如果反对者或要求关闭的人真的能给出一个理由,我将不胜感激。 (1) 如果你不知道我在问什么,那就继续吧……这绝对不是你的问题。 (2) 如果这对您来说太明显/太简单,请回答。 --- 我没有看到第三个原因,除非你是巨魔。 --- 或者这是一个非常愚蠢的问题,但正如我所说,我是一个十年以上的支持者,所以我可以侥幸逃脱。

【问题讨论】:

  • 在线程之间分割这类事情的问题在于它很容易以令人讨厌的颤抖告终。如果你没有很多工作要做,那么多线程就没有意义。
  • @Spudd86 所以...timers?!
  • 您可能想看看Ncurses 以获得良好的衡量标准。它是终端应用程序的 UI 库。另请参阅:Ncurses on Windows.
  • @Domi :) 谢谢,但如果 UI 足够,我会使用 XML/JSON 配置文件。我实际上正在开发类似于 Metro UI(现代 UI)的 UI。所以,没有 DOS/终端的东西。它被标记为 Direct2D... - PS:如果你在开玩笑,这是一个非常好的笑话!
  • UI 样式和动画的当前标准是两年前的标准。这动作很快,UI 造型时尚具有冰箱里牛奶的生存技能。当今可用的优秀工具丝毫没有赋予它权力,这些工具可以用相对较少的努力快速改变它。由设计师而不是程序员,这样的工具不包括 C++。它使用您的 not 列表中的内容。承诺在一两年后变得糟糕的大量代码更改是错误的。

标签: c++ windows animation user-interface direct2d


【解决方案1】:

好吧,Windows 似乎对所有事物都有一个 API。 :)

我刚刚找到Windows Animation Manager。它不仅可以满足我的需要,而且在页面末尾,它有一些非常好的视频来解释 UI 动画概念以及它们如何与Animation Manager 一起工作。它是一组专为 C++ 使用而设计的 COM 对象。

PS另外,它独立于图形平台。所以它适用于 GDI、GDI+、Direct2D...

PPS一天后,我已经咬牙切齿了,非常好。我用最少的代码可以预见地在屏幕上移动图形元素。这是逻辑。一个问题是它只能为 DOUBLE 值设置动画。所以它对 POINT、RECT、SIZE、POLYGON、多个 FLOAT、PATH 等没有任何概念或支持。一旦我了解它是如何正常工作的,我将把它包装起来并添加对上述数据类型的支持,我是完成。

【讨论】:

【解决方案2】:

我不能告诉你 standard 方式,但 WPF 方式(我认为也是 Java Swing 方式)是有一个名为 的特殊线程>UI 线程,其唯一工作是执行调度程序循环。调度程序循环只是队列的一个花哨的词(带糖)。该框架将为该队列上的每一帧安排一个绘图函数。如果您想要一个动画,您也必须在该队列上安排这些微小的逐步更新。这是因为 WPF 等不希望在 UI 线程上锁定/阻塞,也不希望出现竞争条件。

所以回答你的问题:它既不是一个不同的线程也不是一个计时器。它是一个执行动画步骤的调度器。

【讨论】:

【解决方案3】:

我知道这是死灵术(我经常这样做),而且你已经接受了你的答案......但你或其他读者可能有兴趣看看DirectComposition。请注意,它仅适用于 Windows 8+

Microsoft DirectComposition 是一个 Windows 组件,它支持 具有变换、效果和 动画。

【讨论】:

  • 它只是 W8+,但与 2013 年相比,W8+ 现在已经普及了很多。所以这是对这里答案的一个很好的补充。
【解决方案4】:

GUI 中没有标准。 C++ 也没有 gui。不过现在有线程了:)

  • Word 或 Outlook 等应用程序应使用 C# 作为 gui,使用 C++ 作为核心。
  • 适用于实验室、大学和军事掩体中的技术和开发用户的应用程序通常可以使用简单的跨平台 gui。 QT 很普遍。对于非常简单的东西,比如演示 - fltk 可能就足够了。
  • 狭义小工具(文件压缩器、torrent 客户端、任务管理器)可以使用本机 winapi 窗口功能。 C 风格。不可维护。不可扩展。原生于 windows 平台。多年后针对性能进行了优化。
  • 视频游戏通常重新发明轮子并使用 d3d 执行游戏内的所有 gui 活动。
  • Skype 等应用程序需要最先进的 gui 功能,如浮动/可停靠/托盘/自定义形状/透明度/绝对量身定制的 GUI,不惜一切代价 - 可能会使用 MS 的一些闪亮的东西,如 silverlight 或 Wic,为此很重要。
  • 怪物项目可能会选择 MFC 或 ATL。

对于严肃的 gui,可能的选择是 C# 或 Qt。对于较小的东西 winapi + gdi 或小型跨平台 c++ gui 工具包。

对于 Windows 上的任何非控制台编程,请熟悉“窗口过程”和 winapi 消息循环。首先在 Visual Studio 中创建一个新的默认 win32 项目并查看它生成的代码。不要那样写。请注意以下模式:

// Handles window messages. Gets called by the DispatchMessage indirectly.
LRESULT __stdcall WindowProc(HWND hWnd, UINT msg, WPARAM, LPARAM)
{
    switch(msg) {
        case WM_PAINT: BeginPaint(...);
                       // Some GDI drawing might go here
                       EndPaint(...); break;
        case WM_TIMER: InvalidateWindow(hWnd); break;
        case WM_DESTROY: PostQuitMessage(0); break;
    default: return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return 0;
}

int __stdcall WinMain(HINSTANCE, HINSTANCE, char *cmdLine, int cmdShow)
{
    // create your gui here
    HWND hWnd = CreateWindow(...);
    ShowWindow(hWnd, cmdShow);
    UpdateWindow(hWnd);

    // Main message loop : make the gui "run"
    MSG msg = {0};
    while(GetMessage(&msg, 0, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

这是本机 winapi 应用程序框架。这就是 MFC/ATL/Qt 在下面所做的。 Winapi 提供了一些非常基本的开箱即用控件:窗口、文本框、按钮、单选按钮、选择按钮、列表框。所有都做基本的阴影,突出焦点 - 自win95以来可用的东西,但不是更多。如果 gui 非常简陋,那么您可以只使用普通的 winapi 就可以了。

作为 gui 库开发人员,最好的组合可能是来自 ms 或其他供应商的 win32 api 和 com 组件。

【讨论】:

  • 第一部分+1,但考虑到我自 1998 年以来一直在做 Win32 编程(+标准 UI 和自定义绘制控件),最后部分有点冒犯。大约15 年了...我使用自己的自定义 UI 库(我自己在标准控件之上)加上我自己的 C++ 库,其中包含大部分 Win32 C API。是时候将我的 UI 技能提升到 闪亮的...像 Serenity 了。 - PS:这更像是while(GetMessage(&msg, 0, 0, 0) > 0),因为WM_QUIT 返回0,错误返回-1,在您的while 中计算为TRUE。 MSDN 明确建议不要使用 while。 :)
  • 嗨,感谢您的投票 - 现在我可以添加 cmets 而不是写答案。请原谅我的最后一部分。那个循环条件:vs2013 为我生成了该行,但是,msdn 建议不要这样做。谢谢你的指出。
  • NP :) 现在将您的用户名更改为有意义的名称,如果您没有添加电子邮件,请添加电子邮件,并且您有一个正确的 SO 帐户。
猜你喜欢
  • 1970-01-01
  • 2020-08-01
  • 2015-12-02
  • 1970-01-01
  • 1970-01-01
  • 2012-03-26
  • 2013-07-10
  • 2011-05-20
  • 2012-01-27
相关资源
最近更新 更多