使行状态处理程序无法在数据过滤器上下文框中按预期工作亲爱的社区,
我尝试使用数据过滤器上下文/源框构建仪表板,
并且它在一些细节上的运作正如预期。
但我需要额外的功能,根据选择,我需要过滤位于选项卡页框详细信息1中的附加表。
我每次都会在该上下文中使用 Make Row State Handler 来重新创建。
在 Tabulate 中选择单行时,一切都很好,但是:
- 当我取消选择全部时,标签页框不会改变
- 当我在 Tabulate 中选择多行时,Tab Page Box 中会出现错误选择
- 当我在 GraphBuilder 中选择点时,表格生成过多
- ...
如何使这个场景更加健壮?
是否有不同的方法(无行状态处理程序)来获取 Tabulate and Graph Builder 中的选定行?
有没有更好的策略来做这样的事情?
非常感谢,BR
Names Default To Here( 1 );
Clear Log();
dt = Open( "$SAMPLE_DATA\Big Class.jmp" );
dt << show window( 0 );
tabulate_expr = Expr(
tb_obj = dt << Tabulate( Show Control Panel( 0 ), Add Table( Row Table( Grouping Columns( :sex, :age ) ) ) )
);
gb_expr = Expr(
gb_obj = dt << Graph Builder(
Show Control Panel( 0 ),
Variables( X( :weight ), Y( :height ) ),
Elements( Points( X, Y, Legend( 3 ) ), Smoother( X, Y, Legend( 4 ) ) )
)
);
action_expr = Expr(
Button Box( "Start Analysis", Print( pb_details << get row states() ) )
);
nw = New Window( "Dashboard",
Data Filter Context Box(
H List Box(
V List Box(
H List Box(
Panel Box( "Filter (in Data Filter Source Box)", /* Filter and GB */ dfsb =
Data Filter Source Box( tabulate_expr )
),
Panel Box( "Graph Builder (to be filtered in context", gb_expr )
),
Panel Box( "Action", /* Action */ action_expr )
),
pb_details = Panel Box( "Details (as well in data filter context box)", /* Tab Box */
Tab Box(
Tab Page Box( "Details1 (Data Grid Box, update via Make Row State Handler)", dgb = Data Grid Box() ),
Tab Page Box( "Details2 (Filtered automatically)", tabulate_expr )
)
)
)
)
);
detail_dt = dt << subset( invisible, columns( {"name", "age", "sex"} ) );
dgb << set data table( detail_dt );
dgb << close side panels;
nw << on close(
Close( dt, NoSave );
Close( detail_dt, NoSave );
For Each( {dt}, detail_dt_lst, Try( Close( dt, NoSave ) ) );
);
last_a = []; /* remember last selection to avoid double action */
detail_dt_lst = {}; /* save all table references to be able to close later */
details_update = Function( {a},
If( Is Matrix( a ) & Char( a ) != Char( last_a ),
Show( a );
detail_old = dgb << Get Data Table();
detail_dt = dt << subset( invisible, columns( {"name", "age", "sex"} ) );
Insert Into( detail_dt_lst, detail_dt );
detail_dt << select rows( a ) << delete rows();
dgb << set data table( detail_dt );
dgb << close side panels;
Close( detail_old, NoSave );
last_a = a;
);
);
rsh = pb_details << Make Row State Handler( dt, details_update );
自动化和脚本视窗回复:使行状态处理程序无法在数据过滤器上下文框中按预期工作在我看来,行状态处理程序存在许多不同的问题,以至于您无法使它们变得健壮(例如,它们太容易被删除、触发太多以及许多其他问题)。为了避免您看到的一些问题,请不要使用行状态处理程序函数中可以拥有的参数(在您的例子中为 a ) ,而是使用 << 获取选定的行。
所以您想要有带有制表和图形生成器的仪表板,并且这些应该过滤数据表?有必要有一个正在过滤的数据表吗?避免所有问题的最简单方法是利用按钮框来更新表格。
回复:使行状态处理程序无法在数据过滤器上下文框中按预期工作根据您的实际用例,这里有一个可能有效的选项。它依赖于更新子集而不是重新创建它。它还将检查选定的行,而不是依赖“a”参数
Names Default To Here(1);
dt = Open("$SAMPLE_DATA\Big Class.jmp", Invisible);
tabulate_expr = Expr(
tb_obj = dt << Tabulate(
Show Control Panel(0),
Add Table(Row Table(Grouping Columns(:sex, :age)))
)
);
gb_expr = Expr(
gb_obj = dt << Graph Builder(
Show Control Panel(0),
Variables(X(:weight), Y(:height)),
Elements(Points(X, Y, Legend(3)), Smoother(X, Y, Legend(4)))
)
);
action_expr = Expr(
Button Box("Start Analysis", Print(pb_details << get row states()))
);
nw = New Window("Dashboard",
Data Filter Context Box(
H List Box(
V List Box(
H List Box(
Panel Box("Filter (in Data Filter Source Box)",
dfsb = Data Filter Source Box(tabulate_expr)
),
Panel Box("Graph Builder (to be filtered in context",
gb_expr
)
),
Panel Box("Action",
action_expr
)
),
pb_details = Panel Box("Details (as well in data filter context box)",
Tab Box(
Tab Page Box(
"Details1 (Data Grid Box, update via Make Row State Handler)",
dgb = Data Grid Box()
),
Tab Page Box("Details2 (Filtered automatically)",
tabulate_expr
)
)
)
)
)
);
detail_dt = dt << subset(invisible, columns({"name", "age", "sex"}));
dgb << set data table(detail_dt);
dgb << close side panels;
nw << on close(
Close(dt, NoSave);
Close(detail_dt, NoSave);
);
last_rows = {}; // use list as you can compare those directly
extra_triggers = 0;
details_update = Function({a},
// Write("\!N", Round(Tick Seconds(), 2), " \!thappy state handler triggering");
// Show(dt << Get Row States);
cur_rows = As List(dt << Get Selected Rows);
If(N Items(cur_rows) == 0,
cur_rows = As List((1::N Rows(dt))`); // same as all rows selected
);
If(cur_rows == last_rows,
extra_triggers++;
return();
);
Write("\!N", extra_triggers, " unnecessary triggers occured.");
extra_triggers = 0;
last_rows = cur_rows;
If(N Rows(detail_dt) > N Items(cur_rows),
detail_dt << Delete Rows(N Items(cur_rows) + 1::N Rows(detail_dt));
, N Rows(detail_dt) < N Items(cur_rows),
detail_dt << Add Rows(N Items(cur_rows) - N Rows(detail_dt));
);
detail_dt[0, {"name", "age", "sex"}] = dt[Matrix(last_rows), {"name", "age", "sex"}];
);
rsh = pb_details << Make Row State Handler(dt, details_update);
这不是实现这一目标的唯一方法,但这是一个您可以尝试的非常简单的选项。
希望状态处理程序在某些时候可用的愿望清单项: 改进 JMP 的状态处理程序(悬停标签、行状态处理程序、过滤器状态处理程序、调度程序......)
回复:使行状态处理程序无法在数据过滤器上下文框中按预期工作一个令人困惑的地方是< < m>是如何解释参数的。向量表示已更改的行,但它并未说明它们处于什么状态。您还将收到非过滤事件的回调 - 例如:对表中的选择、标签或标记行状态的更改。这确实使得将响应限制在感兴趣的事件上变得困难。
基于此背景,我认为原始脚本的主要问题是(1)当使用相同参数连续调用该函数时没有响应(这就是清除不起作用的原因)和(2)使用行号作为要删除的行。
下面的脚本(注意:仅限 JMP 18+)不会尝试跟踪和限制变化,但它应该正确响应从子集中删除的实际排除行。
Names Default To Here( 1 );
Clear Log();
//https://community.jmp.com/t5/Discussions/Make-Row-State-Handler-not-working-as-expected-in-a-Data-Filter/m-p/791520
dt = Open( "$SAMPLE_DATA\Big Class.jmp" );
dt << show window( 0 );
tabulate_expr = Expr(
tb_obj = dt << Tabulate( Show Control Panel( 0 ), Add Table( Row Table( Grouping Columns( :sex, :age ) ) ) )
);
gb_expr = Expr(
gb_obj = dt << Graph Builder(
Show Control Panel( 0 ),
Variables( X( :weight ), Y( :height ) ),
Elements( Points( X, Y, Legend( 3 ) ), Smoother( X, Y, Legend( 4 ) ) )
)
);
action_expr = Expr(
Button Box( "Start Analysis", Print( pb_details << get row states() ) )
);
nw = New Window( "Dashboard",
Data Filter Context Box(
H List Box(
V List Box(
H List Box(
Panel Box( "Filter (in Data Filter Source Box)", /* Filter and GB */ dfsb =
Data Filter Source Box( tabulate_expr )
),
Panel Box( "Graph Builder (to be filtered in context", gb_expr )
),
Panel Box( "Action", /* Action */ action_expr )
),
pb_details = Panel Box( "Details (as well in data filter context box)", /* Tab Box */
Tab Box(
Tab Page Box( "Details1 (Data Grid Box, update via Make Row State Handler)", dgb = Data Grid Box() ),
Tab Page Box( "Details2 (Filtered automatically)", tabulate_expr )
)
)
)
)
);
detail_dt = dt << subset( invisible, columns( {"name", "age", "sex"} ) );
dgb << set data table( detail_dt );
dgb << close side panels;
nw << on close(
Close( dt, NoSave );
Close( detail_dt, NoSave );
For Each( {dt}, detail_dt_lst, Try( Close( dt, NoSave ) ) );
);
detail_dt_lst = {}; /* save all table references to be able to close later */
details_update = Function( {a},
Show( a );
If( Is Matrix( a ),
detail_old = dgb << Get Data Table();
detail_dt = dt << subset( invisible, columns( {"name", "age", "sex"} ) );
Insert Into( detail_dt_lst, detail_dt );
filter_state = pb_details << Get Row States(dt);
detail_dt << select rows( Where(Excluded(As Row State(filter_state))) ) << delete rows();
dgb << set data table( detail_dt );
dgb << close side panels;
Close( detail_old, NoSave );
);
);
rsh = pb_details << Make Row State Handler( dt, details_update );
回复:使行状态处理程序无法在数据过滤器上下文框中按预期工作感谢您的建议,按钮框可能是一个解决方案。
我有两个选择:
(1)在启动 GUI 时加载我可能需要的所有详细信息,将它们保存为隐藏表并在特定上下文中显示我需要的部分,在这里我将使用 rowstate 等动态解决方案。
(2)根据请求从数据库加载数据(这里我会选择按钮解决方案)。
但这个案例对我来说总体来说很有趣,因为有很多类似的案例,我更喜欢 (1) 或 (2),而且我想更好地了解 JMP 如何使用它。
回复:使行状态处理程序无法在数据过滤器上下文框中按预期工作非常感谢您的意见@jthi和@danschikore ,这给了我一些改进仪表板的好想法。