Probleme beim Umstieg von 2017r1 auf 2018r3

Hallo in die Runde,
ich bin gerade von 2017r1 auf die aktuelle Version umgestiegen und bekomme nun Fehlermeldungen wegen dieser Zeilen:
me.graphics.textfont=“arial”
me.graphics.textSize=10

Offenbar gibt es beim Canvas (und auch an diversen anderen Objekten fehlt das, z. B. beim Fenster) kein Graphics mehr. Wie behebe ich das?

Gru, Stefan Mettenbrink.

Hi Stefan,

ja, der Zugriff aufs Graphics Objekt ist nur noch über das Paint-Event von Canvas/Window bzw. innerhalb von Picture möglich. Also wäre am einfachsten, alles über Canvas.Paint zu erledigen. Dazu könntest Du ja diverse Methoden anlegen, die einen g As Graphics Parameter besitzen und diese dann innerhalb des Canvas.Paint-Events aufrufen.

Gruß

Wie in meinem beispiel möchte ich dem Graphics Object im Canvas einmalig (dauerhaft) einen Font und eine Schriftgröße zuweisen. Wenn ich das in das Paint Event verlege, wird das ja jedesmal beim Neuzeichne neu gesetzt. Das ist so aber nicht sinnvoll.

Gibt es dafür keine sinnvollere Variante?

Das ist genau die Variante, die Xojo prferiert. Die Alternative dazu wre, ein Offset Picture zu erstellen, alle Zeichnungen innerhalb von Picture.Graphics vorzunehmen und dieses via Canvas.DrawPicture in die Canvas zu zeichnen/bei bedarf neu zu zeichnen.

Das muss man nicht gut finden, oder?
Gerade die Grundeigenschaften setzt man doch nur einmal. Das gehört doch in das Open Event. Dafür habe ich kein Verständnis.

Hat jemand eine plausible (und sinnvolle) Erklärug für diese Änderung?

Das ist doch aber uninteressant. Das Paint Event wird ausgeführt wenn nötig oder wenn erzwungen. Alles was dann neu gezeichnet werden muss, wird also neu gezeichnet.
Es ist ja nicht so als würde das Definieren der Schriftgröße etwas auslösen oder messbare Zeit kosten. M.M. nach macht es keinen signifikanten Unterschied ob solche Parameter im Open Event oder jedesmal bei der Ausführung definiert werden.
Gleichzeitig ist es doch auch flexibler und nur logisch das im Paint Event zu machen, denn dort kannst Du sämtliche Eigenschaften der Schrift so oft im Text ändern wie Du möchtest, während eine Definition im Open Event lediglich die Initialen Eigenschaften beschreiben kann. :slight_smile:

warum diese Änderung eingeführt wurde, wurde im Forum gut erklärt aber ich finde den Post nicht mehr. :confused:

Hallo Stefan,
Dein Ansatz ist falsch, Canvas ist nur zur Darstellung auf dem Bildschirm da, alles zum Bildaufbau solltes du
ausserhalb in einer oder mehreren Picture Elementen durchführen.
Mousedown usw. sind nur zur Steuerung der entsprechenden Funktionen zur Bildbearbeitung da.
canvas.invalidate ruft Paint auf
Paint zeichnet dir alles auf dem Bildschirm. Hier in Paint kanst Du über dein Picture auch z.B. einen Rahmen oder verschiebbares Shape darstellen. Mousedrag/Mousemove geben dabei die Positionen vor.

Paint:
If pic <> Nil Then g.drawpicture pic,0,0,g.Width,g.height,0,0,pic.Width,pic.height
If myshape <> Nil Then g.DrawObject(myshape,mposx,mposy)

// Rahmen rot
g.PenWidth=1
g.penheight=1
g.ForeColor=&cff0000
g.drawrect(0,0,g.Width,g.Height)

Ich meine diese Art der Darstellung ist viel fexibler

Ich kann euch nicht folgen.
Wenn ich ein TextField habe und da eine vom Benutzer definierte Schrift, Scfrtfarbe und Font einstelle, dann mache ich das doch auch direkt im Open-Event (oder vom Einstellungsdialog aus) und nicht im TextChange-Event.

Genauso empfinde ich es für das Graphics Objekt von Canvas und Window (etc.). Hier möchte ich einmal einstellen in welcher Textgröße , -Font und -Farbe der Text ausgegeben werden soll. Ich benötige (in den Problemfällen) keine Änderunges wärend des Paint Events.

Ich erkenne hier keinen Vorteil an der (aus meiner Sicht unnötigen) Einschränkung. Im Gegenteil. Hier werden mit jedem Paint Event immer wieder dieselben Einstellungen vorgenommen.

Niemand würde solches programmieren:

Do
irgendwas
TextField.TextSize=10
loop until Bedingung

Man würde TextSize vor der Schleife einmal setzen.
Genau das versuche ich hier im Open-Event. Das ging bislang auch problemlos. Nicht, dass ich das nicht ändern könnte. Aber es ärgert mich, dass man mir dasmit einen Haufen Arbeit ans Bein bindet.

Mit welcher Version hat sich das Verhalten geändert?

Jetzt gerade aktuell mit 2018r3.

Allerdings ist die schon lange angekündigte Streichung dem Umstand zu verdanken, dass das Graphics-Objekt betriebssystemseitig auch bei jedem Redraw neu erzeugt wird. Die Property war also nur eine Abkürzung zu einer Funktion, die du selbst einfach nachpflegen kannst, z.B. mit einem Graphics-Setup-Event am Beginn des Paint-Events. Dann musst du deinen Code nur rüberkopieren.
Technisch dürfte damit nichts anderes passieren als bisher.

Moment, wenn ich am Beginn des Paint Events jedesmal(!) ein Graphics-Setup-Event aufrufe, erreiche nicht nicht den einmaligen Aufruf, wie ich es jetzt mit dem Open Event erreiche.

Oder verstehe ich etwas falsch?

Was ist denn ein Graphics-Setup-Event?

Deine Code gehört ins Paint-Event:

g.textfont="arial" g.textSize=10

Fertig.

Ein Graphics-Setup-Event kenne ich bisher ebenfalls nicht.
Allerdings verstehe ich den Sinn nicht, warum ich einmalige Einstellungen (wie das Setzen von Font, Schriftfarbe und Schriftgröße nicht im Open Event erledigen kann.
Warum muss ich immer dieselben Einstellungen im Paint Event bei jedem Neuzeichnen erneut setzen. Das ist ineffizient.

Nicht, dass ich das nicht kann, aber ich wüsste schon gern einen (guten/sinnvollen) Grund. Zumal es je vorher ging. Da hat man sich bei dieser Änderung doch hoffentlich etwas geadcht.

Somit war das ein Workaround vom Xojo Framework. Es hat die vermeintlich ‚Control-allgemeinen‘ Graphics-Einstellungen im immer neuen Paint Event Graphics Kontext jedesmal übernommen.
Nötig war das wohl um bestehenden Code nicht zu brechen, da das mit Carbon vlt. möglich war.
Nur konnte man seinerzeit damit auch ausserhalb des Paint Events zeichnen… und das gibt das diverse subtile oder grössere Nebenwirkungen (Bugs), welche jetzt nicht mehr auftreten können.

g.textfont=“arial”
g.textSize=10
und andere reine Einstellungen zeichnen nichts im Objekt. Das stellt lediglich Parameter auf definierte Werte.

In diesem Fall: ja.
Es dürfte nun aber effizienter sein, wenn nur noch diese 2 Eigenschaften in jedem Paint Event gesetzt/überschrieben werden, und nicht jedesmal alle vom Altlast/Kompatibilitäts-GraphicsObjekt übertragen werden müssen.
Und es zwingt die Missbrauche, einen optimaleren Weg wählen zu müssen.

Es sind schon noch ein paar mehr Eigenschaften. Eigentlich alles, was sich zu Graphics in den Properties findet und einstellen lsst.

Eben… daher ja meine Vermutung, dass das nun sogar effizienter ist :slight_smile:

Einfach ein Vorschlag, wie du wenig umbauen musst:
Gib deiner (Window/Canvas)-Unterklasse einen Paint-Event-Handler und starte ihn mit RaiseEvent GraphicsSetUp(g).
Diesen Event definierst du und kopierst den Code aus dem Open-Event für die Graphics-Property in den Instanzen-Eventhandler. Das sollte den Umbauaufwand reduzieren.

Danke für den Tipp.

Inzwischen habe ich alles (irgendwie) umgebaut, das erst mal wieder compiliert wird.
Allerdings habe ich auch Arrays vom Typ Canvas. Da habe ich auch einfach über Zugriff aufs Array drin rumgemalt:
CanvasArray(i).Graphics.Drawrect x,y,w,h

Das geht wohl nicht mehr. Da werde ich wohl einen größere Umbauaufwand haben. In dem Fall aber verständlich.

Noch immer habe ich jedoch keinerlei Verständnis, warum ich die Eigenschaften nicht auch von außerhalb oder zumindest im Open Event setzen darf. Ich finde die Einschränkung unnötig und macht den Code ineffizienter.

Wurde an ClearRect auch etwas verndert?

Mein Code:

'g.ForeColor=rgb(210,210,210)
'g.DrawRect 0,0,g.Width,g.Height
g.clearrect 0,0,g.width,g.height

if AusgabeBild<>nil then
  g.drawpicture AusgabeBild,0,0,g.width,g.height
else
    g.ForeColor=rgb(210,210,210)
    g.DrawRect 0,0,g.Width,g.Height
end

ergibt bei nicht vorhandenem AusgabeBild eine schwarze Flche.