What is the best way to display a large text file in MATLAB GUIDE? - user-interface

How can a MATLAB GUIDE control be used to display the contents of a text file in a GUI? The text file may be very long or very wide so it should have the ability to have vertical and horizontal scroll bars.

A multi-line editbox may be the best choice to display the text. Example:
%# read text file lines as cell array of strings
fid = fopen( fullfile(matlabroot,'license.txt') );
str = textscan(fid, '%s', 'Delimiter','\n'); str = str{1};
fclose(fid);
%# GUI with multi-line editbox
hFig = figure('Menubar','none', 'Toolbar','none');
hPan = uipanel(hFig, 'Title','Display window', ...
'Units','normalized', 'Position',[0.05 0.05 0.9 0.9]);
hEdit = uicontrol(hPan, 'Style','edit', 'FontSize',9, ...
'Min',0, 'Max',2, 'HorizontalAlignment','left', ...
'Units','normalized', 'Position',[0 0 1 1], ...
'String',str);
%# enable horizontal scrolling
jEdit = findjobj(hEdit);
jEditbox = jEdit.getViewport().getComponent(0);
jEditbox.setWrapping(false); %# turn off word-wrapping
jEditbox.setEditable(false); %# non-editable
set(jEdit,'HorizontalScrollBarPolicy',30); %# HORIZONTAL_SCROLLBAR_AS_NEEDED
%# maintain horizontal scrollbar policy which reverts back on component resize
hjEdit = handle(jEdit,'CallbackProperties');
set(hjEdit, 'ComponentResizedCallback',...
'set(gcbo,''HorizontalScrollBarPolicy'',30)')
To enable horizontal scrolling, we must get a handle to the embedded JScrollPane java component. I am using the excellent FINDJOBJ function. Then we set the HorizontalScrollBarPolicy property to javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED (= 30) as explained in this post. I also disabled editing of the text (read only).

Here is my solution for a generic text file called "textfile.txt":
f = figure('menu','none','toolbar','none');
fid = fopen('textfile.txt');
ph = uipanel(f,'Units','normalized','position',[0.4 0.3 0.5 0.5],'title',...
'Display window');
lbh = uicontrol(ph,'style','listbox','Units','normalized','position',...
[0 0 1 1],'FontSize',9);
indic = 1;
while 1
tline = fgetl(fid);
if ~ischar(tline),
break
end
strings{indic}=tline;
indic = indic + 1;
end
fclose(fid);
set(lbh,'string',strings);
set(lbh,'Value',1);
set(lbh,'Selected','on');

Here is my solution. Good Luck
fid = fopen(filename);
str = textscan(fid, '%s', 'Delimiter','\n'); str = str{1};
fclose(fid);
f=figure;
hPan = uipanel(f,'Units','normalized');
uicontrol(hPan, 'Style','listbox', ...
'HorizontalAlignment','left', ...
'Units','normalized', 'Position',[0 0 1 1], ...
'String',str);

Related

Once I have created my rating scales and flipped the screen, they do not appear. What am I doing wrong?

Once I have created the ratingscales in PsychoPy, I cannot get them to show after showing my stimuli. What am I doing wrong?
Preparing experiment
Define window:
win = visual.Window(fullscr=True, color = 'Black')
Preparing stimuli
Pictures
Make list of images in my folder:
images = glob.glob("Yellow/*.jpg")
Randomize the order for pictures:
random.shuffle(images)
Prepare Fixation cross
stim_fix_left = visual.TextStim(win, '+') # Fixation cross is just the character "+". Units are inherited from Window when not explicitly specified.
stim_fix_left.pos = (0.5,0)
stim_fix_right = visual.TextStim(win, '+') # Fixation cross is just the character "+". Units are inherited from Window when not explicitly specified.
stim_fix_right.pos = (-0.5, 0)
Ratings
# the item to-be-rated or respond to:
whichred_left = visual.TextStim(win, text="Does left or right picture contain most red?", height=.04, units='norm')
whichred_left.pos = (0.5,0)
whichred_right = visual.TextStim(win, text="Does left or right picture contain most red?", height=.04, units='norm')
whichred_right.pos = (-0.5, 0)
Create stimuli
Show introduction message:
msg(intro, "white")
Show introduction to block:
msg(block_red, "red")
for i in images:
##Pictures
stim_fix_right.draw()
stim_fix_left.draw()
win.flip()#flip screen
core.wait(1.0)
#Picture 1
img1 = visual.ImageStim(win, image = i)#create visual stimuli
img1.pos = (0.4, 0)
img1.size = (0.5)
#Picture 2
img2 = visual.ImageStim(win, image = images[2])#create visual stimuli
img2.pos = (0.7, 0)
img2.size = (0.5)
#Picture 3
img3 = visual.ImageStim(win, image = i)#create visual stimuli
img3.pos = (-0.4, 0)
img3.size = (0.5)
#Picture 4
img4 = visual.ImageStim(win, image = images[2])#create visual stimuli
img4.pos = (-0.7, 0)
img4.size = (0.5)
#Drawing picures
img1.draw()#draw picture
img2.draw()#draw picture
img3.draw()#draw picture
img4.draw()#draw picture
win.flip()#flip screen
stopwatch.reset() #set clock
core.wait(1.0)
#Ratings
event.clearEvents()
# define window
winrating = visual.Window(size = (1280, 720), color = 'black', units='pix')
x, y = winrating.size # for converting norm units to pix
leftward = -0.35 * x / 2 # use pix units, because the drawing window's units are pix
rightward = -1 * leftward
# create a RatingScale object:
RatingLeft = visual.RatingScale(winrating, choices=map(str, range(1, 8)), mouseOnly=True, pos=(leftward, -y/6),
marker='circle', size=0.85, name='left')
RatingRight = visual.RatingScale(winrating, choices=map(str, range(1, 8)), low=0, high=8, markerStart=4,
leftKeys='left', rightKeys = 'right', acceptKeys='down', pos=(rightward, -y/6),
marker='circle', size=0.85, name='right')
while RatingLeft.noResponse or RatingRight.noResponse:
whichred_left.draw
whichred_right.draw
RatingLeft.draw()
RatingRight.draw()
winrating.flip()
if event.getKeys(['escape']):
core.quit()
There is no need to define a second window. Do all of your drawing into your originally defined window, win. This is created as a full screen window, so I'd assume that the second window, winrating is hidden behind it and any drawing wouldn't be visible.

Textwidth not showing correctly in millimeters vb6

I have a picture box and I print contents in it. I want to know the exact textwidth of the text in millimeters. But I get wrong value. here is my code
me.scalemode = vbmillimeters
picturebox.scalemode = vbmillimeters
picturebox.fontname = "Arial"
picturebox.fontsize = 12
debug.print textwidth("AB.C.D.E. FGHIJKLMN")
When i measure in the printout in paper it is 48 mm
but it shows 32.97mm
please help me where am wrong.
Thanks in advance
If you need the width of the text printed to the picture box, use:
PictureBox.textwidth("AB.C.D.E. FGHIJKLMN")
What you are actually doing: textwidth("AB.C.D.E. FGHIJKLMN") is mesuring the same text printed to the Form (Me).
Doing like this would be less error-prone:
Dim TextWidth as Single
With PictureBox
.ScaleMode = vbMillimeters
.FontName = "Arial"
.FontSize = 12
TextWidth = .TextWidth("AB.C.D.E. FGHIJKLMN")
End With
because if you are then switching to paper, you can also easily switch context:
With SelectedPrinter....

Figure window showing up matlab

I have written this code to help me compare different image histograms however when i run it i get a figure window popping up. I can't see anywhere in the code where i have written imshow and am really confused. Can anyone see why? thanks
%ensure we start with an empty workspace
clear
myPath= 'C:\coursework\'; %#'
number_of_desired_results = 5; %top n results to return
images_path = strcat(myPath, 'fruitnveg');
images_file_names = dir(fullfile(images_path, '*.png'));
images = cell(length(images_file_names), 3);
number_of_images = length(images);
%textures contruction
%loop through all textures and store them
disp('Starting construction of search domain...');
for i = 1:length(images)
image = strcat(images_path, '\', images_file_names(i).name); %#'
%store image object of image
images{i, 1} = imread(image);
%store histogram of image
images{i, 2} = imhist(rgb2ind(images{i, 1}, colormap(colorcube(256))));
%store name of image
images{i, 3} = images_file_names(i).name;
disp(strcat({'Loaded image '}, num2str(i)));
end
disp('Construction of search domain done');
%load the three example images
RGB1 = imread('C:\coursework\examples\salmon.jpg');
X1 = rgb2ind(RGB1,colormap(colorcube(256)));
example1 = imhist(X1);
RGB2 = imread('C:\coursework\examples\eggs.jpg');
X2 = rgb2ind(RGB2,colormap(colorcube(256)));
example2 = imhist(X2);
RGB3 = imread('C:\coursework\examples\steak.jpg');
X3 = rgb2ind(RGB3,colormap(colorcube(256)));
example3 = imhist(X3);
disp('three examples loaded');
disp('compare examples to loaded fruit images');
results = cell(length(images), 2);
results2 = cell(length(images), 2);
results3 = cell(length(images), 2);
for i = 1:length(images)
results{i,1} = images{i,3};
results{i,2} = hi(example1,images{i, 2});
end
results = flipdim(sortrows(results,2),1);
for i = 1:length(images)
results2{i,1} = images{i,3};
results2{i,2} = hi(example2,images{i, 2});
end
results2 = flipdim(sortrows(results2,2),1);
for i = 1:length(images)
results3{i,1} = images{i,3};
results3{i,2} = hi(example3,images{i, 2});
end
results3 = flipdim(sortrows(results3,2),1);
The colormap function sets the current figure's colormap, if there is no figure one is created.
The second parameter of imhist should be the number of bins used in the histogram, not the colormap.
Run your code in the Matlab debugger, step through it line by line, and see when the figure window pops up. That'll tell you what's creating it.
Etienne's answer is right for why you're getting a figure, but I'd just like to add that colormap is unnecessary in this code:
images{i, 2} = imhist(rgb2ind(images{i, 1}, colormap(colorcube(256))));
All you need is:
images{i, 2} = imhist(rgb2ind(images{i, 1}, colorcube(256)));
The second input of rgb2ind should be a colormap, yes. But the output of colorcube is a colormap already. Unless you've got an existing figure and you either want to set the colormap of it or retrieve the colormap it is currently using, the actual function colormap is not necessary.
Other than opening an unnecessary figure, the output of your existing code won't be wrong, as I think in this situation colormap will just pass as an output argument the colormap it was given as an input argument. For example, if you want to set the current figure colormap to one of the inbuilts and return the actual colormap:
cmap = colormap('bone');

Create a title with two colors in RMagick

I need to create a caption for a picture using two colors, all the words are in black except one in other color...
I've been reading the docs of RMagick I can't find a way of doing this... What I'm using right now to create the text is:
txt_name = Draw.new
image.annotate(txt_name, 0,0,0,0, "This RED has to be in red") do
self.gravity = Magick::NorthGravity
self.pointsize = 20
self.fill = '#000000'
txt_name.font_weight = 100
self.font_family = 'Arial'
end
Any idea?? Or something to read so I can make this work??
Thanks!
Something like the following should work for you. (Please note that this is just to show you the process; I wouldn't recommend putting code like this into production. This is begging to be put in its own class EDIT: see below):
draw = Magick::Draw.new
Set all of the text attributes on the draw object:
draw.pointsize = 20
draw.fill = '#000000'
draw.gravity = Magick::NorthGravity
draw.font_weight = 100
draw.font_family = "Arial"
draw.font_style = Magick::NormalStyle
Get your image object (this one is just a new blank image):
image = Magick::Image.new(300,200)
Set up the strings and measure them with get_type_metrics:
black_text = "This "
red_text = "RED"
remainder = " has to be in red"
black_text_metrics = draw.get_type_metrics(black_text)
red_text_metrics = draw.get_type_metrics(red_text)
remainder_metrics = draw.get_type_metrics(remainder)
Annotate with the black text:
draw.annotate(image,
black_text_metrics.width,
black_text_metrics.height,
10,10,black_text)
Change the color to red and add the red text:
draw.fill = "#ff0000"
draw.annotate(image,
red_text_metrics.width,
red_text_metrics.height,
10 + black_text_metrics.width, # x value set to the initial offset plus the width of the black text
10, red_text)
Change the color back to black and add the remainder of the text:
draw.fill = "#000000"
draw.annotate(image,
remainder_metrics.width,
remainder_metrics.height,
10 + black_text_metrics.width + red_text_metrics.width,
10, remainder)
Edit: This may give you an idea of how you could structure this a bit nicer:
TextFragment = Struct.new(:string, :color)
class Annotator
attr_reader :text_fragments
attr_accessor :current_color
def initialize(color = nil)
#current_color = color || "#000000"
#text_fragments = []
end
def add_string(string, color = nil)
text_fragments << TextFragment.new(string, color || current_color)
end
end
class Magick::Draw
def annotate_multiple(image, annotator, x, y)
annotator.text_fragments.each do |fragment|
metrics = get_type_metrics(fragment.string)
self.fill = fragment.color
annotate(image, metrics.width, metrics.height, x, y, fragment.string)
x += metrics.width
end
end
end
and a usage example:
image = Magick::Image.new(300,200)
draw = Magic::Draw.new
draw.pointsize = 24
draw.font_family = "Arial"
draw.gravity = Magick::NorthGravity
annotator = Annotator.new #using the default color (black)
annotator.add_string "Hello "
annotator.add_string "World", "#ff0000"
annotator.add_string "!"
draw.annotate_multiple(image, annotator, 10, 10)

Save a plot to a JPEG file in Matlab

I have designed the following GUI in which there are an axes. I want to save the plot drawn inside them to a jpeg file. However, the file obtained is an image of the overall figure window. This is my code:
X = 0:pi/100:2*pi;
Y = sin(X);
fh = figure;
Pan1 = uipanel(fh,'Units','normalized','Position',[0 0 0.5 1],'title',...
'Panel1');
Pan2 = uipanel(fh,'Units','normalized','Position',[0.5 0 0.5 1],'title',...
'Panel2');
haxes = axes('Parent',Pan2,'Units', 'normalized','Position',...
[0.25 0.25 0.5 0.5]);
hplot = plot(haxes,X,Y);
xlabel(haxes,'Time (second)');
ylabel(haxes,'Amplitude (meter)');
title(haxes,'Sine function');
FileName = uiputfile('*.jpg','Save as');
saveas(hplot,FileName);
saveas only saves figures, not individual plots.
If you have a subplot, or a plot within a uicontrol like you have, you can make a temporary copy of the plot, save it, then delete the temporary copy:
ftmp = figure; atmp = axes;
copyobj(hplot, atmp);
saveas(ftmp, FileName);
delete(ftmp);
If you don't want the temporary copy to flash up on the screen during the copying step, you can use the 'Position' property of the figure to create it off-screen.
Hope that helps!
#Sam's answer is spot on, I just want to add that Matlab is smart enough to know what kind of file you want to save by inspecting the FileName string variable. If you set FileName to something that ends in .jpg, you can save a jpeg. Check out the saves docs to see all the other possible filetypes.
When using the saveas function to create jpeg the resolution is different as when manually saving the figure with File-->Save As..., It's more recommended to use hgexport instead, as follows:
hgexport(gcf, 'figure1.jpg', hgexport('factorystyle'), 'Format', 'jpeg');
This will do exactly as manually saving the figure.
source:
http://www.mathworks.com/support/solutions/en/data/1-1PT49C/index.html?product=SL&solution=1-1PT49C
This is my solution based on Sam Roberts and eykanal's answer:
X = 0:pi/100:2*pi;
Y = sin(X);
fh = figure('toolbar','none','menubar','none');
Pan1 = uipanel(fh,'Units','normalized','Position',[0 0 0.5 1],'title',...
'Panel1');
Pan2 = uipanel(fh,'Units','normalized','Position',[0.5 0 0.5 1],'title',...
'Panel2');
haxes = axes('Parent',Pan2,'Units', 'normalized','Position',...
[0.125 0.1 0.75 0.75]);
hplot = plot(haxes,X,Y);
xlabel(haxes,'Time (second)');
ylabel(haxes,'Amplitude (meter)');
title(haxes,'Sine function');
FileName = uiputfile('*.bmp;*.png;*.jpg;*.tif','Save as');
ftmp = figure('Menu','none','Toolbar','none','Units','normalized',...
'Position',[-1000 -1000 1 1]);
new_axes = copyobj(haxes, ftmp);
set(new_axes,'Units','normalized','Position',[0.1 0.1 0.8 0.8]);
saveas(ftmp, FileName);
delete(ftmp);
delete(fh);

Resources