Patrick,
There is an example in the ptII development tree that uses Python for
GUI work.
Bob Weber sent me a model that I folded in as
$PTII/ptolemy/actor/lib/python/demo/RecordManipulation.xml
I've attached the model.
The Ptolemy II development tree also includes a draft system for laying
out components
in a runtime window. In the Ptolemy II development window, View ->
Interface Window brings
up a run control panel that is editable.
We stopped work on this when we submitted changes to the underlying
package and the author
said he was moving to Eclipse RCP.
To access the Ptolemy II development tree, see
http://chess.eecs.berkeley.edu/ptexternal
For information about Kepler and Python, see
https://kepler-project.org/developers/reference/python-and-kepler
There is also a thread at
http://lists.nceas.ucsb.edu/kepler/pipermail/kepler-users/2011-November/002044.html
about Kepler and Python.
_Christopher
On 6/8/12 5:44 PM, Edward A. Lee wrote:
As I said before:
They aren't as limited as you think...
If a parameter contains an attribute that subclasses
ParameterEditorStyle, then that attribute controls
how the interaction with the parameter is done.
See the
$PTII/ptolemy/actor/gui/style directory.
In addition, you can completely customize the
dialog that Configure Actor opens.
See EditorFactory and its subclasses for examples.
For an example, the PythonScript actor in the library
opens a text editor when you select Configure Actor.
Edward
On 6/8/12 2:14 PM, Rohan Sadler wrote:
Hi Patrick,
I was thinking the same thing today, and was having a look at
wxPython. However, I am in the early days and so can't help you re:
experience.
At this point in time I am almost tempted to run Kepler from the
command line:
https://kepler-project.org/developers/reference/executing-kepler-from-the-command-line.
The python/java GUI buttons would simply change default object
assignments in the kepler/java script before running the project.
There though should be a better way, as it would not be
computationally smart to have two interpreters stacked on top of each
other.
re: other toolkits. The forthcoming book
http://www.amazon.com/Programming-Graphical-Interfaces-Chapman-Series/dp/1439856826
also enables learning GUIs for R.
I agree with you. The bottom line is that there is a need for custom
interfaces for endusers of the kepler workflow, as soon as the
workflow gets complex. Most of my endusers are familiar with excel
and that is it when it comes to software, and don't want to venture
too far out. For example a technician typing in soil and plant
parameters, before getting a soil water balance from Kepler.
Something like RExcel means they can plug in numbers in a
spreadsheet, and get their outputs. In a workflow this would mean that:
1) Run the workflow in Kepler,
2) An excel styled spreadsheet would pop-up, pre-populated with
default parameters, and perhaps some pre-specified data [e.g. swing
pulldown to source locally held weather station data].
3) End user would type in their numbers, then press 'done'
4) Kepler would continue to execute with the new information.
Regards
Rohan
Senior Scientist
Astron Environmental Services
Adjunct Senior Lecturer
School of Agricultural and Resource Economics
The University of Western Australia
________________________________________
From: kepler-users-boun...@kepler-project.org
[kepler-users-boun...@kepler-project.org] On Behalf Of Patrick
Janssen [patr...@janssen.name]
Sent: Tuesday, 5 June 2012 8:54 AM
To: kepler-users@kepler-project.org
Subject: [kepler-users] component gui
The GUI creation tools under the 'Configure Actor' (for creating
custom interfaces for setting actor parameters) are limited (for
example, no sliders, no drop down lists, no tabs, no free text, no
layout constraints, etc). In particular, I find this an issue when
defining complex Python actors with lost of different parameters. As
a result, the interface can end up being a bit unfriendly for the end
users of my actors.
I am wondering - what is the best way of overcoming this? Has anyone
had any experience creating custom GUIs for actors using either Java
or Python, for example using Swing or other toolkits?
_______________________________________________
Kepler-users mailing list
Kepler-users@kepler-project.org
http://lists.nceas.ucsb.edu/kepler/mailman/listinfo/kepler-users
_______________________________________________
Kepler-users mailing list
Kepler-users@kepler-project.org
http://lists.nceas.ucsb.edu/kepler/mailman/listinfo/kepler-users
--
Christopher Brooks, PMP University of California
CHESS Executive Director US Mail: 337 Cory Hall
Programmer/Analyst CHESS/Ptolemy/Trust Berkeley, CA 94720-1774
ph: 510.643.9841 (Office: 545Q Cory)
home: (F-Tu) 707.665.0131 cell: 707.332.0670
<?xml version="1.0" standalone="no"?>
<!DOCTYPE entity PUBLIC "-//UC Berkeley//DTD MoML 1//EN"
"http://ptolemy.eecs.berkeley.edu/xml/dtd/MoML_1.dtd">
<entity name="RecordManipulation" class="ptolemy.actor.TypedCompositeActor">
<property name="_createdBy" class="ptolemy.kernel.attributes.VersionAttribute" value="8.1.devel">
</property>
<property name="_windowProperties" class="ptolemy.actor.gui.WindowPropertiesAttribute" value="{bounds={313, 195, 1014, 556}, maximized=false}">
</property>
<property name="_vergilSize" class="ptolemy.actor.gui.SizeAttribute" value="[801, 446]">
</property>
<property name="_vergilZoomFactor" class="ptolemy.data.expr.ExpertParameter" value="1.1337579617834">
</property>
<property name="_vergilCenter" class="ptolemy.data.expr.ExpertParameter" value="{329.2007575757576, 169.2310606060606}">
</property>
<property name="SDF Director" class="ptolemy.domains.sdf.kernel.SDFDirector">
<property name="iterations" class="ptolemy.data.expr.Parameter" value="1">
</property>
<property name="allowDisconnectedGraphs" class="ptolemy.data.expr.Parameter" value="true">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[40.75, 50.0]">
</property>
</property>
<property name="Annotation" class="ptolemy.vergil.kernel.attributes.TextAttribute">
<property name="textColor" class="ptolemy.actor.gui.ColorAttribute" value="{0.4, 0.4, 0.4, 1.0}">
</property>
<property name="text" class="ptolemy.kernel.util.StringAttribute" value="Author: Bob Weber">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[0.0, 300.0]">
</property>
</property>
<property name="Annotation2" class="ptolemy.vergil.kernel.attributes.TextAttribute">
<property name="text" class="ptolemy.kernel.util.StringAttribute" value="Use Python to query the user about which record to manipulate.">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[330.0, -20.0]">
</property>
</property>
<entity name="Recordmaker" class="ptolemy.actor.lib.python.PythonScript">
<property name="script" class="ptolemy.kernel.util.StringAttribute" value="from ptolemy.data import StringToken from ptolemy.data import ArrayToken from ptolemy.data import RecordToken from ptolemy.data.type import BaseType class Main : "Dialog Example" def fire(self) : if self.label.hasToken(0): slabel = [self.label.get(0).stringValue()] if self.value.hasToken(0): inputValue = [(self.value.get(0))] self.record.broadcast(RecordToken(slabel,inputValue)) ">
</property>
<property name="_editorFactory" class="ptolemy.vergil.toolbox.TextEditorConfigureFactory">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="script">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[125.75, 160.0]">
</property>
<property name="DocAttribute" class="ptolemy.vergil.basic.DocAttribute">
<property name="description" class="ptolemy.kernel.util.StringAttribute" value="Creates a record consisting of the label set equal to the value. Label must be a string, value can be anything. Acts as the inverse of Recordparser to permit dynamic construction and accessing of java Records">
</property>
<property name="author" class="ptolemy.kernel.util.StringAttribute" value="Robert Weber">
</property>
<property name="version" class="ptolemy.kernel.util.StringAttribute" value="1">
</property>
<property name="label (port)" class="ptolemy.kernel.util.StringAttribute" value="String">
</property>
<property name="value (port)" class="ptolemy.kernel.util.StringAttribute" value="general">
</property>
<property name="record (port)" class="ptolemy.kernel.util.StringAttribute" value="RecordToken">
</property>
</property>
<port name="label" class="ptolemy.actor.TypedIOPort">
<property name="input"/>
<property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</port>
<port name="value" class="ptolemy.actor.TypedIOPort">
<property name="input"/>
<property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</port>
<port name="record" class="ptolemy.actor.TypedIOPort">
<property name="output"/>
<property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
<property name="_type" class="ptolemy.actor.TypeAttribute" value="general">
</property>
</port>
</entity>
<entity name="Recordparser" class="ptolemy.actor.lib.python.PythonScript">
<property name="script" class="ptolemy.kernel.util.StringAttribute" value="from ptolemy.data import StringToken from ptolemy.data import ArrayToken from ptolemy.data import RecordToken from ptolemy.data.type import BaseType class Main : "Dialog Example" def fire(self) : if self.label.hasToken(0) : thelabel = self.label.get(0).stringValue() if self.record.hasToken(0): theRecord=self.record.get(0) labels = theRecord.labelSet().iterator() while (labels.hasNext()) : alabel=labels.next() if(thelabel==alabel) : value = (theRecord.get(thelabel)) self.array.broadcast(value) #endif testing label equality #endwhile iterating over the labels in the record #endif testing whether there is an input record #endif testing whether there is an input label #enddef of the fire phase">
</property>
<property name="_editorFactory" class="ptolemy.vergil.toolbox.TextEditorConfigureFactory">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="script">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[415.75, 185.0]">
</property>
<property name="DocAttribute" class="ptolemy.vergil.basic.DocAttribute">
<property name="description" class="ptolemy.kernel.util.StringAttribute" value="Accesses the field in the input record specified by the label input. Acts as the inverse of Recordmaker to permit dynamic construction and accessing of java records. ">
</property>
<property name="author" class="ptolemy.kernel.util.StringAttribute" value="Robert Weber">
</property>
<property name="version" class="ptolemy.kernel.util.StringAttribute" value="1">
</property>
<property name="label (port)" class="ptolemy.kernel.util.StringAttribute" value="String">
</property>
<property name="record (port)" class="ptolemy.kernel.util.StringAttribute" value="Record, e.g., {x=53}">
</property>
<property name="array (port)" class="ptolemy.kernel.util.StringAttribute" value="value of the field specified by the label string as a matrix.">
</property>
</property>
<port name="label" class="ptolemy.actor.TypedIOPort">
<property name="input"/>
<property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</port>
<port name="record" class="ptolemy.actor.TypedIOPort">
<property name="input"/>
<property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</port>
<port name="array" class="ptolemy.actor.TypedIOPort">
<property name="output"/>
<property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
<property name="_type" class="ptolemy.actor.TypeAttribute" value="general">
</property>
</port>
</entity>
<entity name="RecordMerge" class="ptolemy.actor.lib.python.PythonScript">
<property name="script" class="ptolemy.kernel.util.StringAttribute" value="# This is a simple actor that copies the input to the output. # You can remove the ports, add new ports, and modify the script. class Main : "Copy the inputs to the output." def fire(self) : token1 = self.record1.get(0) token2 = self.record2.get(0) self.output.broadcast(token1.merge(token1,token2)) return ">
</property>
<property name="_tableauFactory" class="ptolemy.vergil.toolbox.TextEditorTableauFactory">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="script">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[255.75, 195.0]">
</property>
<port name="record1" class="ptolemy.actor.TypedIOPort">
<property name="input"/>
</port>
<port name="output" class="ptolemy.actor.TypedIOPort">
<property name="output"/>
</port>
<port name="record2" class="ptolemy.actor.TypedIOPort">
<property name="input"/>
</port>
</entity>
<entity name="Recordmaker2" class="ptolemy.actor.lib.python.PythonScript">
<property name="script" class="ptolemy.kernel.util.StringAttribute" value="from ptolemy.data import StringToken from ptolemy.data import ArrayToken from ptolemy.data import RecordToken from ptolemy.data.type import BaseType class Main : "Dialog Example" def fire(self) : if self.label.hasToken(0): slabel = [self.label.get(0).stringValue()] if self.value.hasToken(0): inputValue = [(self.value.get(0))] self.record.broadcast(RecordToken(slabel,inputValue)) ">
</property>
<property name="_editorFactory" class="ptolemy.vergil.toolbox.TextEditorConfigureFactory">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="script">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[125.75, 250.0]">
</property>
<property name="DocAttribute" class="ptolemy.vergil.basic.DocAttribute">
<property name="description" class="ptolemy.kernel.util.StringAttribute" value="Creates a record consisting of the label set equal to the value. Label must be a string, value can be anything. Acts as the inverse of Recordparser to permit dynamic construction and accessing of java Records">
</property>
<property name="author" class="ptolemy.kernel.util.StringAttribute" value="Robert Weber">
</property>
<property name="version" class="ptolemy.kernel.util.StringAttribute" value="1">
</property>
<property name="label (port)" class="ptolemy.kernel.util.StringAttribute" value="String">
</property>
<property name="value (port)" class="ptolemy.kernel.util.StringAttribute" value="general">
</property>
<property name="record (port)" class="ptolemy.kernel.util.StringAttribute" value="RecordToken">
</property>
</property>
<port name="label" class="ptolemy.actor.TypedIOPort">
<property name="input"/>
<property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</port>
<port name="value" class="ptolemy.actor.TypedIOPort">
<property name="input"/>
<property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</port>
<port name="record" class="ptolemy.actor.TypedIOPort">
<property name="output"/>
<property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
<property name="_type" class="ptolemy.actor.TypeAttribute" value="general">
</property>
</port>
</entity>
<entity name="StringConst" class="ptolemy.actor.lib.StringConst">
<property name="value" class="ptolemy.data.expr.Parameter" value="A">
</property>
<doc>Create a constant sequence with a string value.</doc>
<property name="_icon" class="ptolemy.vergil.icon.BoxedValueIcon">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="value">
</property>
<property name="displayWidth" class="ptolemy.data.expr.Parameter" value="80">
</property>
<property name="displayHeight" class="ptolemy.data.expr.Parameter" value="10">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[10.75, 145.0]">
</property>
<property name="_hideName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</entity>
<entity name="StringConst2" class="ptolemy.actor.lib.StringConst">
<property name="value" class="ptolemy.data.expr.Parameter" value="B">
</property>
<doc>Create a constant sequence with a string value.</doc>
<property name="_icon" class="ptolemy.vergil.icon.BoxedValueIcon">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="value">
</property>
<property name="displayWidth" class="ptolemy.data.expr.Parameter" value="80">
</property>
<property name="displayHeight" class="ptolemy.data.expr.Parameter" value="10">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[10.0, 240.0]">
</property>
<property name="_hideName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</entity>
<entity name="Const" class="ptolemy.actor.lib.Const">
<property name="value" class="ptolemy.data.expr.Parameter" value="10">
</property>
<doc>Create a constant sequence.</doc>
<property name="_icon" class="ptolemy.vergil.icon.BoxedValueIcon">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="value">
</property>
<property name="displayWidth" class="ptolemy.data.expr.Parameter" value="60">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[10.75, 180.0]">
</property>
<property name="_hideName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</entity>
<entity name="Const2" class="ptolemy.actor.lib.Const">
<property name="value" class="ptolemy.data.expr.Parameter" value="11">
</property>
<doc>Create a constant sequence.</doc>
<property name="_icon" class="ptolemy.vergil.icon.BoxedValueIcon">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="value">
</property>
<property name="displayWidth" class="ptolemy.data.expr.Parameter" value="60">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[15.0, 270.0]">
</property>
<property name="_hideName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</entity>
<entity name="Selectordialog" class="ptolemy.actor.lib.python.PythonScript">
<property name="script" class="ptolemy.kernel.util.StringAttribute" value="import javax.swing as sshwing from ptolemy.data import StringToken from ptolemy.data import ArrayToken from ptolemy.data.type import BaseType class Main : "Dialog Example" def fire(self) : prompt = "Select" if self.prompt.hasToken(0) : prompt = self.prompt.get(0).stringValue() inputTokens = self.choices.get(0) picks = [] i=0 while i < inputTokens.length() : if inputTokens.getElement(i).getType().equals(BaseType.STRING) : value = inputTokens.getElement(i).stringValue() else : value = inputTokens.getElement(i).toString() picks.append(value) i = i + 1 choice = sshwing.JOptionPane.showInputDialog(None,prompt,"Selection",1,None,picks,picks[0]) st = StringToken(choice) self.output.broadcast(st) ">
</property>
<property name="_editorFactory" class="ptolemy.vergil.toolbox.TextEditorConfigureFactory">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="script">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[315.75, 65.0]">
</property>
<port name="choices" class="ptolemy.actor.TypedIOPort">
<property name="input"/>
</port>
<port name="prompt" class="ptolemy.actor.TypedIOPort">
<property name="input"/>
</port>
<port name="output" class="ptolemy.actor.TypedIOPort">
<property name="output"/>
<property name="_type" class="ptolemy.actor.TypeAttribute" value="string">
</property>
</port>
</entity>
<entity name="Const3" class="ptolemy.actor.lib.Const">
<property name="value" class="ptolemy.data.expr.Parameter" value="{"A","B"}">
</property>
<doc>Create a constant sequence.</doc>
<property name="_icon" class="ptolemy.vergil.icon.BoxedValueIcon">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="value">
</property>
<property name="displayWidth" class="ptolemy.data.expr.Parameter" value="60">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[220.0, 45.0]">
</property>
<property name="_hideName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</entity>
<entity name="StringConst3" class="ptolemy.actor.lib.StringConst">
<property name="value" class="ptolemy.data.expr.Parameter" value="Which parameter?">
</property>
<doc>Create a constant sequence with a string value.</doc>
<property name="_icon" class="ptolemy.vergil.icon.BoxedValueIcon">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="value">
</property>
<property name="displayWidth" class="ptolemy.data.expr.Parameter" value="80">
</property>
<property name="displayHeight" class="ptolemy.data.expr.Parameter" value="10">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[200.0, 75.0]">
</property>
<property name="_hideName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</entity>
<entity name="MonitorValue2" class="ptolemy.actor.lib.MonitorValue">
<doc>Monitor and display values</doc>
<property name="displayWidth" class="ptolemy.data.expr.Parameter" value="10">
</property>
<property name="_icon" class="ptolemy.vergil.icon.UpdatedValueIcon">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="value">
</property>
<property name="displayWidth" class="ptolemy.data.expr.Parameter" value="displayWidth">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[555.0, 185.0]">
</property>
<property name="_hideName" class="ptolemy.data.expr.SingletonParameter" value="true">
</property>
</entity>
<relation name="relation" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation2" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation3" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation4" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation5" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation6" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation7" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation8" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation10" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation12" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation9" class="ptolemy.actor.TypedIORelation">
</relation>
<link port="Recordmaker.label" relation="relation"/>
<link port="Recordmaker.value" relation="relation3"/>
<link port="Recordmaker.record" relation="relation5"/>
<link port="Recordparser.label" relation="relation9"/>
<link port="Recordparser.record" relation="relation7"/>
<link port="Recordparser.array" relation="relation12"/>
<link port="RecordMerge.record1" relation="relation5"/>
<link port="RecordMerge.output" relation="relation7"/>
<link port="RecordMerge.record2" relation="relation6"/>
<link port="Recordmaker2.label" relation="relation2"/>
<link port="Recordmaker2.value" relation="relation4"/>
<link port="Recordmaker2.record" relation="relation6"/>
<link port="StringConst.output" relation="relation"/>
<link port="StringConst2.output" relation="relation2"/>
<link port="Const.output" relation="relation3"/>
<link port="Const2.output" relation="relation4"/>
<link port="Selectordialog.choices" relation="relation8"/>
<link port="Selectordialog.prompt" relation="relation10"/>
<link port="Selectordialog.output" relation="relation9"/>
<link port="Const3.output" relation="relation8"/>
<link port="StringConst3.output" relation="relation10"/>
<link port="MonitorValue2.input" relation="relation12"/>
</entity>
_______________________________________________
Kepler-users mailing list
Kepler-users@kepler-project.org
http://lists.nceas.ucsb.edu/kepler/mailman/listinfo/kepler-users