MATLAB Language
MATLAB उपयोगकर्ता इंटरफ़ेस
खोज…
यूजर इंटरफेस के आसपास डाटा पास करना
अधिकांश उन्नत उपयोगकर्ता इंटरफ़ेस के लिए उपयोगकर्ता को उन विभिन्न कार्यों के बीच जानकारी पारित करने में सक्षम होना पड़ता है जो उपयोगकर्ता इंटरफ़ेस बनाते हैं। MATLAB ऐसा करने के लिए विभिन्न तरीकों की एक संख्या है।
guidata
MATLAB का अपना GUI डेवलपमेंट एनवायरनमेंट (GUIDE) कॉलबैक के बीच डेटा पास करने के लिए एक struct
नाम के handles
का इस्तेमाल करना पसंद करता है। इस struct
में विभिन्न UI घटकों के साथ-साथ उपयोगकर्ता-निर्दिष्ट डेटा के सभी ग्राफिक्स हैंडल शामिल हैं। यदि आप एक गाइड-निर्मित कॉलबैक जो स्वचालित रूप से गुजरता है का उपयोग नहीं कर रहे हैं, तो handles
, आप का उपयोग कर मौजूदा मूल्य प्राप्त कर सकते हैं guidata
% hObject is a graphics handle to any UI component in your GUI
handles = guidata(hObject);
यदि आप इस डेटा संरचना में संग्रहीत मान को संशोधित करना चाहते हैं, तो आप संशोधित कर सकते हैं, लेकिन फिर आपको अन्य कॉलबैक द्वारा दिखाई देने वाले परिवर्तनों के लिए इसे hObject
भीतर संग्रहीत करना होगा। आप इसे एक दूसरे इनपुट तर्क के लिए guidata
करके निर्दिष्ट कर सकते हैं।
% Update the value
handles.myValue = 2;
% Save changes
guidata(hObject, handles)
hObject
का मान hObject
मायने नहीं रखता है जब तक वह एक ही figure
भीतर UI घटक है क्योंकि अंततः डेटा को hObject
वाले आंकड़े में संग्रहीत किया जाता है।
के लिए सबसे अच्छा:
-
handles
संरचना को संग्रहीत करना, जिसमें आप अपने जीयूआई घटकों के सभी हैंडल स्टोर कर सकते हैं। - "छोटे" अन्य चर को संग्रहीत करना, जिन्हें अधिकांश कॉलबैक द्वारा एक्सेस करने की आवश्यकता होती है।
इसके लिए अनुशंसित नहीं :
- बड़े चर संग्रहीत करना जो सभी कॉलबैक और उप-कार्यों (इन के लिए
setappdata
/getappdata
उपयोग करना) तकgetappdata
।
setappdata
/ getappdata
guidata
दृष्टिकोण के समान, आप ग्राफिक्स हैंडल के भीतर से मानों को संग्रहीत करने और पुनः प्राप्त करने के लिए setappdata
और getappdata
का उपयोग कर सकते हैं। इन विधियों का उपयोग करने का लाभ यह है कि आप सभी संग्रहीत डेटा वाले संपूर्ण struct
बजाय केवल वही मान प्राप्त कर सकते हैं जो आप चाहते हैं । यह एक कुंजी / मूल्य स्टोर के समान है।
एक ग्राफिक्स ऑब्जेक्ट के भीतर डेटा को स्टोर करने के लिए
% Create some data you would like to store
myvalue = 2
% Store it using the key 'mykey'
setappdata(hObject, 'mykey', myvalue)
और एक अलग कॉलबैक के भीतर से उसी मूल्य को पुनः प्राप्त करने के लिए
value = getappdata(hObject, 'mykey');
नोट: यदि कोई मूल्य getappdata
को कॉल करने से पहले संग्रहीत नहीं किया गया था, तो यह एक खाली सरणी ( []
) वापस कर देगा।
guidata
समान, डेटा उस आंकड़े में संग्रहीत होता है जिसमें hObject
होता है।
के लिए सबसे अच्छा:
- बड़े चर संग्रहीत करना, जिन्हें सभी कॉलबैक और उप-कार्यों द्वारा एक्सेस नहीं करना पड़ता है।
UserData
हर ग्राफिक्स के हैंडल में एक विशेष गुण होता है, UserData
जिसमें कोई भी डेटा हो सकता है जिसे आप चाहते हैं। इसमें एक सेल ऐरे, एक struct
या एक स्केलर हो सकता है। आप इस संपत्ति का लाभ उठा सकते हैं और इस क्षेत्र में दिए गए ग्राफिक्स हैंडल से जुड़े किसी भी डेटा को स्टोर कर सकते हैं। यदि आप R2014b या नए का उपयोग कर रहे हैं, तो आप ग्राफिक्स ऑब्जेक्ट या डॉट नोटेशन के लिए मानक get
/ set
विधियों का उपयोग करके मूल्य को बचा सकते हैं और प्राप्त कर सकते हैं।
% Create some data to store
mydata = {1, 2, 3};
% Store it within the UserData property
set(hObject, 'UserData', mydata)
% Of if you're using R2014b or newer:
% hObject.UserData = mydata;
फिर एक अन्य कॉलबैक से, आप इस डेटा को पुनः प्राप्त कर सकते हैं:
their_data = get(hObject, 'UserData');
% Or if you're using R2014b or newer:
% their_data = hObject.UserData;
के लिए सबसे अच्छा:
- एक सीमित दायरे के साथ चर को संग्रहीत करना (चर जो केवल उस वस्तु द्वारा उपयोग किए जाने की संभावना है जिसमें वे संग्रहीत होते हैं, या वस्तुओं का इसका सीधा संबंध होता है)।
नेस्टेड कार्य
MATLAB में, एक नेस्टेड फ़ंक्शन मूल फ़ंक्शन में परिभाषित किसी भी चर को पढ़ और संशोधित कर सकता है। इस तरह, यदि आप कॉलबैक को नेस्टेड फ़ंक्शन के रूप में निर्दिष्ट करते हैं, तो यह मुख्य फ़ंक्शन में संग्रहीत किसी भी डेटा को पुनः प्राप्त और संशोधित कर सकता है।
function mygui()
hButton = uicontrol('String', 'Click Me', 'Callback', @callback);
% Create a counter to keep track of the number of times the button is clicked
nClicks = 0;
% Callback function is nested and can therefore read and modify nClicks
function callback(source, event)
% Increment the number of clicks
nClicks = nClicks + 1;
% Print the number of clicks so far
fprintf('Number of clicks: %d\n', nClicks);
end
end
के लिए सबसे अच्छा:
- छोटे, सरल GUIs। (त्वरित प्रोटोटाइप के लिए,
guidata
और / याset/getappdata
विधियों को लागू नहीं करना है)।
इसके लिए अनुशंसित नहीं :
मध्यम, बड़े या जटिल जीयूआई।
GUI
GUIDE
के साथ बनाया गया।
स्पष्ट इनपुट तर्क
यदि आपको कॉलबैक फ़ंक्शन में डेटा भेजने की आवश्यकता है और कॉलबैक के भीतर डेटा को संशोधित करने की आवश्यकता नहीं है, तो आप हमेशा सावधानीपूर्वक तैयार की गई कॉलबैक परिभाषा का उपयोग करके कॉलबैक में डेटा पास करने पर विचार कर सकते हैं।
आप एक अनाम फ़ंक्शन का उपयोग कर सकते हैं जो इनपुट जोड़ता है
% Create some data to send to mycallback
data = [1, 2, 3];
% Pass data as a third input to mycallback
set(hObject, 'Callback', @(source, event)mycallback(source, event, data))
या आप कॉलबैक निर्दिष्ट करने के लिए सेल सरणी सिंटैक्स का उपयोग कर सकते हैं, फिर से अतिरिक्त इनपुट निर्दिष्ट कर सकते हैं।
set(hObject, 'Callback', {@mycallback, data})
के लिए सबसे अच्छा:
- जब कॉलबैक को कुछ ऑपरेशन करने के लिए
data
आवश्यकता होती है, लेकिनdata
चर को नए राज्य में संशोधित और सहेजने की आवश्यकता नहीं होती है।
अपने यूआई में एक बटन बनाना जो कॉलबैक निष्पादन को रोक देता है
कभी-कभी हम एप्लिकेशन की स्थिति का निरीक्षण करने के लिए कोड निष्पादन को रोकना चाहते हैं ( डीबगिंग देखें)। MATLAB संपादक के माध्यम से कोड चलाते समय, यह यूआई में "पॉज़" बटन का उपयोग करके या Ctrl + c (विंडोज पर) दबाकर किया जा सकता है। हालांकि, जब जीयूआई (कुछ uicontrol
के कॉलबैक के माध्यम से) से गणना शुरू की गई थी, तो यह विधि अब काम नहीं करती है, और कॉलबैक को एक अन्य कॉलबैक के माध्यम से बाधित किया जाना चाहिए। नीचे इस सिद्धांत का प्रदर्शन है:
function interruptibleUI
dbclear in interruptibleUI % reset breakpoints in this file
figure('Position',[400,500,329,160]);
uicontrol('Style', 'pushbutton',...
'String', 'Compute',...
'Position', [24 55 131 63],...
'Callback', @longComputation,...
'Interruptible','on'); % 'on' by default anyway
uicontrol('Style', 'pushbutton',...
'String', 'Pause #1',...
'Position', [180 87 131 63],...
'Callback', @interrupt1);
uicontrol('Style', 'pushbutton',...
'String', 'Pause #2',...
'Position', [180 12 131 63],...
'Callback', @interrupt2);
end
function longComputation(src,event)
superSecretVar = rand(1);
pause(15);
print('done!'); % we'll use this to determine if code kept running "in the background".
end
function interrupt1(src,event) % depending on where you want to stop
dbstop in interruptibleUI at 27 % will stop after print('done!');
dbstop in interruptibleUI at 32 % will stop after **this** line.
end
function interrupt2(src,event) % method 2
keyboard;
dbup; % this will need to be executed manually once the code stops on the previous line.
end
यह सुनिश्चित करने के लिए कि आप इस उदाहरण को निम्न करते हैं:
- उपर्युक्त कोड को एक नई फ़ाइल में पेस्ट करें और इसे
interruptibleUI.m
रूप में सहेजें, जैसे कि कोड फ़ाइल की पहली पंक्ति पर शुरू होता है (यह काम करने के लिए 1 विधि के लिए महत्वपूर्ण है)। - स्क्रिप्ट चलाएँ।
- गणना पर क्लिक करें और कुछ ही समय बाद # 1 रोकें या # 2 रोकें पर क्लिक करें।
- सुनिश्चित करें कि आप
superSecretVar
का मूल्य पा सकते हैं।
"हैंडल" संरचना का उपयोग करके डेटा पास करना
यह दो बटन वाले मूल GUI का एक उदाहरण है जो GUI के handles
संरचना में संग्रहीत मान को बदलता है।
function gui_passing_data()
% A basic GUI with two buttons to show a simple use of the 'handles'
% structure in GUI building
% Create a new figure.
f = figure();
% Retrieve the handles structure
handles = guidata(f);
% Store the figure handle
handles.figure = f;
% Create an edit box and two buttons (plus and minus),
% and store their handles for future use
handles.hedit = uicontrol('Style','edit','Position',[10,200,60,20] , 'Enable', 'Inactive');
handles.hbutton_plus = uicontrol('Style','pushbutton','String','+',...
'Position',[80,200,60,20] , 'Callback' , @ButtonPress);
handles.hbutton_minus = uicontrol('Style','pushbutton','String','-',...
'Position',[150,200,60,20] , 'Callback' , @ButtonPress);
% Define an initial value, store it in the handles structure and show
% it in the Edit box
handles.value = 1;
set(handles.hedit , 'String' , num2str(handles.value))
% Store handles
guidata(f, handles);
function ButtonPress(hObject, eventdata)
% A button was pressed
% Retrieve the handles
handles = guidata(hObject);
% Determine which button was pressed; hObject is the calling object
switch(get(hObject , 'String'))
case '+'
% Add 1 to the value
handles.value = handles.value + 1;
set(handles.hedit , 'String', num2str(handles.value))
case '-'
% Substract 1 from the value
handles.value = handles.value - 1;
end
% Display the new value
set(handles.hedit , 'String', num2str(handles.value))
% Store handles
guidata(hObject, handles);
उदाहरण का परीक्षण करने के लिए, इसे gui_passing_data.m
नामक फ़ाइल में gui_passing_data.m
और F5 के साथ लॉन्च करें। कृपया ध्यान दें कि इस तरह के एक सरल मामले में, आपको हैंडल संरचना में मूल्य को संग्रहीत करने की भी आवश्यकता नहीं होगी, क्योंकि आप इसे सीधे संपादित बॉक्स की String
संपत्ति से एक्सेस कर सकते हैं।
उपयोगकर्ता इंटरफ़ेस के आसपास डेटा पास करते समय प्रदर्शन समस्याएँ
दो मुख्य तकनीकें जीयूआई फ़ंक्शन और कॉलबैक के बीच डेटा पास करने की अनुमति देती हैं: सेटपडेटा / गेटपडेटा और गाइडटा ( अधिक जानकारी पढ़ें )। पूर्व का उपयोग बड़े चर के लिए किया जाना चाहिए क्योंकि यह अधिक समय कुशल है। निम्न उदाहरण दो तरीकों की दक्षता का परीक्षण करता है।
एक साधारण बटन के साथ एक GUI बनाया गया है और एक बड़ा चर (10000x10000 डबल) गाइडटाटा और सेटपडेटा दोनों के साथ संग्रहीत किया गया है। बटन अपने निष्पादन के समय दो तरीकों का उपयोग करके चर को फिर से लोड और संग्रहीत करता है। सेटपैडटा का उपयोग करके चलने का समय और प्रतिशत सुधार कमांड विंडो में प्रदर्शित होते हैं।
function gui_passing_data_performance()
% A basic GUI with a button to show performance difference between
% guidata and setappdata
% Create a new figure.
f = figure('Units' , 'normalized');
% Retrieve the handles structure
handles = guidata(f);
% Store the figure handle
handles.figure = f;
handles.hbutton = uicontrol('Style','pushbutton','String','Calculate','units','normalized',...
'Position',[0.4 , 0.45 , 0.2 , 0.1] , 'Callback' , @ButtonPress);
% Create an uninteresting large array
data = zeros(10000);
% Store it in appdata
setappdata(handles.figure , 'data' , data);
% Store it in handles
handles.data = data;
% Save handles
guidata(f, handles);
function ButtonPress(hObject, eventdata)
% Calculate the time difference when using guidata and appdata
t_handles = timeit(@use_handles);
t_appdata = timeit(@use_appdata);
% Absolute and percentage difference
t_diff = t_handles - t_appdata;
t_perc = round(t_diff / t_handles * 100);
disp(['Difference: ' num2str(t_diff) ' ms / ' num2str(t_perc) ' %'])
function use_appdata()
% Retrieve the data from appdata
data = getappdata(gcf , 'data');
% Do something with data %
% Store the value again
setappdata(gcf , 'data' , data);
function use_handles()
% Retrieve the data from handles
handles = guidata(gcf);
data = handles.data;
% Do something with data %
% Store it back in the handles
handles.data = data;
guidata(gcf, handles);
मेरे Xeon [email protected] GHz पर मुझे Difference: 0.00018957 ms / 73 %
मिलता है Difference: 0.00018957 ms / 73 %
, इस प्रकार गेटप्पाटा / सेटपडेटा का उपयोग करके मुझे 73% का प्रदर्शन सुधार मिलता है! ध्यान दें कि यदि 10x10 डबल चर का उपयोग किया जाता है तो परिणाम नहीं बदलता है, हालांकि, यदि बड़े डेटा वाले कई फ़ील्ड्स handles
होते हैं, तो परिणाम बदल जाएगा।