【问题标题】:wxLua - How do I implement a Cancel button?wxLua - 如何实现取消按钮?
【发布时间】:2012-09-13 18:07:44
【问题描述】:

我有一个带有“运行”按钮的 wxLua Gui 应用程序。根据选择的选项,运行可能需要很长时间,所以我想实现一个“取消”按钮/功能。但是看起来 wxLua 中的所有东西都在一个 Gui 线程上运行,一旦你点击 Run,按 Cancel 什么都不会做,Run 总是会完成。

Cancel 基本上将一个变量设置为 true,并且正在运行的进程会定期检查该变量。但是在运行时不会发生取消按钮按下事件。

我从未使用过协同程序;如果 Run 进程定期产生一个“Cancel check”进程,那么 Cancel 事件会发生吗?

或者还有其他方法吗?

【问题讨论】:

    标签: lua wxwidgets coroutine cancel-button


    【解决方案1】:

    (以下假设“运行”是指在同一进程中长时间运行的操作,并且使用 wxExecute 或 wxProcess 运行外部进程。)

    “取消”事件没有被触发,因为通过执行你的运行逻辑你没有给 UI 处理点击事件的机会。

    为避免阻塞 UI,您需要执行以下操作。当您单击运行按钮时,围绕您要运行的函数创建一个协程:

    coro = coroutine.create(myLongRunningFunction)
    

    此时您的跑步活动已完成。然后在 EVT_IDLE 事件中,只要它不完整,你就会恢复这个协程。它看起来像这样:

    if coro then -- only if there is a coroutine to work on
      local ok, res = coroutine.resume(coro, additional, parameters)
      -- your function either yielded or returned
      -- you may check ok to see if there was an error
      -- res can tell you how far you are in the process
      -- coro can return multiple values (just give them as parameters to yield)
      if coroutine.status(coro) == 'dead' then -- finished or stopped with error
        coro = nil
        -- do whatever you need to do knowing the process is completed
      end
    end
    

    只要您的进程未完成,您可能需要请求更多 IDLE 事件,因为某些操作系统不会触发 IDLE 事件,除非触发了其他一些事件。假设您的处理程序具有event 参数,您可以执行event:RequestMore(true) 来请求更多IDLE 事件(RequestMore)。

    您的长时间运行的进程需要在正确的时间调用 coroutine.yield() (不要太短,因为您会浪费时间来回切换,也不要太长时间让用户注意到 UI 中的延迟);您可能需要对此进行试验,但调用之间 100 毫秒左右的基于计时器的方法可能会起作用。

    您可以像现在一样在 IDLE 事件处理程序或长时间运行的函数中检查 Cancel 值。我描述的逻辑将使您的应用程序 UI 有机会按您的预期处理 Cancel 事件。

    【讨论】:

      【解决方案2】:

      我不使用 WXWidgets,但我在使用 IUP 的 lua 脚本中实现取消按钮的方式是设置一个取消标志,该标志在按下按钮时设置,并在运行期间检查进度显示。

      用法是这样的

      ProgressDisplay.Start('This is my progress box',100)
      for i=1,100 do
          ProgressDisplay.SetMessage(i.." %")
          fhSleep(50,40)  -- Emulate performing the task 
          ProgressDisplay.Step(1)
          if ProgressDisplay.Cancel() then
              break
          end
      end 
      ProgressDisplay.Reset()
      ProgressDisplay.Close() 
      

      如果您想查看 ProgressDisplay 的定义,请参阅:

      http://www.fhug.org.uk/wiki/doku.php?id=plugins:code_snippets:progress_bar

      【讨论】:

        猜你喜欢
        • 2019-01-24
        • 2011-11-19
        • 1970-01-01
        • 2016-04-15
        • 2014-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多