如何实时更新 DM 中的框字段
how to live update box field in DM
我想创建一个框,其中的字段由另一个函数更新(在我的示例中是一个循环)。
每次值更改时,显示都应更改。
我第一次尝试创建一个仅显示最后一个值的框。
Class MyTestDialog: UIFrame
{
TagGroup CreateMyDialog(Object self)
{
TagGroup DialogTG = DLGCreateDialog("useless text")
TagGroup Fields,FieldItems
Fields = DLGCreateBox("Current",FieldItems)
FieldItems.DLGAddElement(DLGCreateRealField(42,15,3).DLGIdentifier("#RField"))
DialogTG.DLGAddElement(Fields.DLGTableLayOut(3,1,0))
Return DialogTG
}
Void Doit(Object self,number count)
{
for (count=0; count<5; count++)
{
self.LookUpElement("#RField").DLGValue(sum(getfrontimage())*count)
self.Display("Text at top of box window")
sleep(3)
}
}
Object Init(Object self) return self.super.Init(self.CreateMyDialog())
}
Object MyBeamCurrentDisplay = Alloc(MyTestDialog).Init()
MyBeamCurrentDisplay.Display("Text at top of box window")
sleep(3)
MyBeamCurrentDisplay.Doit(5)
您的脚本确实有效(除非您不想每次都 re-display 对话框。),但因为 DM-script 本身以及 UI 更新调用在 DM 的主线程上处理,您看不到更新。
对话框更新了 5 次,但是对话框的 display 只有在脚本完成后才会更新,给 main-thread CPU 周期处理 UI 更新。
如果您将脚本放在 background-thread 上,您会看到它有效:
// $BACKGROUND$
Class MyTestDialog: UIFrame
{
TagGroup CreateMyDialog(Object self)
{
TagGroup DialogTG = DLGCreateDialog("useless text")
TagGroup Fields,FieldItems
Fields = DLGCreateBox("Current",FieldItems)
FieldItems.DLGAddElement(DLGCreateRealField(42,15,3).DLGIdentifier("#RField"))
DialogTG.DLGAddElement(Fields.DLGTableLayOut(3,1,0))
Return DialogTG
}
Void Doit(Object self,number count)
{
for (count=0; count<5; count++)
{
self.LookUpElement("#RField").DLGValue(sum(getfrontimage())*count)
// self.Display("Text at top of box window")
sleep(0.1)
}
}
Object Init(Object self) return self.super.Init(self.CreateMyDialog())
}
Object MyBeamCurrentDisplay = Alloc(MyTestDialog).Init()
MyBeamCurrentDisplay.Display("Text at top of box window")
sleep(0.2)
MyBeamCurrentDisplay.Doit(20)
(代码的第一行必须 正好 // $BACKGROUND
)
另一种方法是将脚本保留在主线程上,但在 sleep(0.1)
之前添加 doEvents()
以便为主应用程序完成排队任务(如更新)提供一些 CPU 周期UI的。
我还尝试了一些更新和不同的线程,我认为您可能会发现以下示例很有用:
number TRUE = 1
number FALSE = 0
Class MyTestDialog: UIFrame
{
object messageQueue
object stoppedSignal
number updateTimeSec
void OnUpdateStateChanged(object self, taggroup checkboxTG )
{
if ( TRUE == checkboxTG.DLGGetValue() )
self.StartThread( "RegularFrontImageUpdate" )
else
messageQueue.PostMessage( Alloc(object) ) // Single message: Stop, so any object will do
}
number AboutToCloseDocument( object self, number verify )
{
result("\nAbout to close")
messageQueue.PostMessage( Alloc(object) ) // Single message: Stop, so any object will do
stoppedSignal.WaitOnSignal( infinity(), NULL ) // Ensure we don't kill the UI object while the update thread is still accessing it
return FALSE
}
TagGroup CreateMyDialog(Object self)
{
TagGroup DialogTG = DLGCreateDialog("useless text")
TagGroup Fields,FieldItems
Fields = DLGCreateBox("Current Front Image Sum",FieldItems)
FieldItems.DLGAddElement(DLGCreateStringField("No front image",30).DLGIdentifier("#StrField").DLGEnabled(FALSE))
FieldItems.DLGAddElement(DLGCreateRealField(0,15,3).DLGIdentifier("#RField").DLGEnabled(FALSE))
FieldItems.DLGAddElement(DLGCreateCheckbox("Update", TRUE, "OnUpdateStateChanged").DLGIdentifier("#ToggleCheck"))
DialogTG.DLGAddElement(Fields.DLGTableLayOut(3,1,0))
Return DialogTG
}
void RegularFrontImageUpdate(Object self)
{
stoppedSignal.ResetSignal()
self.SetElementIsEnabled("#RField",TRUE)
self.SetElementIsEnabled("#StrField",TRUE)
result("\nEnabling auto-update")
while(TRUE)
{
object message = messageQueue.WaitOnMessage( updateTimeSec, null )
if ( message.ScriptObjectIsValid() )
{
// Handle message. We just use 'empty' objects in this example
// as we only have a "single" message: Stop updating now!
self.LookUpElement("#ToggleCheck").DLGValue( 0 )
self.LookUpElement("#RField").DLGValue( 0 )
self.SetElementIsEnabled("#RField",FALSE)
self.SetElementIsEnabled("#StrField",FALSE)
result("\nDisabling auto-update")
break;
}
else
{
// Timeout of waiting time. Just update
image front := FindFrontImage()
if ( front.ImageIsValid() )
{
self.LookUpElement("#RField").DLGValue( sum(front) )
self.LookUpElement("#StrField").DLGValue( front.GetName() )
}
else
self.LookUpElement("#ToggleCheck").DLGValue( 0 )
}
}
stoppedSignal.SetSignal()
}
object Launch(object self)
{
updateTimeSec = 0.1
messageQueue = NewMessageQueue()
stoppedSignal = NewSignal( false )
self.Init(self.CreateMyDialog()).Display("Title")
self.StartThread( "RegularFrontImageUpdate" )
return self
}
}
Alloc(MyTestDialog).Launch()
我想创建一个框,其中的字段由另一个函数更新(在我的示例中是一个循环)。 每次值更改时,显示都应更改。
我第一次尝试创建一个仅显示最后一个值的框。
Class MyTestDialog: UIFrame
{
TagGroup CreateMyDialog(Object self)
{
TagGroup DialogTG = DLGCreateDialog("useless text")
TagGroup Fields,FieldItems
Fields = DLGCreateBox("Current",FieldItems)
FieldItems.DLGAddElement(DLGCreateRealField(42,15,3).DLGIdentifier("#RField"))
DialogTG.DLGAddElement(Fields.DLGTableLayOut(3,1,0))
Return DialogTG
}
Void Doit(Object self,number count)
{
for (count=0; count<5; count++)
{
self.LookUpElement("#RField").DLGValue(sum(getfrontimage())*count)
self.Display("Text at top of box window")
sleep(3)
}
}
Object Init(Object self) return self.super.Init(self.CreateMyDialog())
}
Object MyBeamCurrentDisplay = Alloc(MyTestDialog).Init()
MyBeamCurrentDisplay.Display("Text at top of box window")
sleep(3)
MyBeamCurrentDisplay.Doit(5)
您的脚本确实有效(除非您不想每次都 re-display 对话框。),但因为 DM-script 本身以及 UI 更新调用在 DM 的主线程上处理,您看不到更新。
对话框更新了 5 次,但是对话框的 display 只有在脚本完成后才会更新,给 main-thread CPU 周期处理 UI 更新。
如果您将脚本放在 background-thread 上,您会看到它有效:
// $BACKGROUND$
Class MyTestDialog: UIFrame
{
TagGroup CreateMyDialog(Object self)
{
TagGroup DialogTG = DLGCreateDialog("useless text")
TagGroup Fields,FieldItems
Fields = DLGCreateBox("Current",FieldItems)
FieldItems.DLGAddElement(DLGCreateRealField(42,15,3).DLGIdentifier("#RField"))
DialogTG.DLGAddElement(Fields.DLGTableLayOut(3,1,0))
Return DialogTG
}
Void Doit(Object self,number count)
{
for (count=0; count<5; count++)
{
self.LookUpElement("#RField").DLGValue(sum(getfrontimage())*count)
// self.Display("Text at top of box window")
sleep(0.1)
}
}
Object Init(Object self) return self.super.Init(self.CreateMyDialog())
}
Object MyBeamCurrentDisplay = Alloc(MyTestDialog).Init()
MyBeamCurrentDisplay.Display("Text at top of box window")
sleep(0.2)
MyBeamCurrentDisplay.Doit(20)
(代码的第一行必须 正好 // $BACKGROUND
)
另一种方法是将脚本保留在主线程上,但在 sleep(0.1)
之前添加 doEvents()
以便为主应用程序完成排队任务(如更新)提供一些 CPU 周期UI的。
我还尝试了一些更新和不同的线程,我认为您可能会发现以下示例很有用:
number TRUE = 1
number FALSE = 0
Class MyTestDialog: UIFrame
{
object messageQueue
object stoppedSignal
number updateTimeSec
void OnUpdateStateChanged(object self, taggroup checkboxTG )
{
if ( TRUE == checkboxTG.DLGGetValue() )
self.StartThread( "RegularFrontImageUpdate" )
else
messageQueue.PostMessage( Alloc(object) ) // Single message: Stop, so any object will do
}
number AboutToCloseDocument( object self, number verify )
{
result("\nAbout to close")
messageQueue.PostMessage( Alloc(object) ) // Single message: Stop, so any object will do
stoppedSignal.WaitOnSignal( infinity(), NULL ) // Ensure we don't kill the UI object while the update thread is still accessing it
return FALSE
}
TagGroup CreateMyDialog(Object self)
{
TagGroup DialogTG = DLGCreateDialog("useless text")
TagGroup Fields,FieldItems
Fields = DLGCreateBox("Current Front Image Sum",FieldItems)
FieldItems.DLGAddElement(DLGCreateStringField("No front image",30).DLGIdentifier("#StrField").DLGEnabled(FALSE))
FieldItems.DLGAddElement(DLGCreateRealField(0,15,3).DLGIdentifier("#RField").DLGEnabled(FALSE))
FieldItems.DLGAddElement(DLGCreateCheckbox("Update", TRUE, "OnUpdateStateChanged").DLGIdentifier("#ToggleCheck"))
DialogTG.DLGAddElement(Fields.DLGTableLayOut(3,1,0))
Return DialogTG
}
void RegularFrontImageUpdate(Object self)
{
stoppedSignal.ResetSignal()
self.SetElementIsEnabled("#RField",TRUE)
self.SetElementIsEnabled("#StrField",TRUE)
result("\nEnabling auto-update")
while(TRUE)
{
object message = messageQueue.WaitOnMessage( updateTimeSec, null )
if ( message.ScriptObjectIsValid() )
{
// Handle message. We just use 'empty' objects in this example
// as we only have a "single" message: Stop updating now!
self.LookUpElement("#ToggleCheck").DLGValue( 0 )
self.LookUpElement("#RField").DLGValue( 0 )
self.SetElementIsEnabled("#RField",FALSE)
self.SetElementIsEnabled("#StrField",FALSE)
result("\nDisabling auto-update")
break;
}
else
{
// Timeout of waiting time. Just update
image front := FindFrontImage()
if ( front.ImageIsValid() )
{
self.LookUpElement("#RField").DLGValue( sum(front) )
self.LookUpElement("#StrField").DLGValue( front.GetName() )
}
else
self.LookUpElement("#ToggleCheck").DLGValue( 0 )
}
}
stoppedSignal.SetSignal()
}
object Launch(object self)
{
updateTimeSec = 0.1
messageQueue = NewMessageQueue()
stoppedSignal = NewSignal( false )
self.Init(self.CreateMyDialog()).Display("Title")
self.StartThread( "RegularFrontImageUpdate" )
return self
}
}
Alloc(MyTestDialog).Launch()