Globale Variablen in einer Funktion werden nicht erkannt?

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

M0rgenstern

Betreff: Globale Variablen in einer Funktion werden nicht erkannt?

BeitragDi, Aug 10, 2010 8:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Leute.

Ich hab ein kleines Problem bei BMax.
Undzwar: Ich bin gerade dabei einen TileMapEditor zu schreiben und nutze dafür meine GUI.
Ich will jetzt aber nicht vor der Hauptschleife tausende Buttons deklarieren. Das sieht unschön aus finde ich. Deshalb hab ich einfach ne Funktion geschrieben, in die ich das packe und die einfach hinter der Hauptschleife steht. Die Funktion wird dann vor der Hauptschleife aufgerufen. Das Problem: Wenn ich das so mache, und dann einzelne Buttons überprüfen will (ob sie angeklickt wurden), dann erkennt er die dazugehörige Variable nicht.
Ich bekomme dann an entsprechender Stelle (da wo ich die Buttonvariable an eine entsprechende Funktion überge) die Meldung Identifier "Variable" not found.
Wenn ich die FUnktion auskommentiere und den unschönen weg nehme, also alles vor die Hautpschleife setze, dann funktioniert es super. Variablen sind auch alle global.

Jetzt meine Frage: Warum funktioniert das nicht? Werden Variablen, die in einer Funktion global deklariert werden im Hauptprogramm nicht als global erkannt?

Hier noch der Code der Funktion:

BlitzMax: [AUSKLAPPEN]
Function InitGui()
Global MainEditWindow:TGuiElement = TGuielement.CreateWindow()
Global MainBottomLabel:TGuiElement = TGuielement.CreateLabel(MainEditWindow, 1)
Global TileEditLabel:TGuiElement = TGuielement.CreateLabel(MainEditWindow, 1)

'(pMask:TMask, psName:String, piXPos:Int, piYPos:Int, piWidth:Int = iBUTTONWIDTH, piHeight:Int = iBUTTONHEIGHT, piEnabled:Int = 1)
'Buttons zu MainBottomLabel:
Global MainLoadMapButton:TGuiElement = TGuielement.CreateButton(MainBottomLabel, "Map Laden", 350, fgfxheight - 125)
Global MainSaveMapButton:TGuiElement = TGuielement.CreateButton(mainBottomLabel, "Map Speichern", 350, fgfxheight - 50)
Global MainSelectLayer1Button:TGuiElement = TGuielement.CreateButton(mainbottomlabel, "Layer1", 500, fgfxheight - 90)
Global MainSelectLayer2Button:TGuiElement = TGuielement.CreateButton(mainbottomlabel, "Layer2", 630, fgfxheight - 90)
Global MainSelectLayer3Button:TGuiElement = TGuielement.CreateButton(mainbottomlabel, "Layer3", 760, fgfxheight - 90)
Global MainNewMapButton:TGuiElement = TGuielement.CreateButton(mainbottomlabel, "Neue Map", 890, fgfxheight - 90)

'Buttons zu TileEditLabel:
Global TilePreviousTileButton:TGuiElement = TGuielement.CreateButton(TileEditLabel, "Vorheriges Tile", 100, fgfxheighthalf + 40)
Global TileNextTileButton:TGuielement = TGuielement.CreateButton(TileEditLabel, "Naechstes Tile", 100, fgfxheighthalf + 160)

SetActiveWindow(MainEditWindow)
End Function


Wäre super, wenn jemand was wüsste.

Lg, M0rgenstern

BladeRunner

Moderator

BeitragDi, Aug 10, 2010 9:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Die globale Deklaration bezieht sich in diesem Fall auf die Funktion, d.h. die Variablen bleiben zwischen zwei Funktionsaufrufen erhalten, sind ausserhalb jedoch nicht verfügbar.
Du könntest das ganze in einem Type speichern und die einzelnen Typevariablen ansprechen. Schöne Programmierung wäre dennoch anders.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

M0rgenstern

BeitragDi, Aug 10, 2010 10:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie meinst du das mit in einem Type abspeichern?
Die stecken ja schon in nem Type (TGuiElement).

Wie wäre denn schöne Programmierung?

Lg, M0rgenstern

BladeRunner

Moderator

BeitragDi, Aug 10, 2010 12:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich meinte sowas:
Code: [AUSKLAPPEN]
type TMyAppGui
    field menubutton:tGuiElement
    field nochnbutton:Tguielement

    method new()
        menubutton = TGuiElement.Create(bla,blub)
        nochnbutton = TGuiElement.Create(foo,bar)
    end method
end type
global MAG:TMyAppGui = new TMyAppGUI
if MAG.menubutton.check() = ....
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

M0rgenstern

BeitragDi, Aug 10, 2010 14:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Achso... Naja, das wär ja relativ unschön. Dann müsste man tausende Felder haben^^

Dann kommt halt alles vor die Hauptschleife.

Lg, M0rgenstern

Holzchopf

Meisterpacker

BeitragDi, Aug 10, 2010 14:49
Antworten mit Zitat
Benutzer-Profile anzeigen
M0rgenstern hat Folgendes geschrieben:
Naja, das wär ja relativ unschön. Dann müsste man tausende Felder haben

Genauso wird's aber i.d.R. bei OOP gemacht.

Ich persönlich finde die Variante mit den Deklarationen vor der Hauptschleife um einiges unschöner. Das ist evtl. Geschmackssache, vielleicht auch nicht, hängt aber u.U. auch damit zusammen, wie lange man mit BMax programmiert (oder auch nicht) und wahrscheinlich (muss aber nicht sein) auch damit, wie ausgiebig man die OOP-Fähigkeiten BMax' in Gebrauch nimmt.

Respektive: Mag zwar verschiedene Geschmäcker geben, aber es ist definitiv OOP-Standard Wink

mfG
Holzchopf
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

M0rgenstern

BeitragDi, Aug 10, 2010 14:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Es kann doch nicht OOP Standard sein, dass man einen Type erstellt, der ein Field für JEDEN Button hat.
Bzw, das kann schon sein, aber kommt mich... seltsam vor.

Lg, M0rgenstern
 

n-Halbleiter

BeitragMi, Aug 11, 2010 0:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Wieso soll es nicht OOP-Standard sein? In einigen Aspekten von OOP hantiert man mit Dingen, die erstmal komisch wirken. Wink

Man gewöhnt sich schnell daran, dass man das so schreibt. Die Vorteile sind die Kapselung und Wiederverwendbarkeit, wie man sie mit OOP ja erreichen möchte. Du hast deine GUI gekapselt und kannst sie so unabhängig von deinen Algorithmen verwenden. Wenn du später eine andere GUI nutzen möchtest (wxMax oder auch MaxGUI), dann kannst du (im Prinzip) das Interface (die Methoden/Funktionen, mit denen deine Algorithmen mit der GUI kommunizieren) gleich bleiben lassen (also die Handhabung der Funktionen/Methoden) und einfach den Inhalt auf die neue GUI anpassen.

Mal nebenbei: Hast du mal mit Delphi gearbeitet?
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit
Ploing!
Blog

"Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935)

M0rgenstern

BeitragMi, Aug 11, 2010 1:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, mit Delphi arbeiten wir in der SChule, warum?

Wenn man so über diese Lösung nachdenkt, dann ist sie doch flexibler... Werd mal schauen ob ich das umschreibe.

Lg, M0rgenstern.
Vielen Dank.

BladeRunner

Moderator

BeitragMi, Aug 11, 2010 9:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Was ich mit schönem Code meinte wäre der Ansatz den Type sich selbst verwalten zu lassen, d.h. in einer internen Liste alle Gadgets zu führen und diese dann eventbasiert reagieren zu lassen. Vieles lässt sich mit intelligentem Design lösen. Der Type als solches wäre wie schon erwähnt die klassische Datenkapselung der OOP.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

M0rgenstern

BeitragMi, Aug 11, 2010 9:50
Antworten mit Zitat
Benutzer-Profile anzeigen
@ Bladerunner: Wenn die Types sich selbst verwalten, dann würde das ganze ja über Funktionspointer laufen, oder?
Da muss ich ehrlich sagen, da hab ich mich nicht rangetraut.


Lg, M0rgenstern
 

n-Halbleiter

BeitragMi, Aug 11, 2010 12:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Funktionspointer sind an sich ganz einfach. Hier ein einfaches Beispiel:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Local Func:Object(Str:String)'Das hier ist die Deklaration vom Funktionspointer.
Local Func2:String(l:Int)
'Rückgabetyp und Parameter müssen benannt werden, die Namen der Parameter sind jedoch an sich egal

Function MyFunc:Object(rgch:String)'Das ist die Funktion. Für diesen Fall gibt sie einfach den String +"!" zurück
Return rgch+"!"
End Function

Function MyFunc2:String(i:Int)
If i>0
Return String(i)+MyFunc2(i-1)
Else
Return String(i)
End If
End Function

Func=MyFunc'Wichtig: Ohne Klammern. Die Funktion wird hier wie eine ganz normale Variable behandelt.
Func2=MyFunc2

Print String(Func("Hallo"))'Und der Aufruf. Der Pointer mit Klammern und Argumenten wird wie die Ursprungsfunktion behandelt.

For Local i:Int=0 Until 10
Print String(Func2(i))
Next


Ich hoffe, damit leuchtet dir das ein. Zu beachten sind an sich ja drei Dinge:
1.: Bei der Deklaration müssen Rückgabetyp und die Parametertypen bekannt sein.
2.: Bei der Zuweisung arbeitet man wie mit Variablen.
3.: Der Pointer kann später dann ganz einfach wie eine Funktion behandelt werden.

Viel Spaß in dieser wundersamen Welt. Wink
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit
Ploing!
Blog

"Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935)

M0rgenstern

BeitragMi, Aug 11, 2010 15:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Hm
Also, ich glaube, ich fange an das zu verstehen. Aber ganz bin ich noch nicht durchgestiegen.

Mal am Beispiel eines Types:

BlitzMax: [AUSKLAPPEN]
Type TButton
Field iXPos:Int, iYPos:Int
Field Func:Object(Para1:Object=Null,Para2:Object=Null,Para3:Object=Null,Para4:Object=Null)

End Type


Und wenn ich dann die Funktion zuweisen will, dann muss ich diese aber außerhalb des Types schreiben, also:

BlitzMax: [AUSKLAPPEN]
Function FileExists:Int(TStream(MeineDatei))
If FileType(meineDatei)=1 Then
Return True
Else
Return False
EndIf
End Function

'Und dann zum zuweisen:

Local MyButton:TButton = TButton.Create(20,20) 'Button erstellen
MyButton.Func = FileExists


Hab ich das richtig verstanden?

Lg, M0rgenstern

Xeres

Moderator

BeitragMi, Aug 11, 2010 15:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Was hindert dich dran, die Funktion in der Create-Funktion zu zu weisen?
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

M0rgenstern

BeitragMi, Aug 11, 2010 15:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Nichts, das war nur um das ganze zu verdeutlichen.

Wollte ja nur wissen, ob das richtig so ist.
Dazu noch eine Frage:

Wenn ich das ganze so schreibe:
BlitzMax: [AUSKLAPPEN]
Function FileExists:Int(TStream(MeineDatei))


Dann muss ich "MeineDatei" ja nicht mehr in der Funktion selbst Casten, oder?

Lg, M0rgenstern

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group