wxLua - 如何实现“取消”按钮?

时间:2012-09-13 18:07:44

标签: lua wxwidgets coroutine cancel-button

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

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

我从未使用过惯例;如果运行过程定期产生“取消检查”过程,那么取消事件会发生吗?

还是有另一种方式吗?

2 个答案:

答案 0 :(得分:3)

(以下假设“运行”表示在同一进程中长时间运行,使用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中的延迟);你可能需要对此进行试验,但是在调用之间100ms左右的基于计时器的东西可能有效。

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

答案 1 :(得分:1)

我不使用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