DrawingArea für transparente Bilder

Alle Fragen zur Programmierung, die nicht in die speziellen Themen passen
Marcus
Foriker
Beiträge: 22
Registriert: Di 27. Dez 2005, 21:25
Kontaktdaten:

DrawingArea für transparente Bilder

Beitrag von Marcus » Di 27. Dez 2005, 21:30

Hallo Leute,

ich versuche in Gambas transparente Bilder zu realisieren. Der Code sieht so aus wie in folgendem Beispiel:


--------

Code: Alles auswählen

PUBLIC SUB Form_Open()

 DIM mypic AS Picture
  DIM bg AS Picture
  
  ' We've already created a DrawingArea called "dr" on the form.
  ' Load the background.
  bg = Picture["barcelona-aquarium.jpg"]
  
  ' Load the transparent picture.
  mypic = Picture["gambas7.png"]
  
  ' Turn on caching for the drawing area.
  ' 
  ' While it wasn't documented till recently, caching is really 
  ' helpful because it lets the drawing area handle its own 
  ' redrawing automatically.  Otherwise it gets erased whenever 
  ' something else obscures it, and in this case, since we're 
  ' drawing before the form gets shown, it never would be drawn 
  ' at all unless we cached it.
  '
  ' You can also set caching in the Properties dialog,
  ' but I wanted to explain it here.
  dr.cached = TRUE
  
  ' Go into drawing mode on our DrawingArea.
  Draw.begin(dr)
  
  ' Place the background in the upper left hand corner.
  ' (You'd want the drawing area to be the same size
  ' as your background.)
  Draw.picture(bg,0,0)
  
  ' Finally, draw our buddy the shrimp...
  Draw.picture(mypic,40,180)
  
  ' ...and leave drawing mode.
  Draw.end
---------

Nun suche ich eine Möglichkeit eine Aktion auf das Bild mypic zu legen. So soll bei einem Klick darauf ein Programm ausgeführt werden. Ich hab aber keine Ahnung wie ich auf mypic zurückgreifen kann. Eine Aktion an die DrawingArea an sich zu binden geht mit:

----------

Code: Alles auswählen

PUBLIC SUB dr_MouseDown()

  EXEC [ "/opt/kde/bin/kedit" ] FOR READ WRITE

END
----------

Gibt es nun eine Möglichkeit auf das Unterelement mypic zuzugreifen?

Wie kann ich sowas sonst realisieren. Alle anderen Elemente scheinen mit Transparenz Probleme zu haben.

MfG
Marcus

roemi
Site Admin
Beiträge: 425
Registriert: So 11. Dez 2005, 20:05
Wohnort: Hanau / Germany
Kontaktdaten:

Beitrag von roemi » Mi 28. Dez 2005, 12:32

Hi und Hallo,

vorab auf die schnelle .... welche Version von Gambas verwendest Du?
Römi (seit 1989 bekennender Bergradfahrer und professioneller Biertrinker)
http://www.roemi.de

Marcus
Foriker
Beiträge: 22
Registriert: Di 27. Dez 2005, 21:25
Kontaktdaten:

Gambas Version

Beitrag von Marcus » Mi 28. Dez 2005, 13:06

Ich verwende Ver. 1.0.6.

Viele
objektorientierten Sprachen haben ein Keyword wie "this", um auf den
aktuellen Objektkontext zu verweisen, mit this.xy=foo kann man dann in
jeder Funktion auf eine Eigenschaft des aktuellen Objekts zugreifen,
also etwa this.mypic=...

Das scheint hier aber nicht zu funktionieren.

Viele Grüße
Marcus

nibbana
Foriker
Beiträge: 143
Registriert: Fr 16. Dez 2005, 21:32
Kontaktdaten:

Beitrag von nibbana » Mi 28. Dez 2005, 13:43

Sowas wie this gibt es schon heißt hier aber ME.

Hilft dir aber nicht weiter, weil mypic local in der Funktion ist und keine Eigenschaft des Objects. Dazu mußt du mypic außerhalb von
Form_Open deklarieren.

mfg. nibbana
"Ich denke, also bin ich." (Descartes)

"Ich denke nicht, also was?" (Zen Meister Seung Sahn)

Marcus
Foriker
Beiträge: 22
Registriert: Di 27. Dez 2005, 21:25
Kontaktdaten:

Global

Beitrag von Marcus » Mi 28. Dez 2005, 21:16

Ich habe nun mal folgendes probiert. Ich habe zunächst eine neue Klasse Gloabal erstellt und diese zur Startklasse gemacht. Dort steht nun folgendes:
----------
STATIC PUBLIC picvideo AS Picture
STATIC PUBLIC SUB Main()
form1.Show
'Wenn Sie diese Zeile nicht einfügen , wird keine Form angezeigt.
END
----------

Die Form1 sieht nun so aus:

----------
PUBLIC SUB Form_Open()

DIM picbg AS Picture
' Load the trbgansparent picture.
Global.picvideo = Picture["konsole.png"]
picbg = Picture["background.png"]

' Turn on caching for the drawing area.
drbg.cached = TRUE

' Go into drawing mode on our DrawingArea.
Draw.begin(drbg)
Draw.picture(picbg,0,0)
Draw.picture(Global.picvideo,140,140)
Draw.end


END
----------

Ich kann also auf die Variable zugreifen und diese definieren. Wie kann ich denn nun eine Aktion an diese Variable binden?

Ein:

----------
PUBLIC SUB Globalpicvideo._MouseDown()

EXEC [ "/opt/kde/bin/kedit" ] FOR READ WRITE

END
-----------
funtkioniert leider nicht.

MfG
Marcus

nibbana
Foriker
Beiträge: 143
Registriert: Fr 16. Dez 2005, 21:32
Kontaktdaten:

Beitrag von nibbana » Do 29. Dez 2005, 00:06

Nochmal zum mitschreiben.

1. du willst in drbg das Hintergrundbild picbg zeichnen
2. du willst das Vordergrundbild picvideo darüber zeichnen
3. du willst auf das Vordergrundbild, und nur darauf, klicken um kedit zu starten

Sehe ich das so richtig?

Wenn ja wird das nicht funktionieren. Weder picgb noch picvideo sind sichtbare Elemente und deshalb auch nicht klickbar. Du kannst das Signal nur an drbg binden.

Aber vielleicht hilft dir folgende Lösung weiter.

Code: Alles auswählen

PUBLIC mypic AS Picture
PUBLIC SUB Form_Open()

' hier der Code aus dem 1. Posting

END

PUBLIC SUB dr_MouseDown()
  DIM x AS INTEGER
  DIM y AS INTEGER
  DIM c AS INTEGER

  x = Mouse.X - 40  ' x-wert von Draw.picture(mypic,...)
  y = Mouse.Y - 180 ' y-wert von Draw.picture(mypic,...)
  c = mypic.Image[x,y] ' Farbwert in mypic
  ' Farbwert testen, -1=außerhalb des Bildes, -16777216=transparenter Bereich
  IF c<>-1 and c<>-16777216 then
    EXEC
  ENDIF
END
mfg. nibbana
"Ich denke, also bin ich." (Descartes)

"Ich denke nicht, also was?" (Zen Meister Seung Sahn)

Marcus
Foriker
Beiträge: 22
Registriert: Di 27. Dez 2005, 21:25
Kontaktdaten:

guter Ansatz

Beitrag von Marcus » Do 29. Dez 2005, 12:11

Hallo,

der Ansatz ist ja schonmal gut. Allerdings werde ich mehrere Bilder über das Hintergrundbild laden müssen, die alle klickbar sein sollen. Es macht also nur sinn mit Positionswerten zu arbeiten. Ich denke da an sowas wie "Wenn sich die Maus in dem Feld X=140 Y=140, X2=172 Y2=172 befindet und dann die Maus gedrückt wird, führe folgendes aus...

Du hast ja auch Mauspositionswerte definiert; deine Abfrage bezieht sich aber auf die transparenz des Bildes. d.h. das Bild muss zwingend einen Transparenten Rahmen haben.

Ich habe sogar schon überlegt unsichtbare Buttons über die Bilder zu legen, aber auch das scheint nicht zu funktionieren. Wenn die Imagebox Transparenz ünterstützen würde hätte ich diese Probleme nicht. :?

MfG
Marcus

nibbana
Foriker
Beiträge: 143
Registriert: Fr 16. Dez 2005, 21:32
Kontaktdaten:

Re: guter Ansatz

Beitrag von nibbana » Do 29. Dez 2005, 12:55

Marcus hat geschrieben: der Ansatz ist ja schonmal gut. Allerdings werde ich mehrere Bilder über das Hintergrundbild laden müssen, die alle klickbar sein sollen. Es macht also nur sinn mit Positionswerten zu arbeiten. Ich denke da an sowas wie "Wenn sich die Maus in dem Feld X=140 Y=140, X2=172 Y2=172 befindet und dann die Maus gedrückt wird, führe folgendes aus...
Die Idee hatte ich auch. Aber dann erkennst du nicht ob das Bild an dieser Stelle transparent ist.
Marcus hat geschrieben: Du hast ja auch Mauspositionswerte definiert; deine Abfrage bezieht sich aber auf die transparenz des Bildes. d.h. das Bild muss zwingend einen Transparenten Rahmen haben.
Ebend nicht. Die Abfrage dient nur dazu im transparenten Bereich keine Aktion auszuführen. Wenn das Bild keine transparenten Teile hat wird immer ein Farbwert ungleich -1 und -16777216 gelesen.
"Ich denke, also bin ich." (Descartes)

"Ich denke nicht, also was?" (Zen Meister Seung Sahn)

Marcus
Foriker
Beiträge: 22
Registriert: Di 27. Dez 2005, 21:25
Kontaktdaten:

Label

Beitrag von Marcus » Fr 30. Dez 2005, 12:32

Hallo,

danke erstmal für die Hilfe. Ich bin nun schon ein gutes Stück weiter gekommen. Da Gambas aber scheinbar keine transparenten Labels unterstützt muss ich diese auch mit Bildern realisieren. Das Problem bei der o.g. Lösung ist das ich genau den Text treffen muss um eine Aktion bei einem Klick auslösen zu können. Wie müsste ich den Code umbiegen um bei diesen Pseudolabeln (picture) einfach einen Klick im Rahmen der gesamten Bildgrösse zu akzeptieren?

MfG
Marcus

nibbana
Foriker
Beiträge: 143
Registriert: Fr 16. Dez 2005, 21:32
Kontaktdaten:

Beitrag von nibbana » Fr 30. Dez 2005, 16:38

Wenn der Text als Bild vorliegt kann die Abfrage ähnlich aussehen. Lass einfach den 'AND c<>-16777216' Teil weg.

Du kannt aber auch den Text direkt mit Draw.Text schreiben. Dann mußt du die X,Y-Werte abfragen und sehen ob du in dem Rechteck bist.

mfg. nibbana
"Ich denke, also bin ich." (Descartes)

"Ich denke nicht, also was?" (Zen Meister Seung Sahn)

Marcus
Foriker
Beiträge: 22
Registriert: Di 27. Dez 2005, 21:25
Kontaktdaten:

Draw.Text

Beitrag von Marcus » Fr 30. Dez 2005, 20:12

Hallo nochmal,

also die Lösung mit den Textlabels in Bildformat funktioniert. Ich finde die Draw.Text Variante aber deutlich Speicherschondender. Da ich das Projekt auch mehrsprachig auslegen möchte, ist auch eine Übersetzung der Strings einfacher.

Jetzt habe ich schon mehrere Dinge probiert. Zum einen habe ich die Draw.Text Ausgabe wie folgt deklariert:

-----
Draw.ForeColor = &FFFFFF& 'Faded red
Draw.Font.Name = "Sans"
Draw.Font.Bold = TRUE
Draw.Font.Size = 14 'Give me real big font
Draw.Text("Video", 120,130)
-----

Der Text ansich wird später aus einer Variablen geholt. Jetzt versuche ich wie folgt die Position der Maus zu bestimmen:

-----
DIM xtxtvideo AS Integer
DIM ytxtvideo AS Integer
DIM xmouse AS Integer
DIM ymouse AS Integer

xtxtvideo = 120 ' x-wert von Draw.Text
ytxtvideo = 130 ' y-wert von Draw.Text
xmouse = Mouse.X
ymouse = Mouse.Y
-----

An dieser Stelle hakts dann leider aus. Nun müsste ich ja irgendwie geststellen ob sich die aktuelle Mausposition innerhalb des Felders xtxtvideo / ytxtvideo befindet.

Eine Idee wie das gehen kann?

Viele Grüße
Marcus[/code]

nibbana
Foriker
Beiträge: 143
Registriert: Fr 16. Dez 2005, 21:32
Kontaktdaten:

Beitrag von nibbana » Fr 30. Dez 2005, 20:38

Die linke obere Ecke hast du ja schon bei Draw.Text angegeben.
Die Breite und Höhe bekommst du mit

Code: Alles auswählen

 w = Draw.Font.Width("video")
 h = Draw.Font.Height("video")
mfg. nibbana
"Ich denke, also bin ich." (Descartes)

"Ich denke nicht, also was?" (Zen Meister Seung Sahn)

Marcus
Foriker
Beiträge: 22
Registriert: Di 27. Dez 2005, 21:25
Kontaktdaten:

Beitrag von Marcus » Fr 30. Dez 2005, 23:45

Hallo,

so siehts jetzt ungefähr aus. Es wäre schön wenn Ihr / Du nochmal drübersehen könntest ob man noch was verbessern kann. Funktionieren tuts (dank deiner Hilfe.

Code: Alles auswählen

PUBLIC wtxtvideo AS Integer
PUBLIC htxtvideo AS Integer
......
      Draw.Text("Video", 120,130)
      wtxtvideo = Draw.Font.Width("Video")
      htxtvideo = Draw.Font.Height("Video")
.....
xtxtvideo = 120  ' x-wert von Draw.Text
ytxtvideo = 130  ' y-wert von Draw.Text
xmouse = Mouse.X
ymouse = Mouse.Y
IF xmouse >= xtxtvideo AND xmouse <= xtxtvideo+wtxtvideo THEN
   IF ymouse >= ytxtvideo AND ymouse <= ytxtvideo+htxtvideo  THEN
    EXEC [ "/opt/kde/bin/kedit" ] FOR READ WRITE
  ENDIF
ENDIF

nibbana
Foriker
Beiträge: 143
Registriert: Fr 16. Dez 2005, 21:32
Kontaktdaten:

Beitrag von nibbana » Sa 31. Dez 2005, 00:24

Wenns geht ist gut.

Hast du im Bild noch mehr Stellen, wo du einen Text anklicken willst? Dann wird sich Sache nämlich sehr unübersichtlich. Ich würde deshalb eine eigene Klasse für das Zeichnen und Testen schreiben.

Und noch ein kleiner Tip zum Forum. Wenn du Gambas-Code klammern willst, benutze nicht Code sondern Gambas (Button ganz rechts).

mfg. nibbana
"Ich denke, also bin ich." (Descartes)

"Ich denke nicht, also was?" (Zen Meister Seung Sahn)

Marcus
Foriker
Beiträge: 22
Registriert: Di 27. Dez 2005, 21:25
Kontaktdaten:

Klasse erstellen

Beitrag von Marcus » Sa 31. Dez 2005, 11:27

Hallo,

ich versuche gerade die Berechnung in eine Klasse auszulagern, die etwa so aussieht:

Code: Alles auswählen


PRIVATE text AS String
PRIVATE w AS Integer
PRIVATE h AS Integer

PUBLIC SUB _new(OPTIONAL txt AS String, OPTIONAL xpos AS Integer, OPTIONAL ypos AS Integer)
  text = txt
  x = xpos
  y = ypos
END

PUBLIC SUB setTxt(txt AS String)
  text = txt
END

PUBLIC FUNCTION getWidth() AS Integer

  Draw.ForeColor = &FFFFFF& 'Faded red
  Draw.Font.Name = "Sans"
  Draw.Font.Bold = TRUE
  Draw.Font.Size = 14 'Give me real big font
  w = Draw.Font.Width(text)

  RETURN w
END

PUBLIC FUNCTION getHeigth() AS Integer

  Draw.ForeColor = &FFFFFF& 'Faded red
  Draw.Font.Name = "Sans"
  Draw.Font.Bold = TRUE
  Draw.Font.Size = 14 'Give me real big font
  h = Draw.Font.Height(text)

  RETURN h
END
Ich kann die Werte auch wunderbar unterhalb Form1 / Form_Open() während des Zeichnes der Drawingarea ändern.

Wenn ich allerdings versuche aus der MouseDown Funktion daraus Werte abzurufen, bekomme ich eine Fehlermeldung, da ja nicht mehr auf die Drawing Area zugegriffen werden kann. Kann ich evtl. die DrawingArea selbst als public definieren?

MfG
Marcus

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste