Klitzekleine GUI

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

M0rgenstern

Betreff: Klitzekleine GUI

BeitragMo, Aug 09, 2010 13:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab mich endlich mal an eine GUI gesetzt, da ich gemerkt habe dass sowas auf Dauer doch praktischer ist.
Das ganze war dann jetzt im Endeffekt keine Hexerei und es ist auch nichts großartiges, aber vielleicht werden sich ja einige Neulinge drüber freuen.
Ich schieb noch nen type zum verwalten von Bildern hinterher, alleinschon weil er in der GUI gebraucht wird.

Die GUI beinhaltet: Windows (keine eigenständigen Fenster, sondern nur Gruppenverbände)
Labels. Das sind einfach größere Flächen die Buttons beinhalten. So kann man unterschiedliche Flächen bequem ein und ausblenden. Natürlich Buttons. Und Textfelder zur Texteingabe. Wie das mit der Texteingabe funktioniert ist unten im Beispiel zu sehen.

Also, erstmal, hier der BIldertype:

BlitzMax: [AUSKLAPPEN]
Type TMyIMage
Global tlAllMyImages:TList = New TList
Field tiimage:TImage
Field iMaxFrames:Int
Field iFrame:Int
Field iTimer:Int, iLastFrameUpDate:Int

Function Create:TMyImage(pImage:TImage, pMaxFrames:Int = 0, PTimer:Int = 0)
Local MyIMage:TMyImage = New TMyImage
MyIMage.tiimage = pImage
MyIMage.iMaxFrames = pMaxFrames
MyIMage.iTimer = PTimer
MyIMage.iFrame = 0
MyIMage.iLastFrameUpDate = MilliSecs()
Return Myimage
End Function

Method Animate()
If iMaxFrames <> 0 Then
If ((iTimer + iLastFrameUpDate) < MilliSecs()) Then
iFrame = (iFrame + 1) Mod iMaxFrames
iLastFrameUpDate = MilliSecs()
EndIf
End If
End Method

Method AnimateManual()
If iMaxFrames <> 0 Then
iFrame = (iFrame + 1) Mod iMaxFrames
End If
End Method

Method New()
tlAllMyImages.AddLast(Self)
End Method

Method Destroy()
tlAllMyImages.Remove(Self)
End Method
End Type


Und hier das ganze GUI Gedöhns:

BlitzMax: [AUSKLAPPEN]
Global CurrentWindow:TGuiElement
Global SelectedTextField:TGuiElement

Const iGUITYPE_WINDOW:Int = 1
Const iGUITYPE_LABEL:Int = 2
Const iGUITYPE_BUTTON:Int = 3
Const iGUITYPE_TEXTFIELD:Int = 4

Const iBUTTONWIDTH:Int = 128
Const iBUTTONHEIGHT:Int = 64

Const iMAX_LABELS_PER_WINDOW:Int = 5
Const iMAX_BUTTONS_PER_LABEL:Int = 10

AutoMidHandle(1)

Global tiButton:TImage = LoadAnimImage("Data/gfx/GUI/ButtonComplete.png", 128, 64, 0, 2)
Global tifGUIFont:TImageFont = LoadImageFont("Data/gfx/GUI/chintzy.ttf", 17, SMOOTHFONT)
Global tiTextField:TImage = LoadImage("Data/gfx/GUI/InBox.png")

Type TGuiElement
Global tlAllGuiElements:TList = New TList

Field Owner:TGuiElement
Field aChildren:TGuiElement[]
Field iType:Int
Field sName:String
Field iXPos:Int, iYPos:Int
Field iWidth:Int, iHeight:Int
Field iEnabled:Int
Field iVisible:Int = 1
Field tmImage:TmyImage
Field iClicked:Int
Field iClickedLast:Int
Field iIsOn:Int, iIsOnLast:Int
'Nur Textfelder:
Field iLastBlink:Int, iBlinkTime:Int
Field iBlink:Int
Field sInput:String

Function CreateWindow:TGuiElement()
Local Window:TGuiElement = New TGuiElement
Window.Owner = Null
Window.iType = iGUITYPE_WINDOW
Window.aChildren = New TGuiElement[iMAX_LABELS_PER_WINDOW]
For Local index:Int = 0 To (iMAX_LABELS_PER_WINDOW - 1)
Window.aChildren[index] = Null
Next
Return Window
End Function

Function CreateLabel:TGuiElement(pWindowOwner:TGuiElement, penabled:Int = 1)
Local Label:TGuiElement = New TGuiElement
Label.Owner = pWindowOwner
InsertInWindow(Label, pWindowOwner)
Label.iType = iGUITYPE_LABEL
Label.iEnabled = penabled
Label.aChildren = New TGuiElement[iMAX_BUTTONS_PER_LABEL]
For Local index:Int = 0 To (iMAX_BUTTONS_PER_LABEL - 1)
Label.aChildren[index] = Null
Next
Return Label
End Function

Function CreateButton:TGuiElement(pLabelOwner:TGuiElement, psName:String, piXPos:Int, piYPos:Int, piWidth:Int = iBUTTONWIDTH, piHeight:Int = iBUTTONHEIGHT, piEnabled:Int = 1)
Local Button:TGuiElement = New TGuiElement
Button.Owner = pLabelOwner
Button.iType = iGUITYPE_BUTTON
InsertInLabel(Button, pLabelOwner)
Button.sName = psName
Button.iXPos = piXPos
Button.iYPos = piYPos
Button.iWidth = piWidth
Button.iHeight = piHeight
Button.iEnabled = piEnabled
Button.tmImage = TMyIMage.Create(tiButton, 2)
Return Button
End Function

Function CreateTextField:TGuiElement(pLabelOwner:TGuiElement, psName:String, piXPos:Int, piYPos:Int, piWidth:Int = iBUTTONWIDTH, piHeight:Int = iBUTTONHEIGHT, piEnabled:Int = 1)
Local TextField:TGuiElement = New TGuiElement
TextField.Owner = pLabelOwner
TextField.iType = iGUITYPE_TEXTFIELD
InsertInLabel(TextField, pLabelOwner)
TextField.iXPos = piXPos
TextField.iYPos = piYPos
TextField.iWidth = piWidth
TextField.iHeight = piHeight
TextField.iEnabled = piEnabled
TextField.iBlinkTime = 500
TextField.iBlink = 1
TextField.iLastBlink = MilliSecs()
TextField.tmImage = TMyIMage.Create(tiTextField)
TextField.sName = psName
Return TextField
End Function

Function InsertInWindow(pLabel:TGUIElement, pWindow:TGuiElement)
For Local iIndex:Int = 0 To (iMAX_LABELS_PER_WINDOW - 1)
If (pwindow.aChildren[iIndex] = Null) Then
pwindow.aChildren[iIndex] = plabel
Return
EndIf
Next
End Function

Function InsertInLabel(pButton:TGUIElement, pLabel:TGuiElement)
For Local iIndex:Int = 0 To (iMAX_BUTTONS_PER_LABEL - 1)
If (pLabel.aChildren[iIndex] = Null) Then
pLabel.aChildren[iIndex] = pButton
Return
EndIf
Next
End Function

Function GuiElementClicked:Int(pGuiElement:TGuiElement)
Return pGuielement.iclicked
End Function

Method New()
tlAllGuiElements.AddLast(Self)
End Method

End Type

Function SetActiveWindow(pWindow:TGuiElement)
If pWindow.iType = iGUITYPE_WINDOW Then
CurrentWindow = pWindow
EndIf
End Function

Function UpdateGUI(piMousehit:Int, pfMouseX:Int, pfMouseY:Int)
For Local GuiElement:TGuiElement = EachIn TGuiElement.tlallGuiElements
Select guielement.iType
Case iGUITYPE_LABEL
If GuiElement.ienabled And GUIElement.iVisible And (GUIElement.Owner = CurrentWindow) Then
GuiElement.iClickedLast = GuiElement.iclicked
guielement.iisonlast = guielement.iison
GuiElement.iClicked = (RectMouseCollision(pfmousex, pfmousey, GUIElement.iXPos, GUIElement.iYPos, GUIElement.iWidth, GUIElement.iHeight) And piMouseHit)
guielement.iison = RectMouseCollision(pfmousex, pfmousey, GUIElement.iXPos, GUIElement.iYPos, GUIElement.iWidth, GUIElement.iHeight)
Else
GuiElement.iClicked = 0
EndIf
Case iGUITYPE_BUTTON
If GuiElement.ienabled And GuiElement.iVisible And (GuiElement.Owner.owner = CurrentWindow) Then
If GuiElement.Owner.iEnabled Then
GuiElement.iClickedLast = GuiElement.iclicked
guielement.iisonlast = guielement.iison
GuiElement.iClicked = (RectMouseCollision(pfmousex, pfmousey, GUIElement.iXPos, GUIElement.iYPos, GUIElement.iWidth, GUIElement.iHeight) And piMouseHit)
GuiElement.iison = RectMouseCollision(pfMouseX, pfMouseY, GuiElement.iXPos, GuiElement.iYPos, GuiElement.iWidth, GuiElement.iHeight)

Else
GuiElement.iClicked = 0
EndIf
EndIf
Case iGUITYPE_TEXTFIELD
If GuiElement.ienabled And GuiElement.iVisible And (GuiElement.Owner.owner = CurrentWindow) Then
If GuiElement.Owner.iEnabled Then
guiElement.iClickedLast = GuiElement.iclicked
guielement.iisonlast = guielement.iison
GuiElement.iClicked = (RectMouseCollision(pfmousex, pfmousey, GUIElement.iXPos, GUIElement.iYPos, GUIElement.iWidth, GUIElement.iHeight) And piMouseHit)
GuiElement.iison = RectMouseCollision(pfMouseX, pfMouseY, GuiElement.iXPos, GuiElement.iYPos, GuiElement.iWidth, GuiElement.iHeight)
Else
GuiElement.iClicked = 0
EndIf
EndIf
End Select
Next
End Function

Function RenderGui()
For Local GuiElement:TGuielement = EachIn TGuiElement.tlAllGuiElements

Select GuiElement.iType

Case iGUITYPE_BUTTON
If GuiElement.iVisible And (GuiElement.Owner.owner = CurrentWindow) Then
If GuiElement.Owner.iEnabled Then
'If guielement.iclicked <> guielement.iclickedlast Then guielement.tmimage.animateManual()
If GuiElement.iison <> GuiElement.iisonlast Then GuiElement.tmimage.animateManual()
Local ImageFont:TimageFont = GetImageFont()
SetImageFont(tifGuiFont)
SetScale(Float(GuiElement.iwidth) / Float(ImageWidth(GuiElement.tmimage.tiimage)), Float(GuiElement.iheight) / Float(ImageHeight(GuiElement.tmimage.tiimage)))
DrawImage(GuiElement.tmimage.tiimage, GuiElement.iXPos, GuiElement.iYPos, GuiElement.tmimage.iframe)
SetColor(20, 20, 20)
DrawText(GuiElement.sName, GuiElement.iXPos - TextWidth(GuiElement.sname) / 2, GuiElement.iYPos - TextHeight(GuiElement.sname) / 2)
SetColor(255, 255, 255)
SetScale(1, 1)
SetImageFont(ImageFont)
EndIf
EndIf
Case iGUITYPE_TEXTFIELD
If GuiElement.iVisible And (GuiElement.Owner.owner = CurrentWindow) Then
If GuiElement.Owner.iEnabled Then
If ((guielement.iblinktime + guielement.ilastblink) < MilliSecs()) Then
guielement.ilastblink = MilliSecs()
guielement.iblink = 1 - guielement.iblink
End If
'If guielement.iclicked <> guielement.iclickedlast Then guielement.tmimage.animateManual()
If GuiElement.iison <> GuiElement.iisonlast Then GuiElement.tmimage.animateManual()
Local ImageFont:TimageFont = GetImageFont()
SetImageFont(tifGuiFont)
' SetScale(GuiElement.iwidth / ImageWidth(GuiElement.tmimage.tiimage), GuiElement.iheight / ImageHeight(GuiElement.tmimage.tiimage))
DrawImage(GuiElement.tmimage.tiimage, GuiElement.iXPos, GuiElement.iYPos, GuiElement.tmimage.iframe)
SetColor(20, 20, 20)
DrawText(GuiElement.sName, GuiElement.iXPos - guielement.tmImage.tiimage.width / 3, GuiElement.iYPos - guielement.tmImage.tiimage.height / 2)
SetColor(255, 255, 255)
SetScale(1, 1)
SetImageFont(ImageFont)
SetColor(200, 150, 150)
DrawText(guielement.sinput, GuiElement.iXPos - 50, GuiElement.iyPos - 5)
SetColor(255, 255, 255)
If SelectedTextField = GuiElement
If GuiElement.iblink = 1 Then
DrawRect(GuiElement.iXPos - 50 + TextWidth(GuiElement.sinput), GuiElement.iyPos - 5, 1, 15)
End If
EndIf
EndIf
EndIf
End Select

Next
End Function



Function RectMouseCollision:Int(piMouseX:Int, piMouseY:Int, piXRect:Int, piYRect:Int, piRectWidth:Int, piRectHeight:Int)
If ((piMouseX <= (piXRect + piRectWidth / 2)) And (piMouseX >= (piXRect - piRectWidth / 2))) Then
If ((piMouseY <= (piYRect + piRectHeight/2)) And (piMouseY >= (piYRect - piRectHeight/2))) Then
Return True
EndIf
EndIf
Return False
End Function


Den Pfad für die Grafiken muss natürlich jeder individuell umschreiben. UNd die Konstanten für die Buttongrößen dann entsprechend anpassen.

Die Struktur sieht so aus: Es kann beliebig viele Windows geben. Jedes window kann maximal 5 Labels (kleinere Flächen) beinhalten und jedes Label kann maximal 10 Buttons beinhalten. Ihr könnt also auf einem einzigen Fenster gleichzeitig 50 Buttons darstellen. Es kann immer nur ein Fenster aktiv sein.
Welches das ist ändert mal einfach mit SetActiveWindow(pWindow).
Beim erstellen von Labels ist es wichtig, ein Fenster (Window) zu übergeben das vorher auch bereits erstellt wurde. Beim Erstellen eines Buttons muss man ein entsprechendes Label angeben.

Hier ist noch ein Beispiel:
BlitzMax: [AUSKLAPPEN]
Import brl.timer
Import brl.random
Import brl.PNGLoader
Import "GUI_New.bmx"
SuperStrict

Graphics 1024, 768


SeedRnd MilliSecs()
AutoMidHandle(1)
SetBlend(ALPHABLEND)


Global fGFXWidth:Float = GraphicsWidth()
Global fGFXHeight:Float = GraphicsHeight()
Global fGFXWidthHalf:Float = fGFXWidth / 2.0
Global fGFXHeightHalf:Float = fGFXHeight / 2.0

Global fXScroll:Float, fYScroll:Float

Global FTimer:TTimer = CreateTimer(60)

Global iMousehitRight:Int
Global iMousehitLeft:Int
Global iMouse_X:Int, iMouse_Y:Int

Local MainMenuWindow:TGuiElement = tguielement.createwindow()
Local OptionLabel:TGuiElement = tguielement.CreateLabel(MainMenuWindow, 0)
Local MenuLabel:TGuiElement = tguielement.CreateLabel(MainMenuWindow)
Local StartingGameLabel:TGuiElement = TGuiElement.CreateLabel(MainMenuWindow, 0)

'(pMask:TMask, psName:String, piXPos:Int, piYPos:Int, piWidth:Int = iBUTTONWIDTH, piHeight:Int = iBUTTONHEIGHT, piEnabled:Int = 1)
Local ButtonOptionsMenu:TGuiElement = TGuiElement.CreateButton(MenuLabel, "Options", 400, 200,,, 1)
Local ButtonBeendenMenu:TGuiElement = TGuiElement.CreateButton(MenuLabel, "Beenden", 400, 300,,, 1)
Local ButtonStartenMenu:TGuiElement = TGuiElement.CreateButton(MenuLabel, "Starten", 400, 400,,, 1)
Local ButtonMenuOptions:TGuiElement = TGuiElement.CreateButton(OptionLabel, "Menu", 300, 300,,, 1)

'(pLabelOwner:TGuiElement, psName:String, piXPos:Int, piYPos:Int, piWidth:Int = iBUTTONWIDTH, piHeight:Int = iBUTTONHEIGHT, piEnabled:Int = 1)
Local TextFieldPLayerName:TGuiElement = TGuielement.CreateTextField(Startinggamelabel, "Name:", 400, 300,,, 1)

SetActiveWindow(MainMenuWindow)

While Not KeyHit(KEY_ESCAPE) Or AppTerminate()
WaitTimer(FTimer)
Cls
iMouse_x = MouseX()
iMouse_Y = MouseY()

iMousehitLeft = MouseHit(1)

UpdateGUI(iMousehitLeft, iMouse_X, iMouse_Y)
RenderGui()

If iMousehitLeft And TGuiElement.guielementclicked(ButtonOptionsMenu) Then
OptionLabel.ienabled = 1
MenuLabel.iEnabled = 0
EndIf
If iMousehitLeft And TGuiElement.guielementclicked(ButtonBeendenMenu) Then End
If iMousehitLeft And TGuiElement.GuiElementClicked(ButtonStartenMenu) Then
MenuLabel.iEnabled = 0
StartingGameLabel.ienabled = 1
EndIf
If iMousehitLeft And TGuiElement.GuiElementClicked(ButtonMenuOptions) Then
OptionLabel.ienabled = 0
MenuLabel.iEnabled = 1
EndIf

If iMousehitLeft And TGuiElement.GuiElementClicked(TextFieldPLayerName) Then SelectedTextField = TextFieldPLayerName

If SelectedTextField <> Null Then
Local c:Int
Local w:String

c = GetChar()
If ((c <> 13) And (c <> 0)) Then
If c <> 8 Then
w = Chr(c)
ElseIf c = 8 Then
SelectedTextField.sinput = Left(SelectedTextField.sinput, SelectedTextField.sinput.Length - 1)
EndIf
EndIf

If (SelectedTextField.ixpos - 50 + TextWidth(SelectedTextField.sinput)) < (SelectedTextField.iXPos + SelectedTextField.tmImage.tiimage.width / 2 - 30) Then
SelectedTextField.sInput = SelectedTextField.sInput + w
EndIf
EndIf

imousehitleft = 0

Flip 0
Wend


So...
Viel Spaß damit. Ich hoffe es hilft mal jemandem.

Lg, M0rgenstern

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group