2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiQuesta è la Makeover Challenge Q1 2022.
L'obiettivo è creare un esempio, uno script o una guida per eseguire una delle tre attività (tutte hanno a che fare con l'avvio di un'azione dopo aver fatto clic su qualcosa in JMP):
- Sfida A: (immagini e script per creare la tabella dati iniziale per l'apertura delle immagini allegate: 2022Q1_ChallengeA.zip)
- Hai: Una colonna della tabella dati con immagini o collegamenti a un sito Web o a un file (ovvero espressioni)
- Vuoi: fare clic su una cella di questa colonna e aprire il collegamento o l'immagine all'esterno di JMP
- L'obiettivo generale: fare clic su una cella di una tabella dati dovrebbe avviare qualcosa
- Sfida B : (script per aprire la tabella dati e creare il report allegato: 2022Q1_ChallengeB_starterScript.jsl)
- Hai: Big Class e un report del Graph Builder di peso per altezza (vedi script)
- Ciò che desideri: chiudendo il report del Costruttore di grafici dovrebbe aprire un report di distribuzione di "età", salvare questo report come immagine e chiudere il report di distribuzione.
- L'obiettivo generale: la chiusura di una finestra dovrebbe attivare un'azione
- Sfida C: (script per aprire la tabella dati e creare il report allegato: 2022Q1_ChallengeC_starterScript.jsl)
- Hai: Un report del Generatore di grafici sui dati di esempio delle misurazioni della crescita.
- Desideri: quando fai clic su una riga o selezioni più righe (o categorie nella legenda), desideri generare un sottoinsieme delle righe selezionate.
- L'obiettivo generale: fare clic su un grafico o un report dovrebbe attivare un'azione
Puoi lavorare su tutte le sfide che desideri. Puoi/dovresti inviare le tue risposte direttamente come risposta a questo thread.
!!! Quando invii, inizia dalla prima riga indicando a quale sfida si riferisce la tua risposta, ad es
SFIDA A:
Questa è la mia risposta...
// this is my code
...
Nel prossimo incontro (18 maggio 2022) presenteremo alcune delle risposte e segnerò le migliori risposte come soluzione a questo thread.
Aspetto con ansia le vostre proposte 
Ri: 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiScriverò una breve panoramica di ciò di cui ho parlato oggi nell'incontro. Puoi vedere le mie soluzioni complete nei miei post precedenti in questo argomento. Modificherò la mia soluzione Challenge A per utilizzare la cartella SAMPLE_IMAGE di JMP, quindi dovresti essere in grado di eseguirla direttamente.
Sfida A: fare clic su una cella di una tabella dati dovrebbe avviare qualcosa<BR />
Concetto: utilizzo della proprietà della colonna del gestore eventi
Questo è abbastanza semplice da fare lasciando che sia JMP a scriverlo per te. Aggiungi, ad esempio, un gestore eventi per la pagina Web e quindi modifica lo script per adattarlo meglio alle tue esigenze. Di seguito è riportata la mia soluzione di esempio su come aprire un'immagine nella cella.
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]);
)))
)
)
);
I gestori eventi possono essere abbastanza potenti in quanto potresti, ad esempio, interrogare i dati dal database facendo clic sulla cella.
Sfida B: La chiusura di una finestra dovrebbe attivare un'azione
Concetto: utilizzo << Alla chiusura()</CODE></P>
<P><CODE class=" language-jsl">
L'idea in questa sfida era eseguire un'azione quando il Costruttore di grafici è chiuso. Questo è un compito abbastanza semplice da eseguire utilizzando << On Close(). Di seguito è riportata la versione leggermente modificata della soluzione fornita da @Robbb
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();
);
Una cosa da considerare a questo proposito è che quando si utilizzano riferimenti alla tabella dati (in questo caso dt), se si apre una nuova tabella prima di chiudere gb, molto probabilmente si chiuderà la tabella sbagliata.
Puoi vedere questo problema in questo script di esempio:
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");
E questo script fornisce una possibile soluzione utilizzando Eval(EvalExpr()) ed Expr() per ottenere un riferimento esplicito alla tabella
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)
);
));
Potresti anche usare la funzione con On Close, ma in questo caso genererà un codice più complicato, poiché non avrai accesso al riferimento della piattaforma bivariata ma piuttosto alla finestra che ha la bivariata, quindi devi analizzare la finestra nome che potrebbe funzionare o meno (potrebbe esserci un modo per ottenere un riferimento alla piattaforma all'interno della finestra).
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);
);
));
Sfida C: fare clic su un grafico o un report dovrebbe attivare un'azione
Concetto: utilizzo << Crea gestore stato riga()
</CODE></P>
<P>Questo aveva soluzioni molto diverse e tutte erano leggermente diverse. <STRONG>La grande sfida con questo tipo di script è decidere come gestire gli stati delle righe in costante cambiamento.</STRONG> Un'opzione è utilizzare un pulsante per attivare l'azione (come<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/15435" target="_blank"> @Ressel</A> did) invece di Row State Handler, questa è secondo me l'opzione più efficace in questo caso.</P>
<P> </P>
<P>Il resto delle soluzioni utilizzava il gestore dello stato delle righe e diversi modi (o meno) di gestire le righe selezionate che venivano modificate continuamente. <STRONG>Una cosa da notare con Row State Handler è che restituirà le righe modificate,</STRONG> non solo righe selezionate. Quindi, se sei interessato solo alle colonne selezionate, devi tenerne conto.</P>
<P> </P>
<P>Nella maggior parte dei casi semplici puoi usare qualcosa di simile<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/9474" target="_blank"> @Georg</A> ha dato come risposta.</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);
Un'opzione per gestire le righe sarebbe quella di creare un array associativo ( JMP consente di utilizzare Matrix come chiave nell'array associativo ) in cui raccogli le righe su cui è già stato creato un sottoinsieme. Dovrebbe funzionare purché non si modifichi l'ordine delle righe o si aggiunga/rimuova riga.
Di seguito è riportato un rapido esempio che utilizza l'array associativo per raccogliere le righe che sono state suddivise in sottoinsiemi. Nell'esempio sto controllando le righe che hanno lo stato di riga 1 (riga selezionata) e quindi creo un sottoinsieme di quelle se non è già stato creato. Un vantaggio di questo è che puoi anche salvare i riferimenti datatable all'array associativo e accedervi rapidamente con aa_subset_rows << Ottieni valori; ma questa soluzione potrebbe essere ancora un po' difettosa se vengono selezionate molte linee tenendo premuto e trascinando il mouse su di esse.
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);
Ri: 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiSfida C:
Consiglio vivamente di fare cose del genere con i pulsanti poiché impedisce la creazione di troppi sottoinsiemi. Ma qui ho seguito la sfida data e ho aggiunto un semplice controllo per non creare almeno lo stesso sottoinsieme due volte.
Visualizza altro...
Con Row State Handler non possiamo accedere all'evento di rilascio del mouse, quindi creeremo comunque molti sottoinsiemi se l'utente seleziona più righe una per una dal grafico (potrebbe esserci un modo per farlo con Mouse Box(), ma penso che usare il pulsante lo farebbe essere molto più semplice e facile).
Ri: 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiSfida B:
Visualizza altro...
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
Nomi predefiniti qui(1); // 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modi // Challenge B dt = Open("$SAMPLE_DATA/Big Class.jmp"); //Usa l'espressione per rendere lo script un po' più pulito SE questo dovesse essere espanso create_dist = Expr( dist = dt << Distribution(Nominal Distribution(Column(:age)), Histograms Only); wait(1); // aggiungi attendere così possiamo vedere che la distribuzione è stata creata dist << Salva immagine("$TEMP/Big_Class_age_dist.png", png); dist << Chiudi finestra; ); gb = dt << Costruttore di grafici( Dimensioni(528, 454), Mostra pannello di controllo(0), Variabili(X(:altezza), Y(:peso)), Elementi(Punti(X, Y, Legenda(3)) , Linea di adattamento(X, Y, Legenda(5))) ); gb << Alla chiusura(crea_dist); // Open("$TEMP/Big_Class_age_dist.png"); // rimuovi il commento per aprire l'immagine
Ri: 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiSfida A:
Per lo più codice scritto da JMP con Aggiungi proprietà colonna. Aggiunto anche un esempio su come aggiungere e aprire URL
Visualizza altro...
Names Default To Here(1);
// Challenge A
path = "2022Q1_ChallengeA"; // path to images
{dtx} = Multiple File Import(
<<SET folder=""></SET>
Nomi predefiniti qui(1); // Percorso sfida A = "2022Q1_ChallengeA"; // percorso delle immagini {dtx} = Importazione di più file (<
Utilizzando la variabile di percorso SAMPLE_IMAGES (funziona anche come esempio di quanto sia facile apportare modifiche durante l'esecuzione di script, basta cambiare una variabile e lo script funziona ancora (ho rimosso un URL dall'elenco in modo che nessuna riga vuota venga aggiunta ad altre colonne )):
Names Default To Here(1);
// Challenge A
path = Get Path Variable("$SAMPLE_IMAGES");
{dtx} = Multiple File Import(
<<SET folder=""></SET>
Ri: 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiSfida C
Sfortunatamente c’era poco altro da fare per quanto riguarda le sfide A e B. Le soluzioni fornite sembravano impeccabili. Al contrario, ho ritenuto che qualche miglioramento fosse ancora possibile per la sfida C. Qualche parola sulla mia risposta
- Praticamente ho rubato il codice necessario da qui ( @txnelson è, come molti altri sceneggiatori, una rock star per me)
- Ho leggermente modificato il grafico includendo punti dati visibili, quindi è più semplice selezionare singole righe
- Dopo aver selezionato i punti nel grafico, la tabella dati con il sottoinsieme non viene aperta immediatamente. Questo viene fatto tramite il pulsante aggiunto sotto il grafico
Vedi sotto lo script completo, incluso il grafico modificato.
// 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 );
Ri: 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiSFIDA A
Ci scusiamo per aver affrettato la pistola con la mia soluzione iniziale... Eccone uno più pulito.
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>Ri: 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiSFIDA A:
NOTA: Ho mantenuto questa versione precedente poiché alcune persone l'avevano già vista, ma ho pubblicato una soluzione più pulita come file Rispondere a questo.
Non è affatto una bella soluzione, ma fa il suo lavoro... Spero che ne arrivi uno più elegante!
Questo da aggiungere dopo lo 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";
)
)
)
)
);
Ri: 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiSFIDA C
Con una casella del mouse non era possibile selezionare qualcosa, quindi sono passato a un gestore dello stato di riga
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";
)
);
Ri: 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiSFIDA C
Questa è la mia risposta, vedi lo script completo di seguito.
La parte inferiore aggiunge un gestore dello stato della riga alla tabella, che attiva l'azione (vedi esempio in Indice di scripting).
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 );Ri: 2022_Q1 MakeOverChallenge: azione al clic del mouse in vari modiSFIDA B
Aggiungi questo alla fine dello script:
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 );
);