How to pass an Image from GUI1 to GUI2 in MATLAB - image

This must be easy but for some reasons I can't get this to work.
What I have is 2 GUIs namely GUI1 and GUI2.
In GUI1 I read and stored an Image in say A. It also has a PushButton. Now when I click this Button it should show that image in GUI2's axes1.
I tried setappdata and getappdata but it ends up giving error. I can't understand the syntax. I'm all new to MATLAB. Any help is appreciated.

setappdata / getappdata are discussed in more detail below.
As mentioned in the comments, you can use setappdata(0, ... / getappdata(0, ... to assign/read data to/from the root object.
Excerpted from MATLAB User Interfaces - Passing Data Around User Interface. The original authors were Suever and Hoki. Attribution details can be found on the contributor page. The source is licenced under CC BY-SA 3.0 and may be found in the Documentation archive. Reference topic ID: 2883 and example ID: 9775.
Passing Data Around User Interface
Most advanced user interfaces require the user to be able to pass information between the various functions which make up a user interface. MATLAB has a number of different methods to do so.
guidata
MATLAB's own GUI Development Environment (GUIDE) prefers to use a struct named handles to pass data between callbacks. This struct contains all of the graphics handles to the various UI components as well as user-specified data. If you aren't using a GUIDE-created callback which automatically passes handles, you can retrieve the current value using guidata
% hObject is a graphics handle to any UI component in your GUI
handles = guidata(hObject);
If you want to modify a value stored in this data structure, you can modify but then you must store it back within the hObject for the changes to be visible by other callbacks. You can store it by specifying a second input argument to guidata.
% Update the value
handles.myValue = 2;
% Save changes
guidata(hObject, handles)
The value of hObject doesn't matter as long as it is a UI component within the same figure because ultimately the data is stored within the figure containing hObject.
Best for:
Storing the handles structure, in which you can store all the
handles of your GUI components.
Storing "small" other variables which need to be accessed by most callbacks.
Not recommended for:
Storing large variables which do not have to be accessed by all
callbacks and sub-functions (use setappdata/getappdata for
these).
setappdata/getappdata
Similar to the guidata approach, you can use setappdata and getappdata to store and retrieve values from within a graphics handle. The advantage of using these methods is that you can retrieve only the value you want rather than an entire struct containing all stored data. It is similar to a key/value store.
To store data within a graphics object
% Create some data you would like to store
myvalue = 2
% Store it using the key 'mykey'
setappdata(hObject, 'mykey', myvalue)
And to retrieve that same value from within a different callback
value = getappdata(hObject, 'mykey');
Note: If no value was stored prior to calling getappdata, it will return an empty array ([]).
Similar to guidata, the data is stored in the figure that contains hObject.
Best for:
Storing large variables which do not have to be accessed by all
callbacks and sub-functions.
UserData
Every graphics handle has a special property, UserData which can contain any data you wish. It could contain a cell array, a struct, or even a scalar. You can take advantage of this property and store any data you wish to be associated with a given graphics handle in this field. You can save and retrieve the value using the standard get/set methods for graphics objects or dot notation if you're using R2014b or newer.
% Create some data to store
mydata = {1, 2, 3};
% Store it within the UserData property
set(hObject, 'UserData', mydata)
% Of if you're using R2014b or newer:
% hObject.UserData = mydata;
Then from within another callback, you can retrieve this data:
their_data = get(hObject, 'UserData');
% Or if you're using R2014b or newer:
% their_data = hObject.UserData;
Best for:
Storing variables with a limited scope (variables which are likely to be used only by the object in which they are stored, or objects having a direct relationship to it).
Nested Functions
In MATLAB, a nested function can read and modify any variable defined in the parent function. In this way, if you specify a callback to be a nested function, it can retrieve and modify any data stored in the main function.
function mygui()
hButton = uicontrol('String', 'Click Me', 'Callback', #callback);
% Create a counter to keep track of the number of times the button is clicked
nClicks = 0;
% Callback function is nested and can therefore read and modify nClicks
function callback(source, event)
% Increment the number of clicks
nClicks = nClicks + 1;
% Print the number of clicks so far
fprintf('Number of clicks: %d\n', nClicks);
end
end
Best for:
Small, simple GUIs. (for quick prototyping, to not have to implement the guidata and/or set/getappdata methods).
Not recommended for:
Medium, large or complex GUIs.
GUI created with GUIDE.
Explicit input arguments
If you need to send data to a callback function and don't need to modify the data within the callback, you can always consider passing the data to the callback using a carefully crafted callback definition.
You could use an anonymous function which adds inputs
% Create some data to send to mycallback
data = [1, 2, 3];
% Pass data as a third input to mycallback
set(hObject, 'Callback', #(source, event)mycallback(source, event, data))
Or you could use the cell array syntax to specify a callback, again specifying additional inputs.
set(hObject, 'Callback', {#mycallback, data})
Best for:
- When the callback needs data to perform some operations but the data variable does not need to be modified and saved in a new state.

Related

Store a sheet object in cache of my google app script [duplicate]

I am trying to develop a webapp using Google Apps Script to be embedded into a Google Site which simply displays the contents of a Google Sheet and filters it using some simple parameters. For the time being, at least. I may add more features later.
I got a functional app, but found that filtering could often take a while as the client sometimes had to wait up to 5 seconds for a response from the server. I decided that this was most likely due to the fact that I was loading the spreadsheet by ID using the SpreadsheetApp class every time it was called.
I decided to cache the spreadsheet values in my doGet function using the CacheService and retrieve the data from the cache each time instead.
However, for some reason this has meant that what was a 2-dimensional array is now treated as a 1-dimensional array. And, so, when displaying the data in an HTML table, I end up with a single column, with each cell being occupied by a single character.
This is how I have implemented the caching; as far as I can tell from the API reference I am not doing anything wrong:
function doGet() {
CacheService.getScriptCache().put('data', SpreadsheetApp
.openById('####')
.getActiveSheet()
.getDataRange()
.getValues());
return HtmlService
.createTemplateFromFile('index')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function getData() {
return CacheService.getScriptCache().get('data');
}
This is my first time developing a proper application using GAS (I have used it in Sheets before). Is there something very obvious I am missing? I didn't see any type restrictions on the CacheService reference page...
CacheService stores Strings, so objects such as your two-dimensional array will be coerced to Strings, which may not meet your needs.
Use the JSON utility to take control of the results.
myCache.put( 'tag', JSON.stringify( myObj ) );
...
var cachedObj = JSON.parse( myCache.get( 'tag' ) );
Cache expires. The put method, without an expirationInSeconds parameter expires in 10 minutes. If you need your data to stay alive for more than 10 minutes, you need to specify an expirationInSeconds, and the maximum is 6 hours. So, if you specifically do NOT need the data to expire, Cache might not be the best use.
You can use Cache for something like controlling how long a user can be logged in.
You could also try using a global variable, which some people would tell you to never use. To declare a global variable, define the variable outside of any function.

Is there a generic way to access objects in UFT

My task is to check the value of data from the global data sheet within different UIs, each of them having lots of data.
My idea was to do this in a generic way.
I create a array with the objects name, which corresponds with the name of the data sheet column
And then I just compare the content
Browser("").Page("").GENERIC_TYPE(label).GetROProperty("value") = datasheet.GetParameter(label)
Is there such a Generic Type that works for WebEdit and WebList?
You can use WebElement and this is generic as all elements on the page are web elements.
If you are reading the objects from OR, then you might have to update the element type to WebElement and it's tidious (if you are dealing with multiple objects). So the alternative way is using the below approach.
Browser("").Page("").WebElement("xpath:=//*[#common_attribute=" + element_attribute_value + "]").GetROProperty("value") = datasheet.GetParameter(label)

How does one read the data value from a Function outside FunctionCallbackInfo?

When I create a function like this:
v8::Function::New(<Isolate>, <C_Function>, <Data_Value>);
The Data_Value that I supply is useful for many things and I can access that when the function is called, with something like FunctionCallbackInfo->GetData().
But I have found no way to get back this data in a different scenario. Let's say I store that Function in a Persistent object, and then I would like to read which data is currently bound to it. Any ideas?
I don't think it's exposed via the API.
But there's an alternative:
manually construct a v8::FunctionTemplate
set its ->InstanceTemplate()->SetInternalFieldCount(num_fields)
get the v8::Function from the template with template->GetFunction(context),
now you should have function->InternalFieldCount() == num_fields
you can use function->SetInternalField(index, value) and function->GetInternalField(index) to store any data you want.
For complete examples, search for "SetInternalFieldCount" in V8's test-api.cc.

Reading a large batch of objects taking way too long

I’m experimenting with scripting a batch of OmniFocus tasks in JXA and running into some big speed issues. I don't think the problem is specific to OmniFocus or JXA; rather I think this is a more general misunderstanding of how getting objects works - I'm expecting it to work like a single SQL query that loads all objects in memory but instead it seems to do each operation on demand.
Here’s a simple example - let’s get the names of all uncompleted tasks (which are stored in a SQLite DB on the backend):
var tasks = Application('OmniFocus').defaultDocument.flattenedTasks.whose({completed: false})
var totalTasks = tasks.length
for (var i = 0; i < totalTasks; i++) {
tasks[i].name()
}
[Finished in 46.68s]
Actually getting the list of 900 tasks takes ~7 seconds - already slow - but then looping and reading basic properties takes another 40 seconds, presumably because it's hitting the DB for each one. (Also, tasks doesn't behave like an array - it seems to be recomputed every time it's accessed.)
Is there any way to do this quickly - to read a batch of objects and all their properties into memory at once?
Introduction
With AppleEvents, the IPC technology that JavaScript for Automation (JXA) is built upon, the way you request information from another application is by sending it an "object specifier," which works a little bit like dot notation for accessing object properties, and a little bit like a SQL or GraphQL query.
The receiving application evaluates the object specifier and determines which objects, if any, it refers to. It then returns a value representing the referred-to objects. The returned value may be a list of values, if the referred-to object was a collection of objects. The object specifier may also refer to properties of objects. The values returned may be strings, or numbers, or even new object specifiers.
Object specifiers
An example of a fully-qualified object specifier written in AppleScript is:
a reference to the name of the first window of application "Safari"
In JXA, that same object specifier would be expressed:
Application("Safari").windows[0].name
To send an IPC request to Safari to ask it to evaluate this object specifier and respond with a value, you can invoke the .get() function on an object specifier:
Application("Safari").windows[0].name.get()
As a shorthand for the .get() function, you can invoke the object specifier directly:
Application("Safari").windows[0].name()
A single request is sent to Safari, and a single value (a string in this case) is returned.
In this way, object specifiers work a little bit like dot notation for accessing object properties. But object specifiers are much more powerful than that.
Collections
You can effectively perform maps or comprehensions over collections. In AppleScript this looks like:
get the name of every window of Application "Safari"
In JXA it looks like:
Application("Safari").windows.name.get()
Even though this requests multiple values, it requires only a single request to be sent to Safari, which then iterates over its own windows, collecting the name of each one, and then sends back a single list value containing all of the name strings. No matter how many windows Safari has open, this statement only results in a single request/response.
For-loop anti-pattern
Contrast that approach to the for-loop anti-pattern:
var nameOfEveryWindow = []
var everyWindowSpecifier = Application("Safari").windows
var numberOfWindows = everyWindowSpecifier.length
for (var i = 0; i < numberOfWindows; i++) {
var windowNameSpecifier = everyWindowSpecifier[i].name
var windowName = windowNameSpecifier.get()
nameOfEveryWindow.push(windowName)
}
This approach may take much longer, as it requires length+1 number of requests to get the collection of names.
(Note that the length property of collection object specifiers is handled specially, because collection object specifiers in JXA attempt to behave like native JavaScript Arrays. No .get() invocation is needed (or allowed) on the length property.)
Filtering, and why your code example is slow
The really interesting part of AppleEvents is the so-called "whose clause". This allows you provide criteria with which to filter the objects from which the values will be returned from.
In the code you included in your question, tasks is an object specifier that refers to a collection of objects that have been filtered to only include uncompleted tasks using a whose clause. Note that this is still just reference at this point; until you call .get() on the object specifier, it's just a pointer to something, not the thing itself.
The code you included then implements the for-loop anti-pattern, which is probably why your observed performance is so slow. You are sending length+1 requests to OmniFocus. Each invocation of .name() results in another AppleEvent.
Furthermore, you're asking OmniFocus to re-filter the collection of tasks every time, because the object specifier you're sending each time contains a whose clause.
Try this instead:
var taskNames = Application('OmniFocus').defaultDocument.flattenedTasks.whose({completed: false}).name.get()
This should send a single request to OmniFocus, and return an array of the names of each uncompleted task.
Another approach to try would be to ask OmniFocus to evaluate the "whose clause" once, and return an array of object specifiers:
var taskSpecifiers = Application('OmniFocus').defaultDocument.flattenedTasks.whose({completed: false})()
Iterating over the returned array of object specifies and invoking .name.get() on each one would likely be faster than your original approach.
Answer
While JXA can get arrays of single properties of collections of objects, it appears that due to an oversight on the part of the authors, JXA doesn't support getting all of the properties of all of the objects in a collection.
So, to answer you actual question, with JXA, there is not a way to read a batch of objects and all their properties into memory at once.
That said, AppleScript does support it:
tell app "OmniFocus" to get the properties of every flattened task of default document whose completed is false
With JXA, you have to fall back to the for-loop anti-pattern if you really want all of the properties of the objects, but we can avoid evaluating the whose clause more than once by pulling its evaluation outside of the for loop:
var tasks = []
var taskSpecifiers = Application('OmniFocus').defaultDocument.flattenedTasks.whose({completed: false})()
var totalTasks = taskSpecifiers.length
for (var i = 0; i < totalTasks; i++) {
tasks[i] = taskSpecifiers[i].properties()
}
Finally, it should be noted that AppleScript also lets you request specific sets of properties:
get the {name, zoomable} of every window of application "Safari"
But there is no way with JXA to send a single request for multiple properties of an object, or collection of objects.
Try something like:
tell app "OmniFocus"
tell default document
get name of every flattened task whose completed is false
end tell
end tell
Apple event IPC is not OOP, it’s RPC + simple first-class relational queries. AppleScript obfuscates this, and JXA not only obfuscates it even worse but cripples it too; but once you learn to see through the faux-OO syntactic nonsense it makes a lot more sense. This and this may give a bit more insight.
[ETA: Omni recently implemented its own embedded JavaScriptCore-based scripting support in its apps; if JS is your thing you might find that a better bet.]

How to create dynamic Callbacks in MATLAB?

I have this line of code:
delete_btn = uicontrol(rr_ops, 'Style', 'pushbutton', 'String', 'Delete Graphic', 'Position', [13 135 98 20], ...
'Callback', 'delete_graphic');
and a little bit upper this function:
function delete_graphic
global rr_list
selected = get(rr_list, 'Value');
selected
return;
why this code is not working? I really dont understand...
What do I need? I create one button and a listbox, clicking on button - deleting selected element from a listbox.
Thx for help.
PS
Always getting this error:
??? Undefined function or variable 'delete_graphic'.
??? Error while evaluating uicontrol Callback
here is all my code: http://paste.ubuntu.com/540094/ (line 185)
The generally-preferred way to define a callback function is to use a function handle instead of a string. When you use a string, the code in the string is evaluated in the base workspace. This means that all the variables and functions used in the string have to exist in the base workspace when the callback is evaluated. This makes for a poor GUI design, since you don't really want the operation of your GUI dependent on the base workspace (which the user can modify easily, thus potentially breaking your GUI).
This also explains the error you are getting. The function delete_graphic is defined as a subfunction in your file rr_intervals.m. Subfunctions can only be called by other functions defined in the same m-file, so delete_graphic is not visible in the base workspace (where your string callback is evaluated). Using a function handle callback is a better alternative. Here's how you would do it:
Change the callback of your button (line 216) from 'delete_graphic' to #delete_graphic.
Change the function definition of delete_graphic (line 185) to:
function delete_graphic(hObject,eventdata)
where hObject is the handle of the object issuing the callback and eventdata is optional data provided when the callback is issued.
EDIT:
If you want to pass other arguments to delete_graphic, you can perform the following steps:
Add the additional input arguments to the end of the function definition. For example:
function delete_graphic(hObject,eventdata,argA,argB)
Use a cell array when you set the callback for your button, where the first cell contains the function handle and the subsequent cells each contain an input argument. For example:
set(delete_btn,'Callback',{#delete_graphic,A,B});
There is one caveat to this, which is that the values A and B stored in the cell array are fixed at what they are when you set the callback. If you change A or B in your code it will not change the values stored in the cell-array callback.
If you aren't able to use the above solution (i.e. if A and B need to change value), there are a few other options for how you can share data among a GUI's callbacks:
You can rework the organization of your code to make use of nested functions. This makes it very easy to share data between callbacks. Some nice examples of using nested functions to create GUIs can be found in the MathWorks File Exchange submission GUI Examples using Nested Functions by Steven Lord.
You can store data in the UserData property of a uicontrol object. To access or update it, you just need the object handle.
You can use the functions SETAPPDATA/GETAPPDATA to attach data to a handle graphics object (i.e. uicontrol).
Since it appears your code was created using GUIDE, you can make use of the handles structure GUIDE creates to store data using the GUIDATA function.

Resources