当前位置:  开发笔记 > 后端 > 正文

状态机和用户界面工作 - 任何示例/经验?

如何解决《状态机和用户界面工作-任何示例/经验?》经验,为你挑选了4个好方法。

我正在寻找解决我的前端小部件代码的方法.有人建议使用有限状态机来思考我正在做的事情.我知道一个状态机模式可以适用于几乎任何问题.我想知道是否有一些经验丰富的UI程序员实际上养成了这个习惯.

所以,问题是 - 你们中的任何一个UI程序员都会在你的工作中考虑状态机吗?如果是这样,怎么样?

谢谢,-Morgan



1> Michael Borg..:

我目前正在使用(专有)框架,它非常适合UI作为状态机的范例,它肯定可以减少(但不能消除)UI元素之间复杂和无法预见的交互问题.

主要的好处是它允许您以更高的粒度在更高的抽象级别进行思考.而不是想"如果按下按钮A然后组合框B被锁定,文本字段C被清除并且按钮D被解锁",您认为"按下按钮A将应用程序置于CHECKED状态" - 并且进入该状态意味着某些事情发生.

但是,我不认为将整个UI建模为单个状态机是有用的(甚至是可能的).相反,通常有许多较小的状态机,每个状态机处理UI的一部分(由几个在概念上相互作用并在一起的控件组成),以及一个(可能不止一个)处理更多基本问题的"全局"状态机.



2> Ken Fox..:

状态机通常太低级别,无法帮助您考虑用户界面.它们为UI工具包提供了一个很好的实现选择,但是在正常的应用程序中有太多的状态和转换需要您手动描述它们.

我喜欢考虑具有延续的UI.(谷歌它 - 这个术语足够具体,你可以得到很多高质量的点击.)

而不是我的应用程序处于由状态标志和模式表示的各种状态,我使用continuation来控制应用程序下一步做什么.用一个例子来解释是最容易的.假设您要在发送电子邮件之前弹出确认对话框.第1步构建一封电子邮件.第2步得到确认.第3步发送电子邮件.大多数UI工具包都要求您在每个步骤之后将控制权传递回事件循环,如果您尝试使用状态机来表示它,则会使其变得非常难看.通过延续,您不会考虑工具包强加给您的步骤 - 这是构建和发送电子邮件的所有过程.但是,当进程需要确认时,您将继续捕获应用程序的状态,并将该继续执行到确认对话框上的"确定"按钮.按下确定后,

在编程语言中,Continuations相对较少,但幸运的是,你可以使用闭包获得一个穷人的版本.回到电子邮件发送示例,在您需要获得确认时,您将剩余的进程写为闭包,然后将该闭包交给OK按钮.闭包类似于匿名嵌套子例程,它们在下次调用时记住所有局部变量的值.

希望这能给你一些新的思考方向.我将尝试稍后使用真实代码回来向您展示它是如何工作的.

更新:以下是Ruby中Qt的完整示例.有趣的部分在ConfirmationButton和MailButton中.我不是Qt或Ruby专家,所以我很欣赏你们所能提供的任何改进.

require 'Qt4'

class ConfirmationWindow < Qt::Widget
  def initialize(question, to_do_next)
    super()

    label = Qt::Label.new(question)
    ok = ConfirmationButton.new("OK")
    ok.to_do_next = to_do_next
    cancel = Qt::PushButton.new("Cancel")

    Qt::Object::connect(ok, SIGNAL('clicked()'), ok, SLOT('confirmAction()'))
    Qt::Object::connect(ok, SIGNAL('clicked()'), self, SLOT('close()'))
    Qt::Object::connect(cancel, SIGNAL('clicked()'), self, SLOT('close()'))

    box = Qt::HBoxLayout.new()
    box.addWidget(label)
    box.addWidget(ok)
    box.addWidget(cancel)

    setLayout(box)
  end
end

class ConfirmationButton < Qt::PushButton
  slots 'confirmAction()'
  attr_accessor :to_do_next
  def confirmAction()
    @to_do_next.call()
  end
end

class MailButton < Qt::PushButton
  slots 'sendMail()'
  def sendMail()
    lucky = rand().to_s()
    message = "hello world. here's your lucky number: " + lucky
    do_next = lambda {
      # Everything in this block will be delayed until the
      # the confirmation button is clicked. All the local
      # variables calculated earlier in this method will retain
      # their values.
      print "sending mail: " + message + "\n"
    }
    popup = ConfirmationWindow.new("Really send " + lucky + "?", do_next)
    popup.show()
  end
end

app = Qt::Application.new(ARGV)

window = Qt::Widget.new()
send_mail = MailButton.new("Send Mail")
quit = Qt::PushButton.new("Quit")

Qt::Object::connect(send_mail, SIGNAL('clicked()'), send_mail, SLOT('sendMail()'))
Qt::Object::connect(quit, SIGNAL('clicked()'), app, SLOT('quit()'))

box = Qt::VBoxLayout.new(window)
box.addWidget(send_mail)
box.addWidget(quit)

window.setLayout(box)
window.show()
app.exec()


很有意思.我肯定会按照你的谷歌推荐.

3> 小智..:

不需要将UI建模为状态机; 它是显示的对象,它可以有助于建模为状态机.然后,您的UI变为(过度简化)一组事件处理程序,用于各种对象中的状态更改.

这是一个变化:

DoSomethingToTheFooObject();  
UpdateDisplay1();  // which is the main display for the Foo object  
UpdateDisplay2();  // which has a label showing the Foo's width,
                   // which may have changed  
...  

至:

Foo.DoSomething();  

void OnFooWidthChanged() { UpdateDisplay2(); }  
void OnFooPaletteChanged() { UpdateDisplay1(); }  

考虑到您正在显示的数据中的哪些更改应该导致重新绘制可以澄清,无论是从客户端UI端还是服务器Foo端.

如果你发现,当Foo的状态发生变化时,可能需要重新绘制100个UI内容,当调色板发生变化时,所有这些都需要重新绘制,但是当宽度发生变化时,只需要重新绘制10个,它可能会暗示某些事件/状态改变Foo应该发出信号.如果您发现有一个大型事件处理程序OnFooStateChanged()通过检查许多Foo的属性来查看已更改的内容,为了最大限度地减少UI更新,它会提示有关Foo事件模型的粒度的信息.如果您发现想要编写一个小的独立UI小部件,您可以在UI中的多个位置使用它,但它需要知道Foo何时更改并且您不希望包含Foo实现带来的所有代码,它建议一些与您的UI相关的数据组织,你的表示层,比"我的表单类中的所有代码"更严肃.

-PC


回到当天,我们称之为MVC.那是在Rails摧毁这个词之前.

4> Dill..:

有一本关于这个主题的书.可悲的是,它的绝版和罕见的二手产品非常昂贵.

Constructing the User Interface with Statecharts
by Ian Horrocks, Addison-Wesley, 1998


这本书出现在[Scribd]上(http://www.scribd.com/doc/235638010/Ian-Horrocks-Constructing-the-User-Interface-Wit-BookZZ-org#scribd)
推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有