回调函数抛出意外 "nonconformant arguments" 错误
callback function throws unexpected "nonconformant arguments" error
我使用的是 GNU Octave,版本 4.4.1。我正在尝试通过包含两个滑块来制作一个简单振荡器的交互式图,这两个滑块将允许更改初始速度和振荡器质量。
情节本身显示良好,以及带有一个滑块(用于速度)的脚本。这是带有回调函数的脚本的一部分:
function titranje_ia1 (hslider, event)
v0 = get ( hslider, "value" );
m = 1;
k = 1;
t = 0:0.1:30;
x = v0*sin(sqrt(k/m)*t);
axes ('position', [0.1, 0.2, 0.8, 0.75]);
h = plot ( t, x );
axis ([0 30 -11 11]);
set (h, "linewidth", 2);
set (gca, "xlabel", "t (s)", "ylabel", "x (m)", "fontsize", 12);
set (gca, 'XTick', 0:pi:10*pi)
set (gca, 'XTickLabel', {'0','\pi','2\pi','3\pi','4\pi','5\pi','6\pi','7\pi','8\pi','9\pi','10\pi'})
grid on;
l = legend (sprintf('v0 = %f', v0));
set (l, "fontsize", 12)
endfunction
但是,当我包含第二个滑块时
function titranje_ia2 (hslider1, hslider2, event)
v0 = get ( hslider1, "value" );
m = get ( hslider2, "value" );
k = 1;
t = 0:0.1:30;
x = v0.*sin(sqrt(k./m).*t);
axes ('position', [0.1, 0.2, 0.8, 0.75]);
h = plot ( t, x );
axis ([0 30 -11 11]);
set (h, "linewidth", 2);
set (gca, "xlabel", "t (s)", "ylabel", "x (m)", "fontsize", 12);
set (gca, 'XTick', 0:pi:10*pi)
set (gca, 'XTickLabel', {'0','\pi','2\pi','3\pi','4\pi','5\pi','6\pi','7\pi','8\pi','9\pi','10\pi'})
grid on;
l = legend (sprintf('v0 = %f', v0));
set (l, "fontsize", 12)
endfunction
我收到一个错误:
error: titranje_ia2: product: nonconformant arguments (op1 is 0x0, op2 is 1x301)
execution error in graphics callback function
因为我知道 'k' 是一个标量而 't' 是一个向量(但我不确定 v0 和 m 是什么;我想是标量),我在函数 'x' 定义。 't' 大小是 1x301,所以我假设 'sqrt(k./m)' 是 0x0(如 Octave 所见)。不应该是1x1吗?
确实,当我尝试
size(m)
我收到 ans = 0 0(对于 size(v0),我收到 ans = 1 1)。会不会是滑块定义有问题?我在最后包含两个滑块定义:
%Definiramo ui element: 'klizac' za v0
hslider1 = uicontrol (
"style", "slider",
"units", "normalized",
"position", [0.1, 0.0, 0.8, 0.1],
"min", 1,
"max", 10,
"value", 4,
"callback", @titranje_ia2
);
%Definiramo ui element: 'klizac' za m
hslider2 = uicontrol (
"style", "slider",
"units", "normalized",
"position", [0.1, 0.05, 0.8, 0.1],
"min", 1,
"max", 10,
"value", 1,
"callback", @titranje_ia2
);
提前谢谢您!
最好的问候,
伊戈尔
您似乎误解了回调的工作原理。每当您与 uicontrol 对象交互时,关联的回调 always 自动调用 [至少] 两个 个参数:第一个总是 'handle'对应的触发回调的uicontrol对象,第二个是触发的'event'的类型。因此,您的回调函数需要 始终 至少具有 callbackname( hndl, evt )
的签名,以便它可以处理默认传递给它的这两个参数。
如果需要,您可以指定 额外的 参数传递给回调函数,但这些参数必须在回调函数内部被解释为第三个、第四个等等(请参阅下面的示例)。
如果您遇到像您这样的情况,您并不真正关心事件起源于何处,并且您想影响(或者在这种情况下'read from' ) 单个回调中的两个现有 uicontrol,无论哪个触发了事件,最简单的做法是将两个滑块句柄设为回调的额外参数,并简单地忽略第一个参数(即 'active handle')在你的回调中。 (实际上,您也已经忽略了 'event' 参数!)。
这是一个例子:
%% In file makesliders.m
function makesliders()
% Label and slider for initial velocity
IV_label = uicontrol( 'style', 'text' , 'units', 'normalized', 'position', [0.10, 0.025, 0.30, 0.075], 'string', 'Initial Velocity' );
IV_slider = uicontrol( 'style', 'slider', 'units', 'normalized', 'position', [0.45, 0.025, 0.50, 0.075], 'min', 1, 'max', 10 );
% Label and slider for oscillator mass
OM_label = uicontrol( 'style', 'text' , 'units', 'normalized', 'position', [0.10, 0.125, 0.30, 0.075], 'string', 'Oscillator Mass ' );
OM_slider = uicontrol( 'style', 'slider', 'units', 'normalized', 'position', [0.45, 0.125, 0.50, 0.075], 'min', 1, 'max', 10 );
% Set callbacks and initial values to IV and OM sliders, and plot initial graph
v0_init = 4; m_init = 1;
set( IV_slider, 'value', v0_init, 'callback', { @slider_callback, IV_slider, OM_slider } );
set( OM_slider, 'value', m_init , 'callback', { @slider_callback, IV_slider, OM_slider } );
plot_oscillation( v0_init, m_init );
endfunction
function slider_callback (active_handle, event, IV_slider, OM_slider )
v0 = get( IV_slider, 'value' );
m = get( OM_slider, 'value' );
plot_oscillation( v0, m );
endfunction
function plot_oscillation( v0, m )
k = 1;
t = 0 : 0.1 : 30;
x = v0 * sin( sqrt( k / m ) * t );
h = plot( t, x ); set( h , 'linewidth', 2);
set( gca, 'position', [0.1, 0.325, 0.85, 0.650], 'xlim', [0, 30], 'ylim', [-11, 11], 'xlabel', 't (s)', 'ylabel', 'x (m)', 'fontsize', 12, 'xtick', [0 : pi : 10 * pi], 'xticklabel', strcat( arrayfun( @num2str, 0:10, 'uniformoutput', false ), '\pi' ), 'xgrid', 'on', 'ygrid', 'on' );
l = legend( sprintf( 'v0 = %.2f, m = %.2f', v0, m ) ); set( l, 'fontsize', 12 );
endfunction
我使用的是 GNU Octave,版本 4.4.1。我正在尝试通过包含两个滑块来制作一个简单振荡器的交互式图,这两个滑块将允许更改初始速度和振荡器质量。 情节本身显示良好,以及带有一个滑块(用于速度)的脚本。这是带有回调函数的脚本的一部分:
function titranje_ia1 (hslider, event)
v0 = get ( hslider, "value" );
m = 1;
k = 1;
t = 0:0.1:30;
x = v0*sin(sqrt(k/m)*t);
axes ('position', [0.1, 0.2, 0.8, 0.75]);
h = plot ( t, x );
axis ([0 30 -11 11]);
set (h, "linewidth", 2);
set (gca, "xlabel", "t (s)", "ylabel", "x (m)", "fontsize", 12);
set (gca, 'XTick', 0:pi:10*pi)
set (gca, 'XTickLabel', {'0','\pi','2\pi','3\pi','4\pi','5\pi','6\pi','7\pi','8\pi','9\pi','10\pi'})
grid on;
l = legend (sprintf('v0 = %f', v0));
set (l, "fontsize", 12)
endfunction
但是,当我包含第二个滑块时
function titranje_ia2 (hslider1, hslider2, event)
v0 = get ( hslider1, "value" );
m = get ( hslider2, "value" );
k = 1;
t = 0:0.1:30;
x = v0.*sin(sqrt(k./m).*t);
axes ('position', [0.1, 0.2, 0.8, 0.75]);
h = plot ( t, x );
axis ([0 30 -11 11]);
set (h, "linewidth", 2);
set (gca, "xlabel", "t (s)", "ylabel", "x (m)", "fontsize", 12);
set (gca, 'XTick', 0:pi:10*pi)
set (gca, 'XTickLabel', {'0','\pi','2\pi','3\pi','4\pi','5\pi','6\pi','7\pi','8\pi','9\pi','10\pi'})
grid on;
l = legend (sprintf('v0 = %f', v0));
set (l, "fontsize", 12)
endfunction
我收到一个错误:
error: titranje_ia2: product: nonconformant arguments (op1 is 0x0, op2 is 1x301) execution error in graphics callback function
因为我知道 'k' 是一个标量而 't' 是一个向量(但我不确定 v0 和 m 是什么;我想是标量),我在函数 'x' 定义。 't' 大小是 1x301,所以我假设 'sqrt(k./m)' 是 0x0(如 Octave 所见)。不应该是1x1吗? 确实,当我尝试
size(m)
我收到 ans = 0 0(对于 size(v0),我收到 ans = 1 1)。会不会是滑块定义有问题?我在最后包含两个滑块定义:
%Definiramo ui element: 'klizac' za v0
hslider1 = uicontrol (
"style", "slider",
"units", "normalized",
"position", [0.1, 0.0, 0.8, 0.1],
"min", 1,
"max", 10,
"value", 4,
"callback", @titranje_ia2
);
%Definiramo ui element: 'klizac' za m
hslider2 = uicontrol (
"style", "slider",
"units", "normalized",
"position", [0.1, 0.05, 0.8, 0.1],
"min", 1,
"max", 10,
"value", 1,
"callback", @titranje_ia2
);
提前谢谢您! 最好的问候,
伊戈尔
您似乎误解了回调的工作原理。每当您与 uicontrol 对象交互时,关联的回调 always 自动调用 [至少] 两个 个参数:第一个总是 'handle'对应的触发回调的uicontrol对象,第二个是触发的'event'的类型。因此,您的回调函数需要 始终 至少具有 callbackname( hndl, evt )
的签名,以便它可以处理默认传递给它的这两个参数。
如果需要,您可以指定 额外的 参数传递给回调函数,但这些参数必须在回调函数内部被解释为第三个、第四个等等(请参阅下面的示例)。
如果您遇到像您这样的情况,您并不真正关心事件起源于何处,并且您想影响(或者在这种情况下'read from' ) 单个回调中的两个现有 uicontrol,无论哪个触发了事件,最简单的做法是将两个滑块句柄设为回调的额外参数,并简单地忽略第一个参数(即 'active handle')在你的回调中。 (实际上,您也已经忽略了 'event' 参数!)。
这是一个例子:
%% In file makesliders.m
function makesliders()
% Label and slider for initial velocity
IV_label = uicontrol( 'style', 'text' , 'units', 'normalized', 'position', [0.10, 0.025, 0.30, 0.075], 'string', 'Initial Velocity' );
IV_slider = uicontrol( 'style', 'slider', 'units', 'normalized', 'position', [0.45, 0.025, 0.50, 0.075], 'min', 1, 'max', 10 );
% Label and slider for oscillator mass
OM_label = uicontrol( 'style', 'text' , 'units', 'normalized', 'position', [0.10, 0.125, 0.30, 0.075], 'string', 'Oscillator Mass ' );
OM_slider = uicontrol( 'style', 'slider', 'units', 'normalized', 'position', [0.45, 0.125, 0.50, 0.075], 'min', 1, 'max', 10 );
% Set callbacks and initial values to IV and OM sliders, and plot initial graph
v0_init = 4; m_init = 1;
set( IV_slider, 'value', v0_init, 'callback', { @slider_callback, IV_slider, OM_slider } );
set( OM_slider, 'value', m_init , 'callback', { @slider_callback, IV_slider, OM_slider } );
plot_oscillation( v0_init, m_init );
endfunction
function slider_callback (active_handle, event, IV_slider, OM_slider )
v0 = get( IV_slider, 'value' );
m = get( OM_slider, 'value' );
plot_oscillation( v0, m );
endfunction
function plot_oscillation( v0, m )
k = 1;
t = 0 : 0.1 : 30;
x = v0 * sin( sqrt( k / m ) * t );
h = plot( t, x ); set( h , 'linewidth', 2);
set( gca, 'position', [0.1, 0.325, 0.85, 0.650], 'xlim', [0, 30], 'ylim', [-11, 11], 'xlabel', 't (s)', 'ylabel', 'x (m)', 'fontsize', 12, 'xtick', [0 : pi : 10 * pi], 'xticklabel', strcat( arrayfun( @num2str, 0:10, 'uniformoutput', false ), '\pi' ), 'xgrid', 'on', 'ygrid', 'on' );
l = legend( sprintf( 'v0 = %.2f, m = %.2f', v0, m ) ); set( l, 'fontsize', 12 );
endfunction