如何向可见对话框添加内容

How to add content to a visible dialog

当用户点击 dm 脚本中的按钮时,如何将元素添加到可见对话框?


我的目标是一个输入对话框,允许用户 select 他想要处理的图像。这可以是多个图像。因此我想设计一个提供 add 按钮的对话框。单击该按钮会添加一个 select 框 (DLGCreateImagePopup()),用于选择图像。

我的问题是我没有找到更新对话框的方法 UI。它不会重绘内容。唯一接近我的问题的是关于 的 post。 post 建议使用 UIFrame.close() 后跟 UIFrame.display() 但出现的对话框不再是模态的。将 UIFrame.display() 更改为 UIFrame.pose() 对话框就消失了。当再次尝试执行脚本时,错误 Class already declared: 'TestDialog' 出现了。那我得重启GMS了。

以下脚本创建图中所示的对话框。单击 'Add' 时,应该会出现 'Button pressed.' 行,但什么也没有发生。

TagGroup dialog_items;
TagGroup dialog_tags = DLGCreateDialog("Test dialog", dialog_items);

TagGroup group = DLGCreateGroup();
group.DLGIdentifier("group");
dialog_items.DLGAddElement(group);

TagGroup label = DLGCreateLabel("Press the 'Add' button.");
group.DLGAddElement(label);

TagGroup add = DLGCreatePushButton("Add", "addButtonPressed");
group.DLGAddElement(add);

class TestDialog : UIFrame{
    void addButtonPressed(object self){
        TagGroup g = self.LookUpElement("group");
        TagGroup l = DLGCreateLabel("Button pressed.");
        g.DLGAddElement(l);

        self.ValidateView(); // <- does nothing

        // self.close();
        // self.display(""); // <- doesn't show as modal

        // self.close();
        // self.pose(); // <- doesn't show up, forces to restart GMS
    }
}

Object dialog = alloc(TestDialog).init(dialog_tags);

dialog.Pose();

The script dialog model in DM-scripting is very limited and does not support adding or removing items during display (as of GMS 3.4).

也许可以通过大量努力来解决该问题,但总的来说,花太多时间制作脚本对话框 "pretty" 通常是不值得的。

您能做的最好的事情就是利用现有项目的 shown 属性来显示或隐藏它们。

参见示例:

class CElementHideTest : UIframe
{
    TagGroup BuildDialog(object self)
    {
        TagGroup dlg,dlgItems
        dlg = DLGCreateDialog("test",dlgitems)

        TagGroup group = DLGCreateGroup().DLGIdentifier("group")
        dlgitems.DLGAddElement(group)

        TagGroup label = DLGCreateLabel("Toggle tests")
        group.DLGAddElement(label)

        TagGroup toggleEnabledButton = DLGCreatePushButton("Toggle Enabled", "toggleEnabled")
        group.DLGAddElement(toggleEnabledButton)

        TagGroup toggleShownButton = DLGCreatePushButton("Toggle Shown", "toggleShown")
        group.DLGAddElement(toggleShownButton)

        TagGroup field1 = DLGCreateIntegerField(5,5).DLGIdentifier("field")
        dlgitems.DLGAddElement(field1)

        return dlg
    }

    void toggleEnabled(object self)
    {
        number is = self.GetElementIsEnabled("field")
        self.SetElementIsEnabled("field",!is)
    }

    void toggleShown(object self)
    {
        number is = self.GetElementIsShown("field")
        self.SetElementIsShown("field",!is)
    }

    object Init(object self)
    {
        return self.Init(self.BuildDialog())
    }
}

Alloc(CElementHideTest).init().Pose()

虽然可以在显示时调整对话框 window 的大小,但这对模态对话框没有多大用处,因为 OK | 的位置取消按钮在启动时固定。因此,您只能创建一个 "ugly" 对话框,其中包含许多空的 space 项目将出现在其中。

但是,如果您的脚本 运行 在后台线程上运行,则您可以创建自己的模态对话框,如下例所示。这将允许您在显示项目时使用 window 调整大小和 shrink/extend 对话框。

注意,这不能在主线程中的脚本上工作,因为对话框显示代码 也在主线程中 运行s。因此,等待对话框会阻止对话框正确显示。

Class CScriptModalDialog : UIFrame
{
    object contSignal

    TagGroup BuildDialog(object self)
    {
        TagGroup dlg,dlgItems
        dlg = DLGCreateDialog("test",dlgitems)

        TagGroup group = DLGCreateGroup().DLGIdentifier("group")
        dlgitems.DLGAddElement(group)

        TagGroup label = DLGCreateLabel("Display as modal dialog")
        group.DLGAddElement(label)

        TagGroup toggleEnabledButton = DLGCreatePushButton("Continue", "ContinuePressed")
        group.DLGAddElement(toggleEnabledButton)

        contSignal = NewSignal(0)

        return dlg
    }

    void ContinuePressed(object self)
    {
        contSignal.SetSignal()
    }

    number PoseScriptDlg(object self, number timeOutSec )
    {
        self.Init(self.BuildDialog())
        self.Display("Script dialog")
        object cancelSignal = NewCancelSignal()
        number success = contSignal.WaitOnSignal(timeOutSec,cancelSignal)   // Could also use Infinity() as timeout
        self.Close()
        return success
    }

    number WaitOnOK(object self)
    {
        object cancelSignal = NewCancelSignal()
        return contSignal.WaitOnSignal(1,cancelSignal)
    }
}

class CMain
{
    object continueDlg
    CMain(object self) { continueDlg=Alloc(CScriptModalDialog); }

    void RunMethod(object self)
    {
        ClearResults()
        Result("Waiting on user for 3 sec...\n")
        if ( continueDlg.PoseScriptDlg(3) )
            Result("Continue\n")
        else
            Result("TimeOut\n")
    }
}

Alloc(CMain).StartThread("RunMethod")

不是您问题的直接答案,也可能不是您想要的,但作为一个想法提供者: 如果您只想选择最多四张图片,也可以使用现有的 Get...Images() 命令来发挥一点创意,例如 f.e:

image img1,img2,img3,img4
if (GetFourlabeledImagesWithPrompt( "Select up to 4 images.\nDouble selected images will be used once.","Titel", "first:",img1, "second:",img2,"third:",img3,"fourth:",img4))
{
    // Make list of used ID's removing doubles
    taggroup list = NewTagGroup()
    list.TagGroupSetTagAsBoolean( img1.ImageGetLabel(), 1 )
    list.TagGroupSetTagAsBoolean( img2.ImageGetLabel(), 1 )
    list.TagGroupSetTagAsBoolean( img3.ImageGetLabel(), 1 )
    list.TagGroupSetTagAsBoolean( img4.ImageGetLabel(), 1 )

    number nUsed = list.TagGroupCountTags()
    Result("\n Unique images chosen: " + nUsed)
    for( number i=0; i<nUsed; i++)
    {
        image img := FindImageByLabel( list.TagGroupGetTagLabel(i) )
        if ( img.ImageIsValid() )
        {
            Result("\n\t Image #"+i+": <"+img.ImageGetName()+">" )
        }
    }
}