[英]Sliding a point on a curve
I have tried the following code in Matlab 2017b: 我已经在Matlab 2017b中尝试了以下代码:
function demo()
clc,close all
fig=figure();
ax=axes(fig,...
'Units','Normalized',...
'Position',[0.2,0.2,0.6,0.6],...
'XGrid','on',...
'YGrid','on')
slider=uicontrol(...
'Parent',fig,...
'Style','slider',...
'Units','normalized',...
'Position',[0.2,0.9,0.6,0.05],...
'Tag','slider1',...
'Min',0,...
'Max',10,...
'Value',1,...
'Callback',@slider_callback);
x=linspace(0,10);
y=1/3*x.^2;
plot(x,y,'b-')
grid on
xlabel('x-axis')
ylabel('y-axis')
hold on
p=plot(1,1/3,'ro')
hold off
function slider_callback(hObject,eventdata)
x=hObject.Value;
p.XData=x;
p.YData=1/3*x.^2;
drawnow
end
end
Currently, I move the slider and it is only when I release the mouse button that the point is updated. 当前,我移动滑块,并且只有在释放鼠标按钮时,点才会更新。 What changes can I make so that I see the point move as I drag the slider? 我可以进行哪些更改,以便在拖动滑块时看到点移动?
Thanks. 谢谢。
UPDATE : Thanks to VIG's comment, I was able to do this: 更新 :感谢VIG的评论,我能够做到这一点:
function demo()
clc,close all
fig=figure();
% initialize some parameters
xstart=4;
ystart=1/3*4^2;
ax=axes(fig,...
'Units','Normalized',...
'Position',[0.2,0.2,0.6,0.6],...
'XGrid','on',...
'YGrid','on');
slider=uicontrol(...
'Parent',fig,...
'Style','slider',...
'Units','normalized',...
'Position',[0.2,0.9,0.6,0.05],...
'Tag','slider1',...
'Min',0,...
'Max',10,...
'Value',xstart);
addlistener(slider,'Value',...
'PostSet',@(hObject, event) slider_callback(slider, event));
x=linspace(0,10);
y=1/3*x.^2;
plot(x,y,'b-')
grid on
xlabel('x-axis')
ylabel('y-axis')
hold on
plot([-5,10],[0,0],'k-');
plot([0,0],[-5,35],'k-');
p=plot(xstart,ystart,'ro');
a1=quiver(0,0,xstart,ystart,0,...
'LineWidth',1,...
'Color','red');
a2=quiver(0,0,0,xstart,0,...
'LineWidth',1,...
'Color','red');
a3=quiver(0,0,xstart,0,0,...
'LineWidth',1,...
'Color','red');
d=plot([0,xstart,xstart],[ystart,ystart,0],'k--');
hold off
function slider_callback(hObject,eventdata)
x=hObject.Value;
p.XData=x;
p.YData=1/3*x.^2;
a1.UData=x;
a1.VData=1/3*x.^2;
a2.VData=1/3*x.^2;
a3.UData=x;
d.XData=[0,x,x];
d.YData=[1/3*x.^2,1/3*x.^2,0];
drawnow
end
end
Which produces this image: 产生此图像:
I'd love to hear any further suggestions. 我希望听到其他建议。
Thanks. 谢谢。
You need to add a listener, and then you might omit the callback when creating the slider: 您需要添加一个侦听器,然后在创建滑块时可能会省略回调:
slider=uicontrol(...
'Parent',fig,...
'Style','slider',...
'Units','normalized',...
'Position',[0.2,0.9,0.6,0.05],...
'Tag','slider1',...
'Min',0,...
'Max',10,...
'Value',1);
addlistener(slider,'Value','PostSet',@(hObject, event) slider_callback(slider, event));
EDIT: 编辑:
You can use impoint
. 您可以使用impoint
。 Then add: 然后加:
....
addlistener(slider,'Value',...
'PostSet',@(hObject, event) slider_callback(slider, event));
h = impoint(gca,xstart,ystart);
setColor(h,'r')
point = h;
addNewPositionCallback(h,@(h) make_constraint(h));
x=linspace(0,10);
...
and delete the plot p=plot(xstart,ystart,'ro');
并删除图p=plot(xstart,ystart,'ro');
. 。
In slider_callback
replace 在slider_callback
替换
p.XData=x;
p.YData=1/3*x.^2;
with 与
setPosition(point, [x 1/3*x^2])
and add 并添加
function make_constraint(h)
fcn = makeConstrainToRectFcn('impoint',[0 10],[1/3*h(1).^2 1/3*h(1).^2]);
% Enforce boundary constraint function using setPositionConstraintFcn
setPositionConstraintFcn(point,fcn);
a1.UData=h(1);
a1.VData=1/3*h(1).^2;
a2.VData=1/3*h(1).^2;
a3.UData=h(1);
d.XData=[0,h(1),h(1)];
d.YData=[1/3*h(1).^2,1/3*h(1).^2,0];
set(slider, 'Value', h(1))
drawnow
end
So total code: 所以总代码:
function stackover()
clc,close all
fig=figure();
% initialize some parameters
xstart=4;
ystart=1/3*4^2;
ax=axes(fig,...
'Units','Normalized',...
'Position',[0.2,0.2,0.6,0.6],...
'XGrid','on',...
'YGrid','on');
slider=uicontrol(...
'Parent',fig,...
'Style','slider',...
'Units','normalized',...
'Position',[0.2,0.9,0.6,0.05],...
'Tag','slider1',...
'Min',0,...
'Max',10,...
'Value',xstart);
addlistener(slider,'Value',...
'PostSet',@(hObject, event) slider_callback(slider, event));
h = impoint(gca,xstart,ystart);
setColor(h,'r')
point = h;
addNewPositionCallback(h,@(h) make_constraint(h));
x=linspace(0,10);
y=1/3*x.^2;
plot(x,y,'b-')
grid on
xlabel('x-axis')
ylabel('y-axis')
hold on
plot([-5,10],[0,0],'k-');
plot([0,0],[-5,35],'k-');
a1=quiver(0,0,xstart,ystart,0,...
'LineWidth',1,...
'Color','red');
a2=quiver(0,0,0,xstart,0,...
'LineWidth',1,...
'Color','red');
a3=quiver(0,0,xstart,0,0,...
'LineWidth',1,...
'Color','red');
d=plot([0,xstart,xstart],[ystart,ystart,0],'k--');
hold off
function slider_callback(hObject,eventdata)
x=hObject.Value;
setPosition(point, [x 1/3*x^2])
a1.UData=x;
a1.VData=1/3*x.^2;
a2.VData=1/3*x.^2;
a3.UData=x;
d.XData=[0,x,x];
d.YData=[1/3*x.^2,1/3*x.^2,0];
drawnow
end
function make_constraint(h)
fcn = makeConstrainToRectFcn('impoint',[0 10],[1/3*h(1).^2 1/3*h(1).^2]);
% Enforce boundary constraint function using setPositionConstraintFcn
setPositionConstraintFcn(point,fcn);
a1.UData=h(1);
a1.VData=1/3*h(1).^2;
a2.VData=1/3*h(1).^2;
a3.UData=h(1);
d.XData=[0,h(1),h(1)];
d.YData=[1/3*h(1).^2,1/3*h(1).^2,0];
set(slider, 'Value', h(1))
drawnow
end
end
ps demo()
is an existing MATLAB function, so it's best that you choose another name. ps demo()
是现有的MATLAB函数,因此最好选择另一个名称。
EDIT 2: 编辑2:
In the case that you can't use impoint
, you have to add 3 listeners: 如果您不能使用impoint
,则必须添加3个侦听器:
WindowButtonUpFcn
: detects when mouse is released. WindowButtonUpFcn
:检测何时释放鼠标。 WindowButtonMotionFcn
: detects when mouse is moved. WindowButtonMotionFcn
:检测何时移动鼠标。 ButtonDownFcn
: detects when mouse is clicked. ButtonDownFcn
:检测何时单击鼠标。 The first 2 need to be attached to the figure: 前2个需要附加到该图上:
fig=figure('WindowButtonUpFcn',@drop,'WindowButtonMotionFcn',@move);
The last one can be attached to the plot only: 最后一个只能附加到图上:
p=plot(xstart,ystart,'ro','ButtonDownFcn',@click);
Since WindowButtonUpFcn
and WindowButtonMotionFcn
are for the whole figure, these will always be called on motion or release of the mouse. 由于WindowButtonUpFcn
和WindowButtonMotionFcn
用于整个图形,因此始终会在移动或释放鼠标时调用它们。 But we only want the functions to be executed when dragging the point. 但是我们只希望在拖动点时执行功能。 To do this a variable ( dragging
) is introduced. 为此,引入了一个变量( dragging
)。 In the click
function this variable is set to 1
, to indicate that we're dragging. 在click
函数中,此变量设置为1
,以指示我们正在拖动。
Then while moving the mouse, the point, quivers and slider are updated in move
. 然后,在移动鼠标时,点,颤动和滑块会在move
中更新。 Here a control unit is added to make sure you don't drag the point out of the boundaries of the slider. 在此处添加了一个控制单元,以确保您不会将点拖出滑块的边界。
When the mouse is released, dragging
is set to 0
again. 释放鼠标时, dragging
再次设置为0
。
Of course it would be nice to know when you are hovering above the point, so that you know that if you click now, you can drag the point. 当然,很高兴知道您何时将鼠标悬停在该点上方,以便知道如果单击现在可以拖动该点。 To do this we can set the pointerbehaviour with 为此,我们可以使用
iptSetPointerBehavior(p, pointerBehavior);
Here pointerBehavior
is a struct containing 3 functions: 这里的pointerBehavior
是一个包含3个函数的结构:
enterFcn
: executed when mouse enters object. enterFcn
:当鼠标进入对象时执行。 exitFcn
: executed when mouse exits object. exitFcn
:当鼠标退出对象时执行。 traverseFcn
: executed when mouse enters object and when it moves in object. traverseFcn
:当鼠标进入对象并在对象中移动时执行。 We don't need the last one. 我们不需要最后一个。 When entering the mousepointer is set to be a cross with arrows on the edges, when leaving the point is transformed to the (regular) arrow. 输入鼠标指针时,将其设置为边缘上带有箭头的十字,离开鼠标时,该点将转换为(常规)箭头。 (for more info see iptSetPointerBehavior and hggroup ) (有关更多信息,请参见iptSetPointerBehavior和hggroup )
The total code is then: 然后,总代码为:
function stackover()
clc,close all
fig=figure('WindowButtonUpFcn',@drop,'WindowButtonMotionFcn',@move);
% initialize some parameters
xstart=4;
ystart=1/3*4^2;
dragging = 0;
ax=axes('Units','Normalized',...
'Position',[0.2,0.2,0.6,0.6],...
'XGrid','on',...
'YGrid','on');
slider=uicontrol(...
'Parent',fig,...
'Style','slider',...
'Units','normalized',...
'Position',[0.2,0.9,0.6,0.05],...
'Tag','slider1',...
'Min',0,...
'Max',10,...
'Value',xstart);
addlistener(slider,'Value',...
'PostSet',@(hObject, event) slider_callback(slider, event));
pointerBehavior.enterFcn = @(figHandle, currentPoint) set(figHandle, 'Pointer', 'fleur');
pointerBehavior.exitFcn = @(figHandle, currentPoint) set(figHandle, 'Pointer', 'arrow');
pointerBehavior.traverseFcn = [];
x=linspace(0,10);
y=1/3*x.^2;
plot(x,y,'b-')
grid on
xlabel('x-axis')
ylabel('y-axis')
hold on
plot([-5,10],[0,0],'k-');
plot([0,0],[-5,35],'k-');
p=plot(xstart,ystart,'ro','ButtonDownFcn',@click);
iptSetPointerBehavior(p, pointerBehavior); % set behaviour of pointer when over p
iptPointerManager(gcf); % let figure know what you're doing
a1=quiver(0,0,xstart,ystart,0,...
'LineWidth',1,...
'Color','red');
a2=quiver(0,0,0,xstart,0,...
'LineWidth',1,...
'Color','red');
a3=quiver(0,0,xstart,0,0,...
'LineWidth',1,...
'Color','red');
d=plot([0,xstart,xstart],[ystart,ystart,0],'k--');
hold off
function slider_callback(hObject,eventdata)
x=hObject.Value;
p.XData=x;
p.YData=1/3*x.^2;
a1.UData=x;
a1.VData=1/3*x.^2;
a2.VData=1/3*x.^2;
a3.UData=x;
d.XData=[0,x,x];
d.YData=[1/3*x.^2,1/3*x.^2,0];
drawnow
end
function click(hObject,eventdata)
dragging = 1;
end
function drop(hObject,eventdata)
dragging = 0;
end
function move(hObject,eventdata)
if dragging
mouse = ax.CurrentPoint;
x = mouse(1,1);
if x >= slider.Max
x = slider.Max;
elseif x <= slider.Min
x = slider.Min;
end
p.XData=x;
p.YData=1/3*x.^2;
a1.UData=x;
a1.VData=1/3*x.^2;
a2.VData=1/3*x.^2;
a3.UData=x;
d.XData=[0,x,x];
d.YData=[1/3*x.^2,1/3*x.^2,0];
slider.Value = x;
drawnow
end
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.