WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Figure 'UserData' verstehen

 

Martinuk
Forum-Century

Forum-Century


Beiträge: 208
Anmeldedatum: 18.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.03.2017, 21:45     Titel: Figure 'UserData' verstehen
  Antworten mit Zitat      
Hallo,

kann mir jemand bitte erklären weshalb im folgenden Beispiel die Daten von 'UserData' im Hauptfenster (mainFigure) von der Funktion manipuliert warden ohne das Feld 'UserData' nochmals dezidiert zu aktualisieren.

Code:

clear all, clc

hFig = figure('Tag', 'mainFigure');

data = {1 2 3; 4 5 6};
t = uitable('Data', data, ...
            'Visible', 'off');
       
pt = t.Parent;

UserData.table = t;
set(hFig, 'UserData', UserData);

figureTable
 


In einem separaten File habe ich ein Funktion definiert
Code:

function figureTable()
%UNTITLED2 Summary of this function goes here
%   Detailed explanation goes here

hFig = findobj('Tag', 'mainFigure');
userData = get(hFig, 'UserData');

firstCall = hFig.UserData.table.Parent
disp(firstCall.Tag)

userData.table.Data{1} = 99;

hFig2 = figure('Tag', 'figure2', ...
               'CloseRequestFcn', @fcnClose);
set(userData.table, 'Parent', hFig2, ...
               'Data', userData.table.Data, ...
               'Visible', 'on')
           
    function fcnClose(~,~)
        hFig = findobj('Tag', 'mainFigure');
        before_close = hFig.UserData.table.Parent
        delete(hFig2)
    end
end
 


Die Ausgabe im Kommandofenster zeigt klar, dass das 'Parent' der Tabelle überschrieben wurde obwohl ich auf die 'UserData' im Hauptfenster zugreife, warum?

Code:

firstCall =

  Figure (mainFigure) with properties:

      Number: 1
        Name: ''
       Color: [0.9400 0.9400 0.9400]
    Position: [680 558 560 420]
       Units: 'pixels'

  Show all properties

mainFigure

before_close =

  Figure (figure2) with properties:

      Number: 2
        Name: ''
       Color: [0.9400 0.9400 0.9400]
    Position: [363 487 560 420]
       Units: 'pixels'

  Show all properties
 
Private Nachricht senden Benutzer-Profile anzeigen


Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 31.03.2017, 09:24     Titel: Re: Figure 'UserData' verstehen
  Antworten mit Zitat      
Hallo Martinuk,

Ich verstehe die Frage nicht. Was ist das "Hauptfenster"? Wer manipuliert was und was ist "dediziertes Aktualisieren"?

Zitat:
Die Ausgabe im Kommandofenster zeigt klar, dass das 'Parent' der Tabelle überschrieben wurde obwohl ich auf die 'UserData' im Hauptfenster zugreife, warum?

Das lieget daran, dass set(userData.table, 'Parent', hFig2, ... den Parent der Table überschreibt. Dabei kommt es nicht darauf an, wo der Handle des Table-Objekts gespeichert ist.

Insgesamt macht De4in Code also genau was er soll und mir ist nicht klar, was daran nicht klar ist. Kannst Du die Frage nochmal genauer formulieren?

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Martinuk
Themenstarter

Forum-Century

Forum-Century


Beiträge: 208
Anmeldedatum: 18.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 31.03.2017, 14:29     Titel:
  Antworten mit Zitat      
Hallo Jan,

danke für die Antwort.

Die Info des Hauptfenster wird im Handle hFig gespeichert und ein Table erstellt. Dieser hat zunächst das Hauptfenster als Parent.
In das UserData Feld des Hauptfenster schreibe ich dann den ganzen Table. Die Idee ist es nun den Table in einer Funktion temporär ein neues Parent Figure zuzuweisen, das klappt auch alles und ist soweit verständlich für mich.
Was ich nun nicht verstehe ist, dass der Table der nach wie vor im UserData Feld des Hauptfensters vorhanden ist auch nun den manipulierten Table besitzt ohne das ich den in der Funktion geänderten Table explizit mit SET aktualisiere.
Mein Verständnis war, dass ich sozusagen immer die zuletzt gespeicherten Originaldaten vorfinde im UserData analog zu Guidatda. Dort werden die Handles auch nur aktualisiert wenn explizit der Befehl ausgeführt wird.
Wenn ich nämlich nun das Fig2 (hFig2) schließe, dann sind jetzt in meinem Fall die Daten im UserData Feld des Hauptfenster auch nicht abrufbar weil der Table den neunen Parent hatte der ja nicht mehr vorhanden ist.

Wäre cool wenn du mir das erklären kannst warum das so ist?
Private Nachricht senden Benutzer-Profile anzeigen
 
Martinuk
Themenstarter

Forum-Century

Forum-Century


Beiträge: 208
Anmeldedatum: 18.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.04.2017, 22:31     Titel:
  Antworten mit Zitat      
Kann mir niemand das erklären?
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 03.04.2017, 14:16     Titel:
  Antworten mit Zitat      
Hallo Martinuk,

Ich kann es Dir nicht erklären, weil ich nach wie vor das Problem nicht sehe.
Einerseits liegt das daran, dass ich manche Formulierungen nicht verstehe:
Zitat:
In das UserData Feld des Hauptfenster schreibe ich dann den ganzen Table.

Das als Code zu sehen wäre klarer.

Zitat:
Was ich nun nicht verstehe ist, dass der Table der nach wie vor im UserData Feld des Hauptfensters vorhanden ist auch nun den manipulierten Table besitzt ohne das ich den in der Funktion geänderten Table explizit mit SET aktualisiere.

Keine Ahnung, was das heißt.

Du hast in den UserData doch den Handle der Table gespeichert, oder?
Code:
t = uitable('Data', data, ...
            'Visible', 'off');
UserData.table = t;
set(hFig, 'UserData', UserData);

Dieser Handle ist nur eine Art Pointer auf das Table-Objekt. Wenn Du nun per: userData.table.Data; auf das Table-Objekt zugreifst, tja, dann greifst du auf das Table-Objekt zu. Das ist also keine lokal gespeicherte Kopie wie beim "handles"-Struct und guidata . Sondern Du hast hier (im Gegensatz zum dämlich gewählten Namen "handles") tatsächlich einen Handle gespeichert, so dass Du immer auf das originale Objekt zugreifst. Das ist der Sinn eines Handles.

Zitat:
Mein Verständnis war, dass ich sozusagen immer die zuletzt gespeicherten Originaldaten vorfinde im UserData analog zu Guidatda. Dort werden die Handles auch nur aktualisiert wenn explizit der Befehl ausgeführt wird.

Hier werden nicht die "Handles" aktualisiert, sondern ein Struct namens "handles". Das ist wie gesagt einen Namenswahl, die einen leicht verwirren kann. "guidata" wäre ein viel besserer Name gewesen, aber so heißt ja schon der Befehl.

Zitat:
Wenn ich nämlich nun das Fig2 (hFig2) schließe, dann sind jetzt in meinem Fall die Daten im UserData Feld des Hauptfenster auch nicht abrufbar weil der Table den neunen Parent hatte der ja nicht mehr vorhanden ist.

Das Table-Objekt wird gelöscht, wenn der Parent gelöscht wird. Der Handle existiert dann noch, zeigt aber auf ein nicht-existierendes Objekt.

Wird es jetzt klarer? Wenn nicht, frage ruhig weiter. Ein einfacheres Code-Beispiel wäre nützlich statt umständlicher Beschreibungen als Text.

Gruß, Jan

Wäre cool wenn du mir das erklären kannst warum das so ist?[/quote]
Private Nachricht senden Benutzer-Profile anzeigen
 
Martinuk
Themenstarter

Forum-Century

Forum-Century


Beiträge: 208
Anmeldedatum: 18.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 04.04.2017, 06:57     Titel:
  Antworten mit Zitat      
Hallo Jan,

danke für deine Antwort. Jetzt ist es mir die Funktionsweise schon etwas klarer. Dennoch möchte ich die Gelegenheit nutzen noch ein paar diesbezügliche Fragen zu stellen und zu deinen Anmerkungen Stellung beziehen.

Zitat:
In das UserData Feld des Hauptfenster schreibe ich dann den ganzen Table.

Als Hauptfenster verstehe ich in diesem Fallbeispiel das Figure mit dem Tag 'mainFig' dessen Handle der Variable hFig zugewiesen wird. Den zuvor definierten Table schreibe ich in ein Strukt 'userData' welches dann dem Handle-Property 'UserData' des Hauptfensters zugewiesen wird.
Code:

userData.table = t;
set(hFig, 'UserData', userData);
 


Zitat:
Was ich nun nicht verstehe ist, dass der Table der nach wie vor im UserData Feld des Hauptfensters vorhanden ist auch nun den manipulierten Table besitzt ohne das ich den in der Funktion geänderten Table explizit mit SET aktualisiere.

In der Funktion 'figureTable' greife ich in diesem Bsp. auf das hinterlegte Strukt in 'UserData' des Hauptfensters zu weise den Wert/Inhalt einer neuen Variable 'userData' zu.
Code:
userData = get(hFig, 'UserData');

Das geschieht immer sobald die Funktion aufgerufen wird. Die Idee war also immer wieder die Daten einer eigenen Variable zuzuweisen und damit die 'UserData'-Daten im Objekt von der Variable in der Funktion zu entkoppeln. Quasi wollte ich nur die neue Variable 'userData' in der Funktion manipulieren, nicht aber die 'UserData' im Objekt - in diesem Fall des Hauptfensters (mainFigure). Zu diesem Zeitpunkt war mir ja nicht bewusst das man es hier mit einer Art Pointer-Verhalten zu tun hat. Wollte immer die "Originaldaten" im Handle-Property 'UserData' belassen und die Daten nur funktionsintern für etwaige Aufgaben verwenden.

Sobald ich das 2te Figure, in dem ja nun der Table für den Benutzer sichtbar ist schließe, hätte ich einfach das 2te Figure schließen aber trotzdem noch die 'Originaldaten' (Parent für den Table wäre hier nach wie vor das 'mainFigure') des Tables zur Verfügung haben wollen.
Code:
   function fcnClose(~,~)
        before_close = hFig.UserData.table.Parent
        delete(hFig2)
    end

Mit der Zeile before_close = ... habe ich aber gesehen, dass es mit der Datenhandhabung nicht so funktioniert wie es mir erwartet habe. Hier habe ich direkt in der eingebetteten Funktion die 'UserData' des Hauptfensters (mainFigure) abgefragt und gesehen, dass sich der 'Parent' nachhaltig geändert hat obwohl ich die 'UserData' nie mit einem SET-Befehl neu definiert habe. Mit deiner Erklärung macht es aber Sinn, weil eben der Handle selbst und damit ein Pointer der auf den Inhalt der Speicheradresse zeigt in 'UserData' abgelegt ist.




Zitat:
Dieser Handle ist nur eine Art Pointer auf das Table-Objekt. Wenn Du nun per: userData.table.Data; auf das Table-Objekt zugreifst, tja, dann greifst du auf das Table-Objekt zu. Das ist also keine lokal gespeicherte Kopie wie beim "handles"-Struct und guidata . Sondern Du hast hier (im Gegensatz zum dämlich gewählten Namen "handles") tatsächlich einen Handle gespeichert, so dass Du immer auf das originale Objekt zugreifst. Das ist der Sinn eines Handles.

Erstelle ich einfach ein Figure gemäß
Code:

dann ist 'hFig' also nicht als herkömmliche Variable zu verstehen sondern vielmehr als eine Pointer-Variable welche den Wert der Adresse besitzt in dem das erstellte Objekt liegt? Bzw. zeigt der Pointer einfach auf den Adressbereich.
Mir war nicht bewusst, dass die Table-Daten auch dann manipuliert auch wenn ich diese auf eine eigene Variable schreibe.
Code:
userData = get(hFig, 'UserData');

Ich dachte, dass die innerhalb einer Funktion verwendeten Variablen nur in dem der Funktion zugewiesenen Workspace gehandhabt werden.
Aber wenn ich das 'Pointer'-Verhalten richtig verstehe, dann ist mir deine Beschreibung mit handles/guidata und die Verwirrung rund um die Namensgebung handles vollkommen klar.
Würde es sich anders Verhalten wenn ich 'UserData' als Parameter für die Funktion 'figureTable' übergebe? Dann würde MATLAB eine lokale Kopie innerhalb des Funktions-Workspace erstellen oder? Aber auch nur dann, wenn die Eingangsvariable 'inputData' geändert wird, ansonsten sieht MATLAB keine Notwendigkeit und erstellt auch keine Kopie?
Code:
function figureTable(inputData)
% Code in Funktion
end

Zitat:
Wenn ich nämlich nun das Fig2 (hFig2) schließe, dann sind jetzt in meinem Fall die Daten im UserData Feld des Hauptfenster auch nicht abrufbar weil der Table den neunen Parent hatte der ja nicht mehr vorhanden ist.


Zitat:
Das Table-Objekt wird gelöscht, wenn der Parent gelöscht wird. Der Handle existiert dann noch, zeigt aber auf ein nicht-existierendes Objekt.

Du meinst das Feld 'table' in 'UserData' existiert dann noch, nicht aber der Handle? Frag nur weil du sagst 'Der Handle existiert dann noch, zeigt aber ...'

Code:
>> hFig.UserData.table

ans =

  handle to deleted Table
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 08.04.2017, 14:30     Titel:
  Antworten mit Zitat      
Hallo Martinuk,

Zitat:
Erstelle ich einfach ein Figure gemäß
Code:

dann ist 'hFig' also nicht als herkömmliche Variable zu verstehen sondern vielmehr als eine Pointer-Variable welche den Wert der Adresse besitzt in dem das erstellte Objekt liegt?

Ja, genau. Oder besser gesagt: fast genau. Was ist denn eine "herkömmliche Variable" in Matlab? Das ist nämlich nicht trivial.
Code:
A = rand(100, 100);
B = A;

Jetzt sind A und B "herkömmliche Variablen". Beide enthalten etwas Verwaltungs-Informationen, wie z.B. die Dimensionen. Die Pointer auf die Daten weisen aber beide auf den gleichen Adressbereich im Speicher. Matlab kümmert sich darum, dass hier keine Probleme entstehen, aber wenn man den Inhalt von A in einem C-Mex-Script verändert, ist magischerweise auch B geändert worden.
Insofern sind bereits "herkömmliche Variabeln" nicht "herkömmlich". Matlab versteckt das nur vor den Usern, damit es einfach und effizient verwendet werdn kann.

Zitat:
Würde es sich anders Verhalten wenn ich 'UserData' als Parameter für die Funktion 'figureTable' übergebe?

Nein. Die UserData würden immer noch den Handle auf das table-Object enthalten.

Zitat:
Zitat:
Das Table-Objekt wird gelöscht, wenn der Parent gelöscht wird. Der Handle existiert dann noch, zeigt aber auf ein nicht-existierendes Objekt.

Du meinst das Feld 'table' in 'UserData' existiert dann noch, nicht aber der Handle? Frag nur weil du sagst 'Der Handle existiert dann noch, zeigt aber ...'

Der Handle existiert noch, aber er zeigt auf ein nicht mehr existierendes Objekt. Die Adresse eines Hauses existiert ja auch noch, wenn das Haus abgerissen wurde. Allerdings sind das schon sprachliche Spitzfindigkeiten. "Der Handle existiert nicht mehr" ist also nicht ganz korrekt, aber eigentlich ist klar, was gemeint ist.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Martinuk
Themenstarter

Forum-Century

Forum-Century


Beiträge: 208
Anmeldedatum: 18.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 11.04.2017, 23:42     Titel:
  Antworten mit Zitat      
Hallo Jan,

danke für die Beantwortung meiner Fragen. Ich denke, dass ich nun sagen kann es verstanden zu haben bis auf deine Beschreibung wie herkömmlich eine herkömmliche Variable in Matlab wirklich ist.
Mit C-Mex-Skripten habe ich keine Erfahrung, habe aber die Idee dahinter was du meinst verstanden.

Damit werde ich diesen Eintrag für mich als beantwortet betrachten. Danke nochmal...
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.