TextField (Eigene Gui)

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

Mathias-Kwiatkowski

Betreff: TextField (Eigene Gui)

BeitragDi, Jan 01, 2013 22:43
Antworten mit Zitat
Benutzer-Profile anzeigen
also, nach dem langen slider problemen habe ich nun ein neues.
meine fenster werden gemalt, danach setz ich ein viewport in grösse des benutzbaren fensters.
nun lass ich alles kommen labels, buttons und eben auch textfelder. und da fängt das problem an.
den auch im textfeld setz ich ein viewport. allerdings weiss ich nicht wie ich es berechnen soll.

hier ein bild dazu.

user posted image,

Edit: das textfeld hat ein scrol bereich der im minus geht ( das funktioniert auch ) sonst würde die schwarze schrift nicht im fenster dargestellt werden. die schwarze schrift geht logischerweise auch nich aus dem fenster raus (dank viewport ) aber naja wie gesagt ich weiss nich wie ich es berechnen soll ( das neue viewport für den text )
 

PhillipK

BeitragDi, Jan 01, 2013 23:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo!

Da ich, aufgrund deines sliders, auch ne gui angefangen habe, kann ich dir vielleicht mit meinem ansatz helfen.
Zuersteinmal:
Um viewports zu realisieren, habe ich einen kleinen Type geschrieben, TViewport.

Dieser hat x,y,w,h als "bereich" sowie felder für die "alten" viewport daten.

Mit der methode "apply()" werden die alten viewportdaten mit GetViewport() geholt und gespeichert.
Heißt: Fenster will sich zeichnen. Krams drumrum wird gemalt, dann der viewport mit viewport.apply() gesetzt und die childs kommen dran. Sprich elemente wie Textfelder etc Smile

Ist alles fertig, führe ich viewport.restore() aus. Dieses setzt den ursprünglichen viewport, der vorher aktiv war.

Soweit mitgekommen? Gut.

Was haben wir also? Wir können beliebig viele viewports nacheinander setzen und immer wieder zum letzten zurückkehren.

Hier könntest du nun für dein Textfield eine weitere methode einführen: applyWithIntersect() odersowas.

Das sieht etwa wie folgt aus (habs nicht getestet, nur in mein type reingeschrieben!)
BlitzMax: [AUSKLAPPEN]
Type TViewport
Field x:Int = 0
Field y:Int = 0
Field width:Int = 0
Field height:Int = 0

Field oldX:Int = 0
Field oldY:Int = 0
Field oldWidth:Int = 0
Field oldHeight:Int = 0

Method Create:TViewport(x:Int, y:Int, w:Int, h:Int)
Self.Set(x, y, w, h)
Return Self
End Method
Method Set(x:Int, y:Int, w:Int, h:Int)
Self.x = x
Self.y = y
Self.width = w
Self.height = h
End Method

Method apply(xoffset:Int, yoffset:Int)
GetViewport(oldX, oldY, oldWidth, oldHeight)
SetViewport(x + xoffset, y + yoffset, width, height)
End Method

Method ApplyWithIntersect(xoffset:Int, yoffset:Int)
'xoffset + yoffset sind für eventuelle verschiebungen, die an einem fenster oder ähnlichem vorgenommen wurden.

GetViewport(oldX, oldY, oldWidth, oldHeight)

Local vpX:Int = Max(x + xoffset, oldx) 'den größeren von beiden werten bevorzugen: Sollte der viewport eines Textfields links aus dem fenster rausragen!
Local vpY:Int = Max(y + yoffset, oldy) 's.o -> nach oben hin begrenzen

Local vpX2:Int = Min(x + xoffset + width, oldx + oldwidth) 'begrenzen nach rechts: Ragt der textfield-viewport über das fenster hinaus, wirds begrenzt.
Local vpY2:Int = Min(y + yoffset + height, oldy + oldheight) 's.o. -> nach unten hin begrenzen

SetViewport(vpX, vpY, vpX2 - vpX, vpY2 - vpY)

End Method

Method Restore()
SetViewport(oldX, oldY, oldWidth, oldHeight)
End Method
End Type




Als viewport breite/höhe würde ich die des Textfeldes nehmen. Sollte sich deine frage auf die schriftgrößenberechnung beziehen, hab ich dich falsch verstanden^^

Mathias-Kwiatkowski

BeitragDi, Jan 01, 2013 23:28
Antworten mit Zitat
Benutzer-Profile anzeigen
das is ja weniger mien probelem, wie gesagt alte daten speichere ich auch.
bzw übermittel sie.

setvieport win.x,win.y,win.w,win.h
textfield.draw(win.x,win.y,win.w,win.h)

im draw(ox,oy,ow,oh) dann

das gadget wird gezeichnet

setviewport self.x,self.y,sel.w,self.h
nun der text

aber naja das viewport ist ja nun unabhängig vom alten vll ausser range. und ich weiss nicht wie ich es genau rechnen soll.

eine möglichkeit wäre

self.x-ox usw... aber ... naja das funtzt net ^^
  • Zuletzt bearbeitet von Mathias-Kwiatkowski am Mi, Jan 02, 2013 0:02, insgesamt 2-mal bearbeitet
 

PhillipK

BeitragDi, Jan 01, 2013 23:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Ähm.
Entschuldige, ich steig nicht ganz durch.

In meinen augen liegt hier kein problem vor. Bedenke allerdings, das dein Viewport sich auf bildschirmpositionen bezieht.

Wahrscheinlich haben deine Guielemente eine relative position im bezug auf das Fenster.
Heißt: Ein textfield bei x= 0, y= 0 liegt oben links in der ecke des fensters, nicht der grafischen oberfläche.

Wenn dem so ist, musst du für das Textfield viewport simpel
SetViewport(self.x + ox, self.y + oy, self.w, self.h)
nutzen.

Hast du allerdings totale positionen für deine elemente, hast du es falsch durchdacht ;D

Stelle sicher, das du aus dem lokalen, objektbezogenen lokalen positionen die Globalen positionen errechnen kannst.
Kommt nun drauf an, wie deine lokalen positionen aussehen^^
Kleiner tipp: Wenn du globale positionen für deine guielemente nutzt, wird es mit verschiebbaren fenstern schwerer.

Meine aufrufe sind wie folgt:

*hauptelement kriegt draw aufforderung*
-> Geht alle unterelemente durch und ruft Draw(self.x,self.y) auf.

--> Unterelment: zeichnet sich selbst mit offsetx + self.x, offsety + self.y, geht dann alle unterelemente durch und ruft dort Draw(self.x+offsetx, self.y+offsetY) auf..

Diesen baum kann man theoretisch unendlich weit forsetzen. OffsetX / OffsetY sind die parameter, die die methode erhält.

Siehts bei dir ähnlich aus? Addiere einfach den offset auf die textfield.x bzw textfield.y variablen und die landest bei globalen positionen, welche du für das viewport brauchst.

Mathias-Kwiatkowski

BeitragMi, Jan 02, 2013 0:04
Antworten mit Zitat
Benutzer-Profile anzeigen
also du verstehst mein problem nicht, vll drück ich mich schlecht aus...
ich weiss das viewport sich auf (den bereich konzentriert...) es geht um die rechnung

wenn ich ein viewport 50,50,100,100 gebe
und darunter ein 100,100,100,100 überschneidet es sich ja.

z.b. was schon ma funktioniert ist:
Code: [AUSKLAPPEN]

TempX =Window X - Scrollbereich
If TempX < WindowX Then BereichX = WindowX

SetViewport (BereichX, .... )

aber was wenn Textfield X + Textfield Weite > als window x + window weite ist, wie berechne ich das?
 

PhillipK

BeitragMi, Jan 02, 2013 0:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Was spricht gegen simples min/max, wie ich es schon vorgeschlagen hatte?

Immernoch: In meinen augen ist da kein problem Very Happy

Wenn etwas über das "fenster" hinaus ragt, nimm einfach den rand vom fenster.

Anyways, etwas breiter gefasst:
BlitzMax: [AUSKLAPPEN]

Type tTextfield
Field x:Int,y:Int,w:Int,h:Int
Function Create:TTextfield(x:Int,y:Int,w:Int,h:Int)
Local tf:TTextfield = New TTextfield
tf.x = x
tf.y = y
tf.w = w
tf.h = h
Return tf
End Function
End Type

Local window:TTextfield = TTextfield.Create(50,50,100,100) 'der einfachheithalber als "dummy" fürs fenster. Nur zum erklären :>
Local textfeld:TTextfield = TTextfield.Create(100,100,100,100)

SetViewport(window.x,window.y,window.w, window.h) ' fenster setzen
'inhalte zeichnen

'nun zum textfield:
Local tmpx:Int = textfeld.x
Local tmpy:Int = textfeld.y
Local tmpw:Int = textfeld.w
Local tmph:Int = textfeld.h

'tmpX etc enthalten unsere viewport werte. Nun prüfen wir, ob diese eventuell das fenster-viewport krams überschreiten würden:

If tmpx < window.x Then
tmpx = window.x 'neues start-x angeben
tmpw = tmpw - (window.x-textfeld.x) ' von der aktuellen breite die differenz abziehen.
' Da window.x größer ist, erhalten wir mit window.x-textfeld.x die differenz, um welche wir grade tmp.x "erhöht" haben -> dieser wert muss von der alten breite abgezogen werden, damit der "endpunkt" des rechtecks erhalten bleibt.
EndIf

If tmpx + tmpw > window.x + window.w Then
'die breite würde das fenster überschreiten. Also: aus obieger abfrage die differenz rausziehen und als tmpw setzen :)
tmpw = tmpw - ((window.x + window.w) - (tmpx +tmpw)) ' beispiel: 100 -( (50 + 100) - (100 + 100))
'unser textfield würde also bei koordinate 200 enden. das fenster ended aber bei 150. Ergo: wir ziehen die differenz, hier 50, von tmpw ab.
EndIf
'selbes spiel nochmal für y und h werte.


'oder direkt vereinfacht: wir nutzen min und max:

tmpx = Max( textfield.x , window.x) 'größerer von beiden werten wird wiedergegeben. hier also: textfield.x
tmpy = Max( textfield.y , window.y) 'siehe oben

tmpx2 = Min( textfield.x + textfield.w, window.x+window.w) 'trickiger: wir berechnen erst einen zwischenschritt, tmpx2. Dieser ist der totale xkoordinaten punkt, welcher durch x+breite gebildet wird. wir nehmen den kleineren der beiden werte: entweder window oder textfeld.
tmpy2 = Min( textfield.y + textfield.h, window.y + window.h ) 'siehe oben

tmpw = tmpx2-tmpx ' die differenz zu tmpx bildet nun unsere wunschbreite
tmph = tmpy2 - tmpy 'siehe oben.


Hier mal 2 wege, um die positionen zu beschränken.
Obige rechnugn ist aus dem kopf geschrieben und nicht getestet, sollte aber soweit hinhaun.
Im endeffekt werden tmpx = 100, tmpy = 100, tmpw = 50, tmph = 50 werden.

Die rechnung lässt sich beliebig vereinfachen, min / max könnte man auch verschachteln.. aber so sollte es erstmal ausreichen Smile
Hoffentlich hauts bei dir nun hin Smile Ich geh nämlich schlafen *grins*

Mathias-Kwiatkowski

BeitragMi, Jan 02, 2013 0:41
Antworten mit Zitat
Benutzer-Profile anzeigen
ja klingt logisch, bis der scrollbereich hinzukommt^^


also habs nun so wie du aber naja es funtktioniert einfach nich.

Code: [AUSKLAPPEN]

If TextFieldX < WindowX Then ZeigeX = WindowX
If TextFieldX + TextFieldW > WindowX + WindowW Then MaxBereich =  ((WindowX + WindowW) - (TextFieldX  + TextFieldW))


und hier der aufruf des fensters
Code: [AUSKLAPPEN]
Global TestFenster:TWindow = TWindow.Create("Fenster fsdjkhkfjjsdfhskhdfjhsdkfjsj", 50, 50, 300, 500, "Scale | Close | Maximize | SetTask")
Global Text:TTextField = ttextfield.Create(600, 900, 300, Testfenster)
Global TestButton:TButton = tbutton.Create("LOL", 3200, 3300, 150, 20, Testfenster)


also wenn noch nicht gescrollt worden ist, steht der text immernoch dort (ausserhalb des fensters)
sobald ich scrolle wird er kleiner^^ keine ahnung ...

Mathias-Kwiatkowski

BeitragMi, Jan 02, 2013 2:47
Antworten mit Zitat
Benutzer-Profile anzeigen
ich habe nun eine lösung gefunden ... endlich.

Code: [AUSKLAPPEN]
If tx < wx Then SX = wx
      If tx < wx Then
         Temp:Float = wx - tx
         sw = Self.w - temp
      EndIf
      If tx + Self.w > wx + ww Then
         Temp:Float = (tx + Self.w) - (wx + ww)
         sw = Self.w - temp
         Print Temp
      EndIf


muss ergänzen.
TX = textfield X
TW= Textfield W
WX =window x
WW =window w

SW = Offsetz für die weite des viewport's

Midimaster

BeitragMi, Jan 02, 2013 4:20
Antworten mit Zitat
Benutzer-Profile anzeigen
da kann ich euch nur nochmal raten, sich durch mein GUI Gadget Tutorial zu arbeiten. Da stehen schon im Kapitel 2 genau solche Dinge drin: wie verschachtelnde Viewports aus Mother und Child zu handlen sind.

Das Kapitel über Scrolling gibts leider momentan nur in der Syntax eines Monkey Tutorial. Läst sich aber problemlos auf BMax übetragen. An sich ändert sich aber durch Scrolling gar nix an der Viewport Logik, wenn man die korrekt implementiert hat.

Der Phillip ist da schon auf dem richtigen Weg, dass jedes Gadget einen eigenen Viewport verwaltet. Allerdings muss der "alte" gar nicht gesichtert werden. Durch das rekursive Iterieren durch alle Childs wird er sowieso wieder richtig zurückgestellt, wenn man aus einem Child in die Mother zurückspringt.
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe
 

PhillipK

BeitragMi, Jan 02, 2013 6:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, in welcher richtung verschachtelt wird, ist mmn. geschmackssache.

Aber verwirrts bin ich trotzdem:

Wieso genau brauchst du den scrolling bereich für deinen Viewport? Für mich schleierhaft.
Beim scrolling ändert sich nur der startpunkt des zeichnens für den text. Die tatsächliche onscreen-clippingwerte bleiben unangetastet!
Je nachdem wie du scrollst, kannst du SetOrigin() verwenden:

BlitzMax: [AUSKLAPPEN]
Local textbreite:Int = TextWidth( _string)
Local sliderPosition:Float = slider.getPosition() 'ausgehend hier: wert zwischen 0.0 und 1.0 als skalierfaktor
Local textFieldWidth:Float = Self.width

SetOrigin ( -(textbreite - textfieldwidth) * sliderposition, 0) 'scrollen :)

Du siehst, das viewport bleibt unangetastet.
Durch SetOrigin() wird eine art offset auf alle zeichenoperationen geadded. Das Viewport bleibt aber von den originwerten verschont: Es hat immernoch die selbe position auf dem bildschirm. Heißt im klartext: Wir schieben den text ein wenig nach links, wodurch der vordere teil "ausserhalb" des viewports landet und wir einen scrollingeffekt haben.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group