MATLAB Answers

How to design GUI buttons?

28 views (last 30 days)
John Doe
John Doe on 21 May 2020
Commented: Tommy on 4 Jun 2020
Hello everyone.
How can I design a GUI button like the picture above? With logos and text beside the logo? Thanks in advance.

  2 Comments

Mohammad Sami
Mohammad Sami on 22 May 2020
In App Designer, the uibutton have a property called Icon. You can set the Icon property to show an image.
If you want to group the buttons together, then use uitogglebutton with uibuttongroup.
John Doe
John Doe on 23 May 2020
I want it in GUIDE, not app designer.

Sign in to comment.

Accepted Answer

Tommy
Tommy on 28 May 2020
You can set the CData of a uicontrol pushbutton:
p = uicontrol('Style', 'pushbutton', 'Position', [100, 150, 100, 30], 'String', 'Pears');
% background
icon = 130*ones([p.Position([4 3]),3], 'uint8'); % dark gray border
icon(2:end-1,2:end-1,:) = 240; % lighter gray top half
icon(end/2+1:end-3,4:end-3,:) = 225; % medium gray bottom half
icon(2,2,:) = icon(1,1,:); icon(1,1,:) = 240; % rounded upper left edge
icon(2,end-1,:) = icon(1,end,:); icon(1,end,:) = 240; % rounded upper right edge
icon(end-1,2,:) = icon(end,1,:); icon(end,1,:) = 240; % rounded lower left edge
icon(end-1,end-1,:) = icon(end,end,:); icon(end,end,:) = 240; % rounded lower right edge
% image
img = imread('pears.png');
icon(6:25, 6:25, :) = imresize(img, [20, 20]); % place picture on background
p.CData = icon;
If you are creating many similar buttons, you might create a function which accepts the rgb values for the image and spits out the CData. And of course, you can move the image within the background. The above code just places it on the left side of the button with 5 pixels separating it from the edges.

  5 Comments

Show 2 older comments
Tommy
Tommy on 3 Jun 2020
Also, this seems to mess with the color change that happens when you hover over the button. You could use the figure motion callback to restore that functionality if you want. I'd be happy to try and create a small example if you want.
John Doe
John Doe on 3 Jun 2020
Hey Tommy. Thanks for the prompt reply.
What I meant is in my GUIDE, I already have a set of pushbuttons, let's say p1 and p2 with tag p1 and p2. How can I change the icon of them?
From your code, it seems like (my guess) you are programmatically creating the pushbuttons?
p = uicontrol('Style', 'pushbutton',...
'Position', [100, 150, 100, 30],...
'String', 'Pears',...
'Tag', 'whatever'); % <- here
Will this set of code will solve my problem? Kinda confused here.
A small example will surely help me, if that's not such a big of a deal for you.
Tommy
Tommy on 4 Jun 2020
Ah okay I see. That code does create a new pushbutton, named p. If you already have pushbuttons, you can definitely use them instead, but you'll have to find them. Possibly like this:
p1 = findobj('Tag', 'p1');
Then the rest of the code would be the same.
So for example, suppose you've created two buttons, with tags 'p1' and 'p2':
fig = figure;
uicontrol(fig,...
'Style', 'pushbutton',...
'Position', [100, 150, 100, 30],...
'String', 'Pears',...
'Tag', 'p1');
uicontrol(fig,...
'Style', 'pushbutton',...
'Position', [100, 190, 100, 30],...
'String', 'Peppers',...
'Tag', 'p2');
Elsewhere, you can use findobj to retrieve each button and assign its CData, possibly with another function getIcon() to do the dirty work:
tags = {'p1', 'p2'};
files = {'pears.png', 'peppers.png'};
for i = 1:numel(tags)
button = findobj('Tag', tags{i});
img = imread(files{i});
button.CData = getIcon(button, img);
end
function icon = getIcon(button, img)
% background
icon = 130*ones([button.Position([4 3]),3], 'uint8'); % dark gray border
icon(2:end-1,2:end-1,:) = 240; % lighter gray top half
icon(end/2+1:end-3,4:end-3,:) = 225; % medium gray bottom half
icon(2,2,:) = icon(1,1,:); icon(1,1,:) = 240; % rounded upper left edge
icon(2,end-1,:) = icon(1,end,:); icon(1,end,:) = 240; % rounded upper right edge
icon(end-1,2,:) = icon(end,1,:); icon(end,1,:) = 240; % rounded lower left edge
icon(end-1,end-1,:) = icon(end,end,:); icon(end,end,:) = 240; % rounded lower right edge
% image
icon(6:25, 6:25, :) = imresize(img, [20, 20]); % place picture on background
end
If all of your buttons are exactly the same size, you could probably avoid recreating the background each time.
Here is a simple example for changing the figure's motion callback:
% somewhere...
fig = figure;
uicontrol(fig,...
'Style', 'pushbutton',...
'Position', [100, 150, 100, 30],...
'String', 'Pears',...
'Tag', 'p1');
uicontrol(fig,...
'Style', 'pushbutton',...
'Position', [100, 190, 100, 30],...
'String', 'Peppers',...
'Tag', 'p2');
and
% maybe somewhere else...
tags = {'p1', 'p2'};
files = {'pears.png', 'peppers.png'};
for i = 1:numel(tags)
button = findobj('Tag', tags{i});
img = imread(files{i});
[button.CData, button.UserData] = getIcon(button, img);
end
function [icon, blueIcon] = getIcon(button, img)
% background
icon = 130*ones([button.Position([4 3]),3], 'uint8'); % dark gray border
icon(2:end-1,2:end-1,:) = 240; % lighter gray top half
icon(end/2+1:end-3,4:end-3,:) = 225; % medium gray bottom half
icon(2,2,:) = icon(1,1,:); icon(1,1,:) = 240; % rounded upper left edge
icon(2,end-1,:) = icon(1,end,:); icon(1,end,:) = 240; % rounded upper right edge
icon(end-1,2,:) = icon(end,1,:); icon(end,1,:) = 240; % rounded lower left edge
icon(end-1,end-1,:) = icon(end,end,:); icon(end,end,:) = 240; % rounded lower right edge
% alternate background
blueIcon = icon;
blueIcon(2:end-1,2:end-1,3) = blueIcon(2:end-1,2:end-1,3) + 15;
% image
icon(6:25, 6:25, :) = imresize(img, [20, 20]); % place picture on background
blueIcon(6:25, 6:25, :) = imresize(img, [20, 20]);
end
and
% possibly a third location...
tags = {'p1', 'p2'};
fig.WindowButtonMotionFcn = {@moveCallback, tags};
function moveCallback(src, ~, tags)
cPos = src.CurrentPoint;
% To store previous state, so that buttons are not updated every single time this
% function is called:
persistent wasInRect;
if isempty(wasInRect)
wasInRect = false(numel(tags),1);
end
for i = 1:numel(tags)
button = findobj('Tag', tags{i});
% Determine if mouse is on button:
bPos = button.Position;
isInRect = inpolygon(cPos(1), cPos(2), [bPos(1), bPos(1)+bPos(3)], [bPos(2), bPos(2)+bPos(4)]);
% Update button's CData, if necessary:
if (isInRect && ~wasInRect(i)) || (~isInRect && wasInRect(i))
flipCData(button);
wasInRect(i) = ~wasInRect(i);
end
end
function flipCData(button)
altIcon = button.UserData;
button.UserData = button.CData;
button.CData = altIcon;
end
end
You might want to adjust the colors somewhat. There may be better alternatives to using each button's UserData, but I think this at least illustrates the general idea.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!