Autor Beitrag
xToast
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Fr 22.10.10 14:57 
Soa, ich hab gerade ein ziemlich komisches Problem. Wie die Überschrift bereits sagt, handelt es sich dabei darum, das eine Variable in 2 unterschiedlichen Klassen einen anderen Wert hat.

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
public class Class1
{
    public sting varible;

    public void Methode1()
    {
        //Hier ist ein openFileDialog (WinForms). Der Pfad wird in der Variable varible gespeichert und anschließend ausgegeben.
        variable = openFileDialog.FileName;
        MessageBox.Show(variable); //Hier wird der Pfad richtig ausgegeben, der Fehler liegt also in Klasse 2.
    }
}

abstract public class Class2 : Control //Bei dieser Classe handelt es sich um ein Control, in dem etwas mit XNA gerendert wird.
{
    private Class1 Class1;
    protected override void Initialize()
    {
        Allpication.Idle += delegate{ Invalidate();}; //sorgt dafür, das sich das Control regelmäßig wieder Zeichnet.
        Class1 = new Class1();
    }

    public void Methode2()
    {
        if (String.IsNullOrEmpty(Class1.variable)
        {
            MessageBox.Show("Der String hat keinen Inhalt.");
        }
        else
        {
            MessageBox.Show("Der String hat einen Inhalt.");
        }
    }

    private void Button_Click(object sender, EventArgs e) //Hier wird ein Buttonevent erstellt. Erst wenn darauf geklick wird, tritt Classe 1 in Aktion.
    {
        Class1.Methode1();
    }
}


Ich hoffe mal der Code erklärt sich, meiner ist eigentlich viel komplexer, das das ist ne Zusammenfassung.
Naja, zum eigentlich Fehler: Nachdem Methode1 ausgeführt wurde, müsste sich eig. die MessageBox "Der String hat einen Inhalt" öffnen, es öffnent sich aber weiterhin die, die sagt der String sei leer (also die if und nicht die else Klausel).

Schlussfolgerung: der String variable erhält einen Infalt, der aber nur von der Class1 Klasse wahrgenommen wird. Für Class2 ist der String immernoch null, obwohl im String bereits der Pfad der Datei gespeichert ist.

Weiß jemand woran das liegt? Ich hoffe mal ihr versteht mich :?

//Edit: Fehler im Beispiel verbessert.


Zuletzt bearbeitet von xToast am Fr 22.10.10 17:23, insgesamt 1-mal bearbeitet
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 22.10.10 15:36 
ausblenden C#-Quelltext
1:
2:
3:
        Class1 Class1 = new Class1();

        if (String.IsNullOrEmpty(Class1.variable)


Solange du zwischen diesen beiden Zeilen nichts ausführst was die variable Property ändert wird die immer leer sein. Woher soll der Inhalt bei einer neuen Class1 Instanz auch kommen wenn du Methode1 nicht aufrufst?
xToast Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Fr 22.10.10 15:46 
Ich glaube du verstehst etwas falsch^^°

Es ist mir klar, das die variable anfangs leer ist. Aber hierbei handelt es sich um eine Methode, die wieder von vorne Anfängt, sobald die Methode fertig ausgeführt wurde. Dafür sorgt die Ableitung von Control und die Unvalidate Methode in der Initialise Klasse.

Anfangs wird die variable auch leer sein, aber sie bleibt es auch nach der Ausführung von Methode1, und das ist der Fehler den ich nicht beheben kann.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 22.10.10 16:05 
ausblenden C#-Quelltext
1:
Ich glaube du verstehst etwas falsch^^°					


Ich glaube nicht :)

Du erzeugst eine Class1 Instanz innerhalb von Methode2. Die ist nur bekannt innerhalb der Methode2 nirgendwo sonst. Egal welcher Code außerhalb läuft er kann diese methodenlokale Instanz von Class1 nicht ändern(z.b dein Aufruf in Button_Click bezieht sich auf irgendeine andere Instanz von Class1 dessen Definition übrigens im Code fehlt) außer Class1 hätte statische Bestandteile die in deinem gezeigten Code aber nicht sichtbar sind.
xToast Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Fr 22.10.10 17:22 
Ja, mit der initialisierung der Class1 habe ich mich in diesem Beispiel vertan. In meinem Code, wird die Klasse erst einer Membervariable zugewiesen und dann in Initialize erstellt, was, dank XNA auch problemlos klappt.

Soweit ich deinen Post verstanden habe, meinst du, dass ich aus Class2 nicht auf Class1.Methode1 zugreifen kann, das stimmt aber nicht. Das Problem ist lediglich, das Class1 die Variable nicht richtig wahrnimmt, bzw. den Inhalt nicht. Obwohl ind der Stringvariable ein Pfad steht, wird der Pfad von Class2 nicht wahrgenommen und der string gilt als "" (nicht null!).
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 22.10.10 19:34 
So macht der Code jetzt auf jedenfall mehr Sinn. Aber um das Problem zu sehen reicht das nicht. Dafür ist der immer noch zu bruchstückhaft. Könntest du mal eins in kompilierbar zusammenstellen? Auf dem Weg wird dir das Problem wahrscheinlich schon selbst auffallen. Ich wage aber trotzdem zu raten das vermutlich immer noch mehrere Instanzen von Class1 im Spiel sind und du auf die Falsche schaust.
xToast Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Fr 22.10.10 20:11 
Ums kompilerbar wirds zu aufwändig, weil man eben eine Form, ein Control und eben noch eine Klasse braucht, aber hier ist mal mein Code, in dem der Fehler auftritt:
Achja, usingdirektievien sind auch alle vorhanden.

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
    public partial class MapEditor : Form
    {
        //Wird nicht alles verwendet in meinem geposteten Code.
        Image tilesetBitmap;
        public Texture2D texture;

        //Klassen
        Map MapClass = new Map();

        //strings
        public string FilePath;
        public string fileName;
        public string TilesetTextureName;
        public string TilesetName;
        public string fileDlg;
        public string mapDlg;

        //Pfäde
        //public string mapPath;

        public MapEditor()
        {
            InitializeComponent();
        }

        //Map öffnen Button
        private void openMapMenu(object sender, EventArgs e)
        {
            loadMap();
        }

        //Map öffnen
        private void loadMap()
        {
            //openFileDialog
            OpenFileDialog openMapDialog = new OpenFileDialog();

            //openFileDialog Filter setzen
            openMapDialog.AddExtension = true;
            openMapDialog.CheckFileExists = true;
            openMapDialog.CheckPathExists = true;
            openMapDialog.Filter = "Maps (*.png)|*.png; *.PNG";
            openMapDialog.Multiselect = false;
            openMapDialog.ValidateNames = false;
            openMapDialog.Title = "Map öffnen";

            if (openMapDialog.ShowDialog() == DialogResult.OK)
            {
                //Sanduhr Cursor
                Cursor = Cursors.WaitCursor;

                //Mappfad angeben
                MapClass.mapPath = @openMapDialog.FileName;

                if (String.IsNullOrEmpty(MapClass.mapPath) == false)
                {
                    MessageBox.Show(MapClass.mapPath, ":D", MessageBoxButtons.OK, MessageBoxIcon.Error); //Zeigt den Pfad an.
                }
            }

            //Pfeil Cursor
            Cursor = Cursors.Arrow;
        }
    }

    class Map : GraphicsDeviceControl
    {
        private SpriteBatch spriteBatch;
        ContentManager Content;
        ContentManager MapContent;

        //Klassen
        MapTiles MapInfo;
        //MapEditor MapEditor;
        NewMap NewMap;

        //Texturen
        private Texture2D black; 
        private Texture2D map;
        public Texture2D hover;

        //Tiles
        public List<Rectangle> tiles;

        //bool-Variablen
        public bool found;

        //Pfäde
        public string mapPath;

        //Stopwatch
        public Stopwatch redrawControl;

        public Map()
        {
            //Content Menager
            Content = new ContentManager(this.Services, "Content");
            MapContent = new ContentManager(this.Services, "Content");
        }

        protected override void Initialize()
        {
            //SpriteBatch laden
            spriteBatch = new SpriteBatch(GraphicsDevice);

            //Klassen initialiesiern
            // MapEditor = new MapEditor();
            MapInfo = new MapTiles();
            NewMap = new NewMap();

            //Texturen laden
            black = MapContent.Load<Texture2D>("black");
            hover = Content.Load<Texture2D>("hover");

            //Für die Stoppuhr sorgen
            redrawControl = Stopwatch.StartNew();

            //Für das wiederzeichnen sorgen
            Application.Idle += delegate { Invalidate(); };
        }

        protected override void Draw()
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            //Hier tritt der Fehler auf
            //Nach dem drücken von OK im OFD müsste der String MapEditor.mapPath eigentlich einen Wert aufweisen, was er auch tut wie man in Zeile  sieht.
            //Wenn diese Codezeile aufgerufen wird, macht der Code aber trotzdem im if-Statement weiter.
            if (String.IsNullOrEmpty(MapEditor.mapPath) == true)
            {
                if (black != null)
                {
                    //schwarzes Tile zeichnen
                    spriteBatch.Begin();
                    Rectangle pos = new Rectangle(001616);
                    spriteBatch.Draw(black, pos, Color.Black);
                    spriteBatch.End();
                }
                else
                {
                    GraphicsDevice.Clear(Color.CornflowerBlue);
                }
            }
            else
            {
                /// Test
                //Wenn es klappt Messagebox anzeigen
                MessageBox.Show(mapPath, ":D", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //alte Texturen entladen
                if (map != null)
                {
                    map = null;
                }

                if (black != null)
                {
                    black = null;
                    MapContent.Unload();
                }

                //Maptextur laden
                map = Texture2D.FromFile(GraphicsDevice, mapPath);

                if (map != null)
                {
                    //Map zeichnen
                    spriteBatch.Begin();
                    Rectangle pos = new Rectangle(00, map.Width, map.Height);
                    spriteBatch.Draw(map, pos, Color.Black);
                    spriteBatch.End();

                    //found auf true setzten
                    found = true;
                }
                else
                {
                    GraphicsDevice.Clear(Color.CornflowerBlue);
                }
            }
        }
    }


Ich hoffe mal, das reicht dann an Code und man versteht ihna auch ohne XNA Kenntnisse wenn man weis, dass Draw in regelmäßigen Abständen immerwieder aufgerufen wird. (Es sei denn, der OFD ist geöffnet, aber das ist normal und daan liegt der Fehler nicht.


Zuletzt bearbeitet von xToast am Sa 23.10.10 19:30, insgesamt 1-mal bearbeitet
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 22.10.10 21:10 
Deine MapEditor From erzeugt ein Map Object (MapClass) und Map wiederum eine neue MapEditor Form in seiner Initialize Methode. Du hast also 2 MapEditor Instanzen und die die Map kennt wird nie angezeigt und wird diese deshalb auch nie einen mapPath gesetzt bekommen.

Du könntest jetzt anfangen deine ursprüngliche MapEditor Form an Map zu übergeben das ist aber gelinde gesagt Unfug(die kennt Map übrigens schon da sie in der Parent Property des Controls steckt oder im Parent des Parents wenn du irgendwelche Panels und/oder Konsorten dazwischen liegen hast). Man stelle sich vor ein Button ginge nur auf einer ganz speziellen Form. Es sieht so aus das Map nur wegen mapPath auf MapEditor zugreifen. Dann würde ich einfach Map eine Property für mapPath verpassen und diese von MapEditor aus (in loadMap) setzen. Ansonsten sollte Map dann vergessen das MapEditor existiert.

Für diesen Beitrag haben gedankt: xToast
xToast Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Sa 23.10.10 19:33 
So, ich hab den Code oben mal abgeändert. Map kennt die MapEditor Klasse nicht mehr, und aus dieser Klasse wird die variable in der Map Klasse abgeändert.

Der Fehler ist aber immernoch der selbe.

Daran das die Map-Klasse (bzw die GraphicsDeviceControl) abstrakt ist, kann es aber nicht liegen, oder?