您好,我一直在努力尝试制作类似(JMP Pro)SEM 和可靠性框图中使用的拖放界面。
我的想法是在屏幕左侧放置一排“方框”。我希望能够选中其中一个方框,把它拖到屏幕中央区域,放下,然后再选中另一个方框,继续拖放,以此类推。
我试过好几种方法,包括用把手和捕鼠器。我能做到一部分,但做不到全部。
下面展示的是我使用 Mousetrap 编写的最新代码。我可以抓住 GraphBox 左上角的方框,把它拖动到屏幕上的任何位置,然后放到我想要的位置(放置后会变成黑色)。但是之后我就无法再抓住另一个方框了。我只能移动刚刚放置的方框,无法添加新的方框。
我目前正在将其开发成应用程序,但如果这样有帮助,我很乐意更改。
以下脚本展示了我在应用程序构建器中编写的代码。附件包含完整的应用程序。
我担心我对 Mousetrap、GraphBoxes 和添加图形脚本的某些方面还不理解。有人能帮帮我吗?
// This script is executed when a new module instance is
// created. The pre-defined object "thisModuleInstance" refers
// to the instance object, but other objects such as boxes and
// scripts have not yet been created. Variables declared here are
// scoped to the ModuleInstance namespace.
// This special function will receive parameters passed to CreateInstance()
OnModuleLoad({},
);
thisModuleInstance << Create Objects;
// After this point your module instance objects have been created
// and can be referred to by name (for example, "Button1").
x0=5;
y0=95;
winref = (this module instance << Get Box);
// set graph box scales
winref[framebox(1)] << xaxis(0,100);
winref[framebox(1)] << yaxis(0,100);
// draw box in upper left corner.
pen color("Green");
winref[framebox(1)] << add graphics script(
pen color("Green");
Line({0,90}, {10,90},{10,100}, {0,100},{0,90}));
winref[framebox(1)] << Add Graphics Script(
Mousetrap(
// drag script (mouse down)
(
// if mouse location is within box in upper left corner, then OK to drag.
if(
and(
x>=x0-5,
y>=y0-5,
x<=x0+5,
y<=y0+5
),
(
// set x0 and y0 if that were true
x0 = x;
y0 = y;
// redraw the box at current mouse location while mouse button is down
winref[framebox(1)] << add graphics script(
"Front",
pen color("Green");
Line({x0-5, y0-5}, {x0+5, y0-5}, {x0+5, y0+5}, {x0-5, y0+5}, {x0-5, y0-5}));
)
);
),
(
// mouse up script
// draw a polygon centered at the current mouse location
winref[framebox(1)] << add graphics script(
polygon({x0-5,y0-5},{x0+5,y0-5},{x0+5,y0+5},{x0-5,y0+5},{x0-5,y0-5})
);
// at this point I want to manually reposition the mouse over the original box in the
// upper left, and grab another box.
// Instead, all I can do is grab the box I just created and drag it somewhere else.
)
);
);
您很可能不想一直添加新的图形脚本,因为这最终会覆盖您的 If() 函数并“淹没”帧框。

你可以用更好的方式来实现这个功能,但下面是一个你可以尝试的示例。
Names Default To Here(1);
rects = {};
x0 = 5;
y0 = 95;
x = .;
y = .;
nw = New Window("Example",
Graph Box(
Frame Size(200, 200),
Mousetrap(
x0 = x;
y0 = y;
,
p = EvalExpr(Polygon(
{Expr(x0+5), Expr(y0-5)},
{Expr(x0+5), Expr(y0+5)},
{Expr(x0-5), Expr(y0+5)},
{Expr(x0-5), Expr(y0-5)}
));
Insert Into(rects, Name Expr(p));
);
Pen color("Green");
Line({0,90}, {10,90},{10,100}, {0,100},{0,90});
If(x >= x0 - 5 & y >= y0 - 5 & x <= x0 + 5 & y <= y0 + 5,
Pen color("Green");
Line({x0-5, y0-5}, {x0+5, y0-5}, {x0+5, y0+5}, {x0-5, y0+5}, {x0-5, y0-5});
);
For(i = 1, i <= N Items(rects), i++,
Pen Color("Black");
Eval(rects[i]);
);
);
);
</CODE></P>
<P><SPAN class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="jthi_1-1766523967638.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1766523967638.png" style="width: 260px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1766523967638.png" style="width: 260px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1766523967638.png" style="width: 260px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1766523967638.png" style="width: 260px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1766523967638.png" style="width: 260px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1766523967638.png" style="width: 260px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1766523967638.png" style="width: 260px;"><span class="lia-inline-image-display-wrapper" image-alt="jthi_1-1766523967638.png" style="width: 260px;"><img src="https://us.v-cdn.net/6038925/uploads/images/89563i0F98FCB07A4441BC/jthi_1-1766523967638.png" role="button" title="jthi_1-1766523967638.png" alt="jthi_1-1766523967638.png" /></span></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></P>
<BR />
<P>编辑:添加了 x 和 y 的初始化</P>
</LINGO-BODY>
<LINGO-SUB id="lingo-sub-921160" slang="en-US" mode="UPDATE" translate="no">回复:制作拖放脚本</LINGO-SUB>
<LINGO-BODY id="lingo-body-921160" slang="en-US" mode="UPDATE">
<P>我得到:</P>
<P><FONT face="courier new,courier">显示框[EvalContextBox]</FONT><BR /><FONT face="courier new,courier">名称未解析:访问或评估“x”时出现 x 错误,x/*###*/</FONT></P>
<P><FONT face="courier new,courier">第 26 行</FONT><BR /><BR /></P>
<P>x&y 在捕鼠器之外是否仍然存在?</P>
<P><SPAN class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="hogi_0-1766525524905.png" style="width: 999px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="hogi_0-1766525524905.png" style="width: 784px;"><span class="lia-inline-image-display-wrapper" image-alt="hogi_0-1766525524905.png" style="width: 784px;"><img src="https://us.v-cdn.net/6038925/uploads/images/89564iE967B41113B5D41E/hogi_0-1766525524905.png" role="button" title="hogi_0-1766525524905.png" alt="hogi_0-1766525524905.png" /></span></SPAN></SPAN></P>
<P><STRONG>编辑</STRONG>:<BR />它们“在捕鼠器之外依然存在”<BR />但并非永久如此。似乎当鼠标按钮松开时,它们就会重置:<BR /> <A href="https://community.jmp.com/t5/Discussions/Can-JMP-graphics-have-this-effect/m-p/921213/highlight/true#M107999" target="_blank">https://community.jmp.com/t5/Discussions/Can-JMP-graphics-have-this-effect/mp/921213/highlight/true#M107999</A></P>
<BR />
<P>太棒了,有了绿色矩形,拖拽的错觉非常逼真;)<BR />如果没有绿色矩形,感觉就像是:每次鼠标点击都会添加一个黑色矩形。</P>
<P></P>
<iframe src="https://players.brightcove.net/6058004218001/default_default/index.html?videoId=6386912122112" width="280" height="280" allowfullscreen allow="encrypted-media"></iframe>
<P></P>
</LINGO-BODY>
<LINGO-SUB id="lingo-sub-921187" slang="en-US" mode="CREATE" translate="no">回复:制作拖放脚本</LINGO-SUB>
<LINGO-BODY id="lingo-body-921187" slang="en-US" mode="CREATE">
<P>我之前很可能在内存中初始化了 x 和 y 的值,所以脚本才无法运行。我已经更新了脚本,重新初始化了 x 和 y 的值,现在在新的 JMP 会话中似乎可以正常工作了。</P>
</LINGO-BODY>
<LINGO-SUB id="lingo-sub-921211" slang="en-US" mode="CREATE" translate="no">回复:制作拖放脚本</LINGO-SUB>
<LINGO-BODY id="lingo-body-921211" slang="en-US" mode="CREATE">
<P>感谢<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/14366" target="_blank">@jthi</A> (以及<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/26800" target="_blank">@hogi</A>的贡献)!我应该能够根据我的需求进行调整。在这个过程中,我还了解了一些关于 Mousetrap、Add Graphics Script 和 Name Expr 的知识。</P>
<P>JMP社区的响应速度和专业知识总是让我惊叹不已。非常感谢!</P>
</LINGO-BODY>
<LINGO-SUB id="lingo-sub-921219" slang="en-US" mode="UPDATE" translate="no">回复:制作拖放脚本</LINGO-SUB>
<LINGO-BODY id="lingo-body-921219" slang="en-US" mode="UPDATE">
<P>这是<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/14366" target="_blank">@jthi</A>脚本的高级版本:</P>
<P>- 现有框可以拖动。</P>
<P>- 当用户点击没有方框的区域时,不会创建或移动任何方框。</P>
<P>- 顶部的初始盒子就像一个无限的盒子库。</P>
<P></P>
<iframe src="https://players.brightcove.net/6058004218001/default_default/index.html?videoId=6386914707112" width="276" height="280" allowfullscreen allow="encrypted-media"></iframe>
<P></P>
<BR />
<PRE><CODE class=" language-jsl">Names Default To Here( 1 );
squares = {{5, 95}};
x = .;
y = .;
mouseDown = 1;
foundOne = 0;
nw = New Window( "Example",
Graph Box(
Frame Size( 200, 200 ),
Mousetrap(
// find a neighboring square
If( mouseDown,
x0 = x;
y0 = y;
If( N Items( squares ),
kt = KDTable( Matrix( squares ) );
{row, dist} = kt << K nearest rows( {1, 10}, Matrix( {x0, y0} ) );
If( N Items( row ) & dist[1] < 10,
If( row > 1, // keep the one at the top corner
Remove From( squares, row[1] )
);
foundOne = 1;
);
);
);
mouseDown = 0;,
// mouse relesed -> save the square
If( foundOne,
Insert Into( squares, Eval List( {Eval List( {x, y} )} ) )
);
//reset
mouseDown = 1;
foundOne = 0;
);
Pen Color( "Green" );
Line( {0, 90}, {10, 90}, {10, 100}, {0, 100}, {0, 90} ); // 1st square to start with
// dragged square
If( Not( Is Missing( x ) ) & foundOne,
Line( {x - 5, y - 5}, {x + 5, y - 5}, {x + 5, y + 5}, {x - 5, y + 5}, {x - 5, y - 5} )
);
For( i = 1, i <= N Items( squares ), i++,
Pen Color( "Black" );
Eval(
{x0, y0} = squares[i];
Polygon( {x0 + 5, y0 - 5}, {x0 + 5, y0 + 5}, {x0 - 5, y0 + 5}, {x0 - 5, y0 - 5} );
);
);
)
);