是否可以从主线程显示和更新进度条?
Is it possible to display and update a progress bar from the main thread?
我想设置一个进度条来显示冗长例程的状态。从后台线程启动带有进度条的对话框非常简单。但是,是否可以从 "foreground" 进程这样做?这个想法是显示进度状态但阻止用户使用 DM 做任何事情。
内置的 Progress 小工具选项板(可通过 OpenAndSetProgressWindow 脚本命令访问)符合我的目的,但我想要一个更漂亮的界面并显示更多信息。以下是示例脚本。正如我们所看到的,当从前台进程设置 ProgressBar 对话框时,它根本没有更新。
class ProgressBar : UIFrame {
number true, false;
string Identifier_Status, identifier_progressBar;
string panel_name;
number token;
//
ProgressBar(object self) {;
true=1; false=0;
identifier_progressBar = "Progress_Bar";
Identifier_Status = "Progress_Status"
result("Script object \"ProgressBar\"[" + self.ScriptObjectGetID().hex() + "] constructed\n" );
};
~ProgressBar(object self) {;
result("Script object \"ProgressBar\"[" + self.ScriptObjectGetID().hex() + "] destructed\n\n" );
};
//
void SetProgress(object self, number fraction) {
self.DLGSetProgress( identifier_progressBar, fraction );
};
void UpdateStatus(object self, string status ) {
self.LookUpElement(Identifier_Status).DLGTitle(status);
};
void Terminate(object self) {
panel_name.CloseGadgetPanel();
// token.UnregisterScriptPalette();
panel_name.UnregisterScriptPalette();
};
void init(object self, string title, string prompt) {
panel_name = title;
// build main dialog tag group
TagGroup tgDLG = DLGCreateDialog( panel_name );
// create UIFrame elements
TagGroup tgProgressBar = DLGCreateProgressBar(identifier_progressBar).DLGFill("X");
TagGroup tgStatus = DLGCreateLabel(prompt).DLGWidth(40).DLGIdentifier(Identifier_Status);
// build position
TagGroup tgPositon = DLGBuildPositionFromApplication();
tgPositon.TagGroupSetTagAsString( "Width", "Wide" ); // Narrow, Medium, Wide;
tgPositon.DLGSide( "Left" );
tgDLG.DLGPosition(tgPositon);
// assemble dialog
tgDLG.DLGAddElement(tgStatus);
tgDLG.DLGAddElement(tgProgressBar);
// initialize and display
self.super.init( tgDLG );
token = self.RegisterScriptPalette(panel_name, panel_name);
panel_name.OpenGadgetPanel();
//
return;
};
};
class main : Thread {
object obj;
main(object self) {
obj = alloc(ProgressBar);
result("Script object \"main\"[" + self.ScriptObjectGetID().hex() + "] constructed\n" );
};
~main(object self ) {
result("Script object \"main\"[" + self.ScriptObjectGetID().hex() + "] destructed\n" );
};
void RunThread(object self) {
obj.init( "Progress bar test", "<status>" );
string msg1, msg2, msg3;
number time = 5, interval = 0.1, nSteps = time/interval;
for( number idx = 1; idx <= nSteps; idx++) {
//
msg1 = "Processing step:";
msg2 = " ";
msg3 = "#" + idx + " of " + nSteps;
//
OpenAndSetProgressWindow( msg1, msg2, msg3 );
//
obj.UpdateStatus( msg1 + msg2 + msg3 );
obj.SetProgress( idx/nSteps );
yield();
sleep(interval);
};
msg1 = ""; msg3 = "";
msg2 = "completed"
OpenAndSetProgressWindow( msg1, msg2, msg3 );
obj.Terminate();
};
};
if( TwoButtonDialog( "Show and update progress bar as", "background thread", "forground process") ) alloc(main).StartThread();
else alloc(main).RunThread();
当您 运行 DLGSetProgressBar()
形成主线程时,您需要强制更新对话框-window 和 ValidateView()
即在上面的脚本中,您可以在主循环中执行此操作:
void RunThread(object self) {
obj.init( "Progress bar test", "<status>" );
string msg1, msg2, msg3;
number time = 5, interval = 0.5, nSteps = time/interval;
for( number idx = 1; idx <= nSteps; idx++) {
//
msg1 = "Processing step:";
msg2 = " ";
msg3 = "#" + idx + " of " + nSteps;
//
OpenAndSetProgressWindow( msg1, msg2, msg3 );
//
Result("\n Step "+idx)
obj.UpdateStatus( msg1 + msg2 + msg3 );
obj.SetProgress( idx/nSteps );
obj.ValidateView() // <<<<<<<<<<<<<<<<<< HERE
yield();
sleep(interval);
};
msg1 = ""; msg3 = "";
msg2 = "completed"
OpenAndSetProgressWindow( msg1, msg2, msg3 );
obj.Terminate();
};
或者您可以在更新方法中进行:
void SetProgress(object self, number fraction) {
self.DLGSetProgress( identifier_progressBar, fraction );
self.ValidateView()
};
我想设置一个进度条来显示冗长例程的状态。从后台线程启动带有进度条的对话框非常简单。但是,是否可以从 "foreground" 进程这样做?这个想法是显示进度状态但阻止用户使用 DM 做任何事情。
内置的 Progress 小工具选项板(可通过 OpenAndSetProgressWindow 脚本命令访问)符合我的目的,但我想要一个更漂亮的界面并显示更多信息。以下是示例脚本。正如我们所看到的,当从前台进程设置 ProgressBar 对话框时,它根本没有更新。
class ProgressBar : UIFrame {
number true, false;
string Identifier_Status, identifier_progressBar;
string panel_name;
number token;
//
ProgressBar(object self) {;
true=1; false=0;
identifier_progressBar = "Progress_Bar";
Identifier_Status = "Progress_Status"
result("Script object \"ProgressBar\"[" + self.ScriptObjectGetID().hex() + "] constructed\n" );
};
~ProgressBar(object self) {;
result("Script object \"ProgressBar\"[" + self.ScriptObjectGetID().hex() + "] destructed\n\n" );
};
//
void SetProgress(object self, number fraction) {
self.DLGSetProgress( identifier_progressBar, fraction );
};
void UpdateStatus(object self, string status ) {
self.LookUpElement(Identifier_Status).DLGTitle(status);
};
void Terminate(object self) {
panel_name.CloseGadgetPanel();
// token.UnregisterScriptPalette();
panel_name.UnregisterScriptPalette();
};
void init(object self, string title, string prompt) {
panel_name = title;
// build main dialog tag group
TagGroup tgDLG = DLGCreateDialog( panel_name );
// create UIFrame elements
TagGroup tgProgressBar = DLGCreateProgressBar(identifier_progressBar).DLGFill("X");
TagGroup tgStatus = DLGCreateLabel(prompt).DLGWidth(40).DLGIdentifier(Identifier_Status);
// build position
TagGroup tgPositon = DLGBuildPositionFromApplication();
tgPositon.TagGroupSetTagAsString( "Width", "Wide" ); // Narrow, Medium, Wide;
tgPositon.DLGSide( "Left" );
tgDLG.DLGPosition(tgPositon);
// assemble dialog
tgDLG.DLGAddElement(tgStatus);
tgDLG.DLGAddElement(tgProgressBar);
// initialize and display
self.super.init( tgDLG );
token = self.RegisterScriptPalette(panel_name, panel_name);
panel_name.OpenGadgetPanel();
//
return;
};
};
class main : Thread {
object obj;
main(object self) {
obj = alloc(ProgressBar);
result("Script object \"main\"[" + self.ScriptObjectGetID().hex() + "] constructed\n" );
};
~main(object self ) {
result("Script object \"main\"[" + self.ScriptObjectGetID().hex() + "] destructed\n" );
};
void RunThread(object self) {
obj.init( "Progress bar test", "<status>" );
string msg1, msg2, msg3;
number time = 5, interval = 0.1, nSteps = time/interval;
for( number idx = 1; idx <= nSteps; idx++) {
//
msg1 = "Processing step:";
msg2 = " ";
msg3 = "#" + idx + " of " + nSteps;
//
OpenAndSetProgressWindow( msg1, msg2, msg3 );
//
obj.UpdateStatus( msg1 + msg2 + msg3 );
obj.SetProgress( idx/nSteps );
yield();
sleep(interval);
};
msg1 = ""; msg3 = "";
msg2 = "completed"
OpenAndSetProgressWindow( msg1, msg2, msg3 );
obj.Terminate();
};
};
if( TwoButtonDialog( "Show and update progress bar as", "background thread", "forground process") ) alloc(main).StartThread();
else alloc(main).RunThread();
当您 运行 DLGSetProgressBar()
形成主线程时,您需要强制更新对话框-window 和 ValidateView()
即在上面的脚本中,您可以在主循环中执行此操作:
void RunThread(object self) {
obj.init( "Progress bar test", "<status>" );
string msg1, msg2, msg3;
number time = 5, interval = 0.5, nSteps = time/interval;
for( number idx = 1; idx <= nSteps; idx++) {
//
msg1 = "Processing step:";
msg2 = " ";
msg3 = "#" + idx + " of " + nSteps;
//
OpenAndSetProgressWindow( msg1, msg2, msg3 );
//
Result("\n Step "+idx)
obj.UpdateStatus( msg1 + msg2 + msg3 );
obj.SetProgress( idx/nSteps );
obj.ValidateView() // <<<<<<<<<<<<<<<<<< HERE
yield();
sleep(interval);
};
msg1 = ""; msg3 = "";
msg2 = "completed"
OpenAndSetProgressWindow( msg1, msg2, msg3 );
obj.Terminate();
};
或者您可以在更新方法中进行:
void SetProgress(object self, number fraction) {
self.DLGSetProgress( identifier_progressBar, fraction );
self.ValidateView()
};