matlab一行放不下,matlab一个figure里面subplot的行太多,如何保持每个子图的大小并加滚动条来上下滚动查看各个子图...

b14ce9464d2c7742bdb65121e4202564.png问题来源:来自桥哥的公众号后的留言

b14ce9464d2c7742bdb65121e4202564.png

b14ce9464d2c7742bdb65121e4202564.png

b14ce9464d2c7742bdb65121e4202564.png

b14ce9464d2c7742bdb65121e4202564.png

b14ce9464d2c7742bdb65121e4202564.png

b14ce9464d2c7742bdb65121e4202564.png

b14ce9464d2c7742bdb65121e4202564.png

33afbdd13380ad1bb5b1b841c51e9d46.png

今天上去在外面逛展会,看到桥哥发了一篇推文,看到了这个留言,感觉问题挺有意思,于是下午回来就试了一下

b14ce9464d2c7742bdb65121e4202564.png

794c627a06a8ecf676e3b573124e94cc.png

思路

(只考虑窗口内放不下这一系列子坐标系的情况)

首先要知道在matlab的figure中控件的Position属性值中的前两个元素支持负数!

可以这样去理解,matlab的figure或是Panel或是其他的,其坐标系统都是以左下角的点为坐标原点。在figure或是Panel的范围内都属于“第一象限”,我还是画一个图吧.......

54503a2fbaaf51509233ddcd8a3520b6.png

所以,我们可以用一个Panel来盛放这一些列子坐标系,把这个Panel设置为定宽,由于高度肯定是比窗口的高度要高了,所以可以设置这个Panel的纵坐标为负值(横坐标就设置为0,宽度与窗口等宽)。这个纵坐标具体值为:Panel的高度减去窗口的高度得出来的差值取相反数。

怎样滚动呢?可以直接用Slider控件(嫌丑的话自己做一个Slider,这里Slider是竖直的,slider在最上面时才是最大值状态),把其最大值设置为上面算出来的那个差值的绝对值,最小值就设置为0。然后去写Slider的callback,每点击一次就获取上一次点击时Slider的Value值,然后与当前Slider的Value值做差;如果算出来的这个差值为负,说明slider在向下滑动,因此对应的Panel是向上移动的,所以直接用Panel的纵坐标减去这个差值(减负数就是在加正数);差值为正则是相反的情况,同理。

794c627a06a8ecf676e3b573124e94cc.png

但是,我在做的时候没有用subplot画子图

b14ce9464d2c7742bdb65121e4202564.png,我用的之前讲过的Grid布局来布局若干个由axes生成的坐标系,然后在这些坐标系上画图。因为我觉得这样做出来的比subplot做出来的看着要舒服点

b14ce9464d2c7742bdb65121e4202564.png。不过你非要用subplot来整也基本差不多

9e26cc80cd6b165b7c22d30ccb269966.png

还有,如果把Panel或者其他控件放入布局中,你是没法改它的Position值(其实是改了也没用

b14ce9464d2c7742bdb65121e4202564.png),而我想让这个和Slider构成一个水平布局。所以我这里用了2个Panel,一个Panel(父Panel)用来和Slider进行水平布局,而其 子Panel才放那的些个Axes。

由于时间原因,这代码只是用来说明这个思路可行,没有做优化,有兴趣的大哥大姐可以自己优化一下并定制成一个函数,以后就用这个来当subplot用

2c6c3bc2a57553cd2dfa86b07b01c81c.png

比如:

1. 加一个判断,如果一个窗口能装下那些子坐标系,就不用显示Slider。

2. 不使用Slider而使用鼠标上下拖动的方式来移动Panel,等等。

另外,这思路不仅可用在这地方,如果你一个界面装不下那么多控件就可以用本文说的思路,但是不仅以用Slider来上下滑动,可以采用用鼠标拖拽界面的方式来实现。

794c627a06a8ecf676e3b573124e94cc.png

代码

function Multi_Subplot_Scroll(row, column)

% row: 子图的行数

% column: 子图的列数

%%

clc

close all

fMain  = figure('NumberTitle', 'off', ...

'Menubar', 'none', ...

'Units', 'pixels', ...

'Position', [500, 100, 1000, 500], ...

'Resize', 'off');

%%

% 创建一个水平布局

HBox = uiextras.HBox('Parent', fMain);

% 创建一个Panel用于放 子坐标 的Panel

Panel = uipanel('Parent', HBox);

% 创建一个slider用于滚动subplot

Slider = uicontrol('Style', 'slider', ...

'Parent', HBox, ...

'callback', {@callback_Slider, fMain});

% Slider宽20pix,剩下的宽度都给Panel

HBox.Widths = [-1, 20];

% 计算一下子坐标的宽度,实际上不用算(因为放到布局里面了),

% 这里算是为了大概算一下 子Panel的高度,

width_axes = fix( Panel.Position(3) / column ); % hight_axes = width_axes;

% 计算 子Panel的高度

Panel_Sub_Height = width_axes * row;

%% 这里不考虑行数很少,以至于一个窗口就能放下的情况(也就是只考虑放坐标的子Panel比其父Panel高)

% 计算高度差

diff_Height = Panel_Sub_Height - Panel.Position(4);

% 设置Slider的最大值为高度差

Slider.Max = diff_Height;

% 设置Slider的最小值为0

Slider.Min = 0;

% 设置Slider的当前值为Slider的最大值(把slider拿到上方去)

Slider.Value = Slider.Max;

% 初始化 上一次点击slider时slider的值 Slider_PreviousValue 为slider的最大值

setappdata(fMain, 'Slider_PreviousValue', Slider.Max)

% 创建 子Panel

Panel_Sub = uipanel('Parent', Panel, ...

'Units', 'pixels', ...

'Position', [0, -diff_Height, Panel.Position(3), Panel_Sub_Height], ...

'BackgroundColor', 'k');

% 保存 子Panel

setappdata(fMain, 'Panel_Sub', Panel_Sub)

% 创建网格布局

Grid_axes = uiextras.Grid('Parent', Panel_Sub);

% 画各个子图

for i = 1 : row * column

ax = axes('Parent', Grid_axes);

fplot(@sin)

end

% 设置网格布局的参数

Grid_axes.Heights = -ones(1, row);

Grid_axes.Widths = -ones(1, column);

end

function callback_Slider(self, ~, fMain)

% 获取Slider的上一次值

Slider_PreviousValue = getappdata(fMain, 'Slider_PreviousValue');

% 获取当前Slider的值

current_SliderValue = self.Value;

% 计算两者差值

diff_SliderValue = current_SliderValue - Slider_PreviousValue;

% 如果为负说明Slider向下滑,Panel_Sub应该向上动

% 获取放坐标系的Panel

Panel_Sub = getappdata(fMain, 'Panel_Sub');

% 计算要移动的高度

% 重置Panel_Sub的Position

Panel_Sub.Position(2) = Panel_Sub.Position(2) - diff_SliderValue;

% 保存当前Slider的Value

setappdata(fMain, 'Slider_PreviousValue', current_SliderValue)

end

(这两个function在同一个文件夹下)

其实也挺简单的

b14ce9464d2c7742bdb65121e4202564.png

b14ce9464d2c7742bdb65121e4202564.png

b14ce9464d2c7742bdb65121e4202564.png

b14ce9464d2c7742bdb65121e4202564.png,要再优化一下可能就麻烦了一点。

结果:

7e1dd5039ee5bd8237ddc113bd02fc01.gif

e9b47e870da4d7fad30e0c601c5c4bd3.png

--END--

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值