MATLAB has several selection-sensitive capabilities. For example, if you select some text and press F9, it evaluates your selection. (Unless you've remapped your keyboard settings.)
I'd like to be able to replicate this functionality with for a shortcut. So, for example, I want to click a shortcut that displays the current selection. My shortcut callback would be disp(GetSelection()).
But what goes into GetSelection?
Thanks to #Yair Altman's undocumented Matlab, I was able to figure out the java commands to make this work.
Put this in a shortcut (or a function that is called by the shortcut):
%# find the text area in the command window
jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
try
cmdWin = jDesktop.getClient('Command Window');
jTextArea = cmdWin.getComponent(0).getViewport.getComponent(0);
catch
commandwindow;
jTextArea = jDesktop.getMainFrame.getFocusOwner;
end
%# read the current selection
jTxt = jTextArea.getSelectedText;
%# turn into Matlab text
currentSelection = jTxt.toCharArray'; %'
%# display
disp(currentSelection)
I don't believe there is any way to control or read the selection from the Matlab text editor, there is no mention of such an API on the Mathworks website (at least from a quick search on Google). If you want this functionality to enable more advanced text editing, then you might want to consider setting the .m file editor to an external editor (http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_env/brxijcd.html). It may be possible to read the selection from a UIcontrol in a custom GUI, but I don't think this is what you want.
In case you want to use something like this but with text highlighted in the editor rather than in the command window.
I use the following code in order to be able to quickly check the nnz() of a variable, although you can change the code in the nested try-catch to whatever you need.
Lastly, I created a shortcut with this code in the top right of Matlab, which I access quickly by pressing Alt-1.
try
activeEditor = matlab.desktop.editor.getActive;
currentSelection = activeEditor.SelectedText;
try
eval(sprintf('val = nnz(%s);',currentSelection))
disp(sprintf('>> nnz(%s) = %s',currentSelection,num2str(val)))
catch ex
disp(ex.message)
end
catch ex
disp(ex.message)
end
Related
I would like to have a text box and a button in my GUI. When the button is pressed, a history window will come up, and if the user selects a previous entry the text that they have highlighted in the edit box will be overwritten.
It should work like copy-pasting, whatever is selected in the history window should be pasted over what is selected, or the new text should be added wherever the cursor is.
Is there any way in Matlab to do this? Is it possible to access what is highlighted in an edit box?
With vanilla Matlab this isn't possible. It appear that Mathworks is in the process of expanding what they support with GUIs (survey 1, survey 2), but as of yet they don't allow this.
One possible workaround is using findjobj.m, by Yair Altman. He discusses edit boxes in this post
You can trace findjobj.m for your text box to find 1 or 2 lines of code that are needed so you don't have to carry around all 3,400 lines of it.
Then all you really need to do is get the selected indices and work from there.
javaHandle = findjobj(editBoxHandle);
startSelect = get(javaHandle,'SelectionStart');
endSelect = get(javaHandle,'SelectionEnd');
Once you have the indexes of what text is selected, it becomes almost trivial to replace that text with the new text.
text = editBoxHandle.String;
editBoxHandle.String = [text(1:startSelect) newText text(endSelect:end)];
One thing to note, when the user clicks the button the text box will lose focus, and it will no longer be clear what text is selected. You can remedy this by giving focus back to the text box, and re-selecting what was selected in the button's callback.
uicontrol(editBoxHandle); %Give focus to the edit box, selecting the entire text
javaHandle.select(startSelect,endSelect); %select/highlight the correct stuff
This will highlight the text that will be replaced with the users selection
In my notebook, I have a cell returning temp calculation results. It's a bit long, so after it is run, I want to hide it and when needed, to show it.
To do it manually, I can double click the left side of the output, to hide it
After double click
But is there any way I can do this by code? For example,
the last line of the cell, use a command like %%hide output, and the output would be hidden after finished running.
Additionally, can I get this feature in output HTML?
Add ; by the end of the cell to hide the output of that cell.
In the newer versions(5.0.0 at the time I'm writing this), pressing o in the command mode hides the output of the cell in focus. The same happens if you triple click in front of the output.
o is
the first letter in the word "output" or
lower case of 15th letter in the alphabet
You can add %%capture to the beginning of the cell.
Jupyter provides a magic cell command called %%capture that allows you to capture all of to outputs from that cell.
You can use it like this:
%%capture test
print('test')
test.stdout => 'test\n'
https://ipython.readthedocs.io/en/stable/interactive/magics.html
In newer versions of Jupiter Notebook, select the desired cell, make sure you're in command mode and then on the menubar press Cell > Current Outputs. You have then three options:
Toggle (press O in the command mode to apply the same effect)
Toggle Scrolling (the default output)
Clear (to clear the output all together)
Image to Menubar Options
Additionally, you can apply the same effect to all the cells in your document if you chose All Output instead of Current Output.
Not exactly what you are after, but the effect might be good enough for your purposes:
Look into the %%capture magic (https://nbviewer.jupyter.org/github/ipython/ipython/blob/1.x/examples/notebooks/Cell%20Magics.ipynb). It lets you assign that cell output to a variable. By calling that variable later you could see the output.
Based on this, I just came up with this for myself a few minutes ago:
%%javascript
$('#maintoolbar-container').children('#toggleButton').remove()
var toggle_button = ("<button id='toggleButton' type='button'>Show Code</button>");
$('#maintoolbar-container').append(toggle_button);
var code_shown = false;
function code_toggle()
{
if (code_shown)
{
console.log("code shown")
$('div.input').hide('500');
$('#toggleButton').text('Show Code');
}
else
{
console.log("code not shown")
$('div.input').show('500');
$('#toggleButton').text('Hide Code');
}
code_shown = !code_shown;
}
$(document).ready(function()
{
code_shown=false;
$('div.input').hide();
});
$('#toggleButton').on('click', code_toggle);
It does have a glitch: each time you run that cell (which I put at the top), it adds a button. So, that is something that needs to be fixed. Would need to check in the maintoolbar-container to see if the button already exists, and then not add it.
EDIT
I added the necessary piece of code:
$('#maintoolbar-container').children('#toggleButton').remove()
You can use the notebook utils from https://github.com/google/etils:
!pip install etils[ecolab]
from etils import ecolab
with etils.collapse():
print('This content will be hidden by default')
It will capture the stdout/stderr output and display it a some collapsible section.
Internally, this is more or less equivalent to:
import contextlib
import html
import io
import IPython.display
#contextlib.contextmanager
def collapse(name: str = ''):
f = io.StringIO()
with contextlib.redirect_stderr(f):
with contextlib.redirect_stdout(f):
yield
name = html.escape(name)
content = f.getvalue()
content = html.escape(content)
content = f'<pre><code>{content}</code></pre>'
content = IPython.display.HTML(
f'<details><summary>{name}</summary>{content}</details>')
IPython.display.display(content)
The section is collapsed by default, but I uncollapsed it for the screenshot.
To prepend a cell from getting rendered in the output, in the notebook, by voilo or voila gridstack, just put in the first line of each cell to hide the output:
%%capture --no-display
reference in ipypthon documentation
For Windows,
in Jupyter Notebook, click the cell whose output you want to hide.
Click Esc + o for toggling the output
So I totally understand. When you have like 100 different plot and when you do the "Restart & Run All" those ugly plots all show up again
what you can do is ctrl+A and press o it will all of a sudden hide all your cells!!! For you to collapse automatically, you may need to use JupyterLab (another level after JupyterNotebook) but still, by doing ctrl+A then o you will be able to collapse all the results!!!
ctrl+A --> select ALL (make sure to click outside of coding box before you do it!)
o --> toggle collapse
If you don't mind a little hacking, then you may write a simple script for inverting the "collapsed" attribute of each cell from false to true
in the notebook .ipynb file (which is a simple JSON file).
This is however may fail in the future if a the .ipynb format changes.
I am new to using the matlab GUIDE. I know there are some predefined dialog boxes such as inputdlg and msgbox and warndlg and so on and so forth that can easily be implemented into the command line without having to play around with too many things.
However, I was wondering whether it was possible to modify inputdlg in matlab guide? I am just trying to produce a simple dialog box that reads the user input and when the user clicks ok, it closes and records the inputs somewhere. Using inputdlg it is very easy to do so:
uiwait(msgbox(sprintf('Please enter your new references for each electrode.')));
prompt = {'Fp1','Fp1','F7','T3','T5'};
dlg_title = 'Input references';
num_lines = 1;
answer = inputdlg(prompt,dlg_title,num_lines );
The user enters a string for each option 'Fp1', 'F7' and so on and all these answers are recorded in "answer".
Now I have 2 problems:
I have 16 such inputs and if I put them all inside the same "prompt" then the dialog box runs off the screen - so I use prompt, prompt2 and prompt3 to split them up and record the answers. It works fine, but it would be better if I could arrange the input boxes side by side as you can edit/drag inside the matlab guide.
I want my dialog box to look as it does in this picture with the minus sign between the 2 cells where the user will enter something into both boxes. The first box in each line is actually equivalent to the prompt that I have specified above, but in this case the user will enter the string into the first cell rather than being prompted for it.
But I can't seem to figure out how to do this either using inputdlg itself and altering its properties or using guide to create a custom inputdlg.
Does anybody have any advice?
Update
I have added some lines of code in the correct places and I am able to now store the user input to a variable. However, I have around 32 edit boxes and my current method means I will have 32 different inputs... I do not want this, I want them all to be recorded inside the same array.
The code I added was in the edit box callback function:
input = get(hObject, 'String')
display(input)
assignin('base','input',input);
% Save the value
handles.trial = input
guidata(hObject,handles)
This is from editbox1 and I have tried to proceed as
input = get(hObject, 'String')
A(1,:) = input
assignin('base','A',A(1,:));
but in this case it returns A as a cell which has the value entered in the last edit box.
Can anyone help?
First you should make matlab wait for the user to respond. Locate the OpeningFcn of you GUI. The last line should look like that
% uiwait(handles.figure1);
You should uncommon the line. Next, you have to resume the UI when the user clicks OK. This is done by inserting the line
uiresume(handles.figure1);
in the OK button callback. When the users clicks OK, the OutputFcn will be called. There you can return the values you need via varargout cell array. Finally, in the last line of OutputFcn, you should close your GUI using
close(hObject)
All the names I used are the matlab's defaults. If you changed any of them, modify the code accordingly.
I think it should be pretty simple what I want to do, basically I have one edit box that displays a value in percentages and another that I want to update to display raw values. I've tried using the following code under the edit1 (percent) callback:
currentKey = str2num(get(gcf,'CurrentKey'));
percent = str2num(get(handles.edit1,'String'));
if ~isnan(currentKey) && ~isnan(percent) && 0<=percent && percent<=100
set(handles.edit2,'String',num2str(2*percent))
end
But it will only update the second edit box if I first click outside of the first one. Anyone have an idea of what I should be doing?
Thanks!
I think this link should help you:
How can I make the text that I enter into an edit text box update dynamically?
Solution:
This enhancement has been incorporated in Release 2011a (R2011a). For previous product releases, read below for any possible workarounds:
This is expected behavior of the Edit Box UICONTROL in MATLAB.
You can try using the 'keypressfcn' to grab the keyboard input. The attached two files demonstrate the ability of real-time text update. As you enter text into the upper edit box, the text will be copied to the edit box beneath it as you enter.
Please download the following two files:
test_keypressfcn.m
test_keypressfcn.fig
Execute the program.
A GUI will appear. Enter text in the upper edit box displayed in the GUI.
Observe the text in the lower editbox is updated dynamically or in real-time as you enter test in the upper edit box.
Please note that this will work only for text that is continuously entered in the editbox. If you type in between words already entered in the editbox the gui will not perform as expected. You will need to implement logic similar to the one in this example to get the behavior that you desire.
I have a .m file written with definition of input & output variables along with calling of other function files which calculate the numeric output from provided numeric input.
I want to build a GUI in MATLAB for the same.
What I require is coding information for
1)Retrieving numeric data from 'edit text' component & pass this data assigned as input data
2)Set an action by clicking push button to run the program, calculate output from input & display the numeric values as output.
As far as I understand your question, it's pretty easy. I hope this will be helpful.
1. open guide by typing guide in command window.
2. click blank gui
3. guide window will open
4. click and drag a push button and an edit text.
5. click the editor
6. save your file
7. go to the follwing function
function pushbutton_Callback(hObject, eventdata, handles)
and write down this code below.
str = inputdlg('Enter numbers (seperated by commas)');
num = str2num(str{1});
a=num(:,1);
b=num(:,2);
ans=a+b; //or whatever you want to do!
caption = sprintf('your answer is %.2f',ans)
set(handles.edit,'string',caption)