2022_Q1 MakeOverChallenge:以多種方式點選滑鼠的操作這是 2022 年第一季的改造挑戰。
目標是提供一個範例、腳本或指南來完成三個任務之一(所有任務都與在 JMP 中點擊某項後啟動某些操作有關):
- 挑戰A: (用於建立用於開啟附加映像的初始資料表的映像和腳本:2022Q1_ChallengeA.zip)
- 您有: 資料表列,其中包含圖像或網站或檔案的連結(也稱為表達式)
- 您想要: 點擊該列的一個單元格並在 JMP 外部開啟連結或圖像
- 總體目標:單擊資料表單元格應該啟動一些操作
- 挑戰B : (用於開啟資料表並建立附加報表的腳本:2022Q1_ChallengeB_starterScript.jsl)
- 您有:大類和按身高體重計算的圖形產生器報告(請參閱腳本)
- 您想要:關閉圖形產生器報告應開啟「年齡」的分佈報告,將此報告另存為圖片並關閉分佈報告。
- 總體目標:關閉視窗應該觸發一些操作
- 挑戰C: (用於開啟資料表並建立附加報表的腳本:2022Q1_ChallengeC_starterScript.jsl)
- 您有: 關於生長測量樣本數據的圖形產生器報告。
- 您想要:當單擊一行或選擇多行(或圖例中的類別)時,您希望產生所選行的子集。
- 總體目標:點擊圖表或報告應觸發某些操作
您可以嘗試任意數量的挑戰。 您可以/應該直接提交您的答案作為對此主題的回應。
!!! 提交時,請在第一行開始說明您的回覆所指的挑戰,例如
挑戰A:
這就是我的答案...
// this is my code
...
在下次會議(2022 年 5 月 18 日)中,我們將提出一些答案,我將標記最佳答案作為該主題的解決方案。
期待您的來稿:)
回覆:2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作我將簡要概述我今天在會議上談到的內容。 您可以在本主題的早期帖子中查看我的完整解決方案。 我將修改我的挑戰 A 解決方案以使用 JMP 的 SAMPLE_IMAGE 資料夾,因此您應該能夠直接運行它。
挑戰 A:點擊資料表單元格應該啟動一些操作<BR />
概念:使用事件處理程序列屬性
透過讓 JMP 為您編寫腳本,這相當容易做到。 例如,為網頁新增事件處理程序,然後修改腳本以更好地滿足您的需求。 以下是我關於如何在單元格中打開圖像的範例解決方案。
Column(dtx, "Picture") << Add Column Properties(
Set Property(
"Event Handler",
Event Handler(
Click(JSL Quote(Function({thisTable, thisColumn, iRow}, {},
New Window(Char(thisTable:"File Name"n[iRow]), New Image(thisTable:thisColumn[iRow]));
))),
Tip(JSL Quote(Function({thisTable, thisColumn, iRow}, {},
"Enlarge image " || Char(thisTable:"File Name"n[iRow]);
)))
)
)
);
事件處理程序可以相當強大,例如您可以在單元格單擊時從資料庫查詢資料。
挑戰 B:關閉視窗應該觸發一些操作
概念:使用<< 關閉時()</CODE></P>
<P><CODE class=" language-jsl">
此挑戰的想法是在圖形生成器關閉時執行操作。 這是使用 << On Close() 執行的相當簡單的任務。 以下是由 提供的解決方案的稍微修改版本@羅布
gb << On Close(
dist = dt << Distribution(Nominal Distribution(Column(:age)));
image = dist << Get Picture;
image << Save Picture($temp/age_dist.png, "png");
dist << Close Window();
);
需要考慮的一件事是,當您使用對資料表(在本例中為 dt)的參考時,如果您在關閉 gb 之前開啟新表,則很可能會關閉錯誤的表。
您可以在此範例腳本中看到此問題:
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
biv = dt << Bivariate(Y(:Weight), X(:Height), Nonpar Density);
biv << On Close(
close(dt, no save);
);
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
此腳本透過使用 Eval(EvalExpr()) 和 Expr() 來取得對錶的明確參考提供了一個可能的解決方案
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
biv = dt << Bivariate(Y(:Weight), X(:Height), Nonpar Density);
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
Eval(EvalExpr(
biv << On Close(
Close(Expr(biv << Get Data Table), no save)
);
));
您也可以將函數與On Close 一起使用,但在這種情況下,它將產生更複雜的程式碼,因為您將無法存取雙變量平台的引用,而是存取具有雙變量的窗口,因此您必須解析視窗可能有效也可能無效的名稱(可能有一種方法可以獲得視窗內平台的引用)。
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
biv = dt << Bivariate(Y(:Weight), X(:Height), Nonpar Density);
biv << On Close(function({this},
table_name = Trim Whitespace(Word(1, (this << Get Window Title), "-"));
If(Contains(Get Data Table List() << get name, table_name),
Close(Datatable(table_name), no save);
);
));
挑戰 C:點擊圖表或報告應觸發某些操作
概念:使用<< 建立行狀態處理程序()
</CODE></P>
<P>這有很多不同的解決方案,而且都有點不同。 <STRONG>此類腳本的一大挑戰是決定如何管理不斷變化的行狀態。</STRONG> 一種選擇是使用按鈕來觸發操作(例如<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/15435" target="_blank">@雷塞爾</A>did)而不是行狀態處理程序,我認為這是這種情況下最強大的選擇。</P>
<P> </P>
<P>其餘的解決方案確實使用行狀態處理程序和不同的方式(或不使用)來管理始終更改的選定行。 <STRONG>行狀態處理程序需要注意的一件事是它將返回修改後的行,</STRONG>不僅僅是選定的行。 因此,如果您只對選定的列感興趣,則必須考慮到這一點。</P>
<P> </P>
<P>在大多數簡單的情況下,您可以使用類似的東西<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/9474" target="_blank">@喬治</A>給出了答案。</P>
<PRE><CODE class=" language-jsl">f = Function({a},
dt << Subset(Selected Rows(1), Selected columns only(0))
);
rs = dt << make row state handler(f);
管理行的一種選擇是建立關聯數組( JMP 允許使用矩陣作為關聯數組中的鍵),其中收集已建立子集的行。 只要您不更改行順序或新增/刪除行,這就應該有效。
下面是一個使用關聯數組來收集已子集化的行的快速範例。 在範例中,我正在檢查行狀態為 1(所選行)的行,然後建立這些行的子集(如果尚未建立)。 這樣做的一個好處是,您還可以將資料表引用儲存到關聯數組,並透過以下方式快速存取它們: aa_subset_rows << 取得值;但如果透過按住滑鼠並將滑鼠拖曳到多行上來選擇多行,則此解決方案可能仍然有點問題。
Names Default To Here(1);
// Open Data Table
dt = Open("$SAMPLE_DATA/Growth Measurements.jmp", invisible);
gb = dt << Graph Builder(
Size(522, 452),
Show Control Panel(0),
Legend Position("Bottom"),
Graph Spacing(8),
Variables(X(:Age), Y(:Growth), Overlay(:Subject)),
Elements(Line(X, Y, Legend(13)))
);
aa_subset_rows = Associative Array();
f = Function({rows_changed},
//Rowstate 1 is selected row
cur_rows = Loc(dt << Get Row States, 1);
//if no rows are selected, don't try to create subsets
If(N Items(cur_rows) == 0,
return()
);
//compare to previous to prevent opening extensive abmount of subsets
If(Contains(aa_subset_rows , cur_rows),
return();
);
dt_subset = dt << Subset(Output table("selected_rows"), Rows(cur_rows));
aa_subset_rows[cur_rows] = dt_subset;
);
rs = dt << make row state handler(f);
回覆:2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作挑戰C:
我絕對建議使用按鈕做這樣的事情,因為它可以防止創建太多子集。 但在這裡,我遵循了給定的挑戰,並添加了簡單的檢查,確保我們至少不會創建相同的子集兩次。
看更多...
使用行狀態處理程序,我們無法存取滑鼠釋放事件,因此如果用戶從圖中逐條選擇多行,我們仍然會創建許多子集(可能有一種方法可以使用Mouse Box() 來做到這一點,但我認為使用按鈕會變得更簡單、更容易)。
回覆:2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作挑戰B:
看更多...
Names Default To Here(1);
// 2022_Q1 MakeOverChallenge: Action on mouse click in various ways
// Challenge B
dt = Open("$SAMPLE_DATA/Big Class.jmp");
//Use expression to make script a bit more clean IF this were to be expanded
create_dist = Expr(
dist = dt << Distribution(Nominal Distribution(Column(:age)), Histograms Only);
wait(1); // add wait so we can see that distribution is created
dist << Save Picture("$TEMP/Big_Class_age_dist.png", png);
dist << Close Window;
);
gb = dt << Graph Builder(
Size(528, 454),
Show Control Panel(0),
Variables(X(:height), Y(:weight)),
Elements(Points(X, Y, Legend(3)), Line Of Fit(X, Y, Legend(5)))
);
gb << On Close(create_dist);
// Open("$TEMP/Big_Class_age_dist.png"); // un-comment to open the image
名稱預設為此處(1); // 2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作 // 挑戰 B dt = Open("$SAMPLE_DATA/Big Class.jmp"); //使用表達式使腳本更加簡潔,如果要擴展的話 create_dist = Expr( dist = dt << Distribution(Nominal Distribution(Column(:age)), Histograms Only); wait(1); // 添加等待,我們可以看到分佈已建立dist << Save Picture("$TEMP/Big_Class_age_dist.png", png); dist << Close Window; ); gb = dt << 圖形產生器( 大小(528, 454), 顯示控制面板(0), 變數(X(:高度), Y(:重量)), 元素(點(X, Y, 圖例(3) ) , 擬合線(X, Y, 圖例(5))) ); gb << 關閉時(create_dist); // 開啟("$TEMP/Big_Class_age_dist.png"); // 取消註解以開啟圖像
回覆:2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作挑戰A:
主要是使用「新增列屬性」編寫的 JMP 程式碼。 還添加瞭如何添加和打開 URL 的範例
看更多...
Names Default To Here(1);
// Challenge A
path = "2022Q1_ChallengeA"; // path to images
{dtx} = Multiple File Import(
<<SET folder=""></SET>
名稱預設為此處(1); // 挑戰A路徑 = "2022Q1_ChallengeA"; // 映像路徑{dtx} = 多個檔案導入( <<設定資料夾( path ), <<設定名稱過濾器( "*.jpg; *.png;" ), <<設定名稱啟用( 1 ), <<設定新增檔案名列( 1 ), <<設定新增檔案大小列( 1 ) // 用於在最後顯示大小 ) << 匯入資料; // 因為圖片已經在資料表中,所以我們不需要從磁碟機開啟它們,我們只需將圖片載入到新視窗即可Column(dtx, "Picture") << Add Column Properties( Set Property( "Event Handler ", 事件處理程序( Click(JSL Quote(Function({thisTable, thisColumn, iRow}, {}, New Window(Char(thisTable:"檔名"n[iRow]), New Image(thisTable:thisColumn[iRow ])) ); ))), Tip(JSL Quote(Function({thisTable, thisColumn, iRow}, {}, "放大影像" || Char(thisTable:"檔案名稱"n[iRow]); ))) ) ) ) ; // 帶有一些URL 的新欄位new_col = dtx << New Column("URL", Character, Nominal, Values( {"
www.jmp.com","
www.google.com","community.jmp.com ", “
https://www.jmp.com/support/help/en/16.2/”} )); // 為我們建立的程式碼jmp,只是刪除了過多的註解new_col << Add Column Properties( Set Property( "Event Handler", Event Handler( Click(JSL Quote(Function({thisTable, thisColumn, iRow}, { } , Web(Char(thisTable:thisColumn[iRow])); ))), Tip(JSL Quote(Function({thisTable, thisColumn, iRow}, {}, "開啟" || Char(thisTable:thisColumn[iRow] ) || "在您的瀏覽器中。"; ))), Color(JSL Quote(Function({thisTable, thisColumn, iRow}, {}, RGBColor("link"); ))) ) ) );寫(); // 避免煩人的列印最後執行行的日誌
使用SAMPLE_IMAGES 路徑變數(這也可以作為一個範例,說明在編寫腳本時進行更改是多麼容易,只需更改一個變量,腳本仍然有效(我從列表中刪除了一個URL,因此不會將空行添加到其他欄位中) )):
Names Default To Here(1);
// Challenge A
path = Get Path Variable("$SAMPLE_IMAGES");
{dtx} = Multiple File Import(
<<SET folder=""></SET>
回覆:2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作挑戰C
不幸的是,就挑戰 A 和 B 而言,沒有其他可做的。 提供的解決方案似乎無可挑剔。 相較之下,我覺得挑戰C還是有一些改進的可能。 我的回答簡單說幾句
- 我基本上已經竊取了必要的程式碼從這裡( @tx尼爾森和許多其他編劇一樣,對我來說是搖滾明星)
- 我通過包含可見數據點對圖表進行了輕微修改,因此更容易選擇單獨的行
- 選擇圖中的點後,不會立即開啟包含子集的資料表。 這是透過圖表下方新增的按鈕完成的
請參閱下面的完整腳本,包括修改後的圖表。
// Open Data Table
dt = Open( "$SAMPLE_DATA/Growth Measurements.jmp",invisible );
// Report snapshot: Growth Measurements - Graph Builder
gb = dt << Graph Builder(
Size( 522, 452 ),
Show Control Panel( 0 ),
Legend Position( "Bottom" ),
Graph Spacing( 8 ),
Variables( X( :Age ), Y( :Growth ), Overlay( :Subject ) ),
Elements(
Points( X, Y, Legend( 17 ), Jitter Limit( 0 ) ), // added markers
Line( X, Y, Legend( 13 ) ) ),
SendToReport( // increased markers to decent size
Dispatch(
{},
"Graph Builder",
FrameBox,
{Marker Size( 6 ), Marker Drawing Mode( "Normal" )}
)
)
);
// my solution (stolen from here: https://community.jmp.com/t5/Discussions/Creating-a-Subset-from-an-Interactive-Graph/td-p/114459)
subsetButton = Button Box( "Dear user, Please press here to create a Subset of the Selected Points immediately",
If( N Rows( dt << get selected rows ) > 0,
dt << subset( selected rows( 1 ), selected columns( 0 ) )
)
);
Report( gb )["Graph Builder"] << append( subsetButton );
回覆:2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作挑戰A
抱歉,我最初的解決方案太倉促了... 這是一個更乾淨的。
Names Default to Here ( 1 );
//path = <YOUR full="" path="" to="" where="" the="" images="" have="" been="" saved="">;
// eg.
// path = "C:\EventHandlerImages\";
path = "$DOCUMENTS\Scripting\2022Q1\ChallengeA\2022Q1_ChallengeA\";
//==========================================================================
//Multiple File Import is new in JMP 14
{dtx} = Multiple File Import(
<<SET folder=""></SET></YOUR>回覆:2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作挑戰A:
筆記:我保留了這個舊版本,因為有些人已經看過它,但我發布了一個更乾淨的解決方案作為回覆到這個。
根本不是一個漂亮的解決方案,但它確實完成了工作... 期待更優雅的出現!
這要加入 starterScript 之後:
// Defining the file name for an image placeholder for displaying on the OS when clicking:
pictFileName = Get Default Directory() || "verylonganduselessname.png"; //name for the temp image file (to be deleted at the end)
dtx:Picture << Set Property("tmpFileName", pictFileName); //saving the name so it can be retrieved from within the table
dtx << On Close( Delete File(pictFileName) ); //make sure we erase the temp image file at the end.
// Setting a Click event handler for the column of interest:
dtx:Picture << Set Property(
"Event Handler",
Event Handler(
Click(JSL Quote( Function(
{thisTable, thisColumn, iRow},
pictFileName = thisTable:thisColumn<< Get Property("tmpFileName"); //recover the path for a temp file
thisTable:thisColumn[iRow] << Save Image( pictFileName ); //save cell contents to temp file
Web( "file://" || pictFileName ) // open the image file
)
)
),
Tip(JSL Quote( Function(
{thisTable, thisColumn, iRow},
"click to open";
)
)
)
)
);
回覆:2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作挑戰C
使用滑鼠框無法選擇某些內容,因此我變更為行狀態處理程序
Names Default To Here( 1 );
// Open Data Table
dt = Open( "$SAMPLE_DATA/Growth Measurements.jmp", invisible );
// Report snapshot: Growth Measurements - Graph Builder
gb = dt << Graph Builder(
Size( 522, 452 ),
Show Control Panel( 0 ),
Legend Position( "Bottom" ),
Graph Spacing( 8 ),
Variables( X( :Age ), Y( :Growth ), Overlay( :Subject ) ),
Elements( Line( X, Y, Legend( 13 ) ) )
);
active_subset = "";
first_subset = "false";
rsh = dt << make row state handler(
Function( {a},
subtbl = dt << Subset( Selected Rows( 1 ) );
gb << Bring Window To Front;
if(
first_subset == "true",
close(active_subset, no save)
);
active_subset = subtbl;
first_subset = "true";
)
);
回覆:2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作挑戰C
這是我的答案,請參閱下面的完整腳本。
下半部向表格新增行狀態處理程序,該處理程序觸發操作(請參閱腳本索引中的範例)。
Names Default To Here( 1 );
// Open Data Table
dt = Open( "$SAMPLE_DATA/Growth Measurements.jmp", invisible );
// Report snapshot: Growth Measurements - Graph Builder
gb = dt << Graph Builder(
Size( 522, 452 ),
Show Control Panel( 0 ),
Legend Position( "Bottom" ),
Graph Spacing( 8 ),
Variables( X( :Age ), Y( :Growth ), Overlay( :Subject ) ),
Elements( Line( X, Y, Legend( 13 ) ) )
);
// This is my code (Georg)
// (see Scripting Index "Make Row State Handler")
// Define a function, that does the action
f = Function( {a},
Current Data Table() << Subset( Selected Rows( 1 ), Selected columns only( 0 ) )
);
// Set up a row state handler, that triggers the execution of a function on any change of row states,
// a change on row selection by clicking on a line in Graph Builder is a change of row states in the table
rs = dt << make row state handler( f );回覆:2022_Q1 MakeOverChallenge:以各種方式點選滑鼠的操作挑戰B
將其添加到腳本的底部:
gb << On Close(
dist = dt << Distribution( Nominal Distribution( Column( :age ) ) );
image = dist << Get Picture;
path = "$temp/age_dist.png";
image << Save Picture( path, "png" );
dist << Close Window();
Open( path );
);