Anfngerfrage: DB ffnen / Beispiele

[quote=205815:@Axel Eickhoff]
Gibt es vielleicht irgendwo ein für Normalsterbliche verständliches Tutorial zum Thema “Ich befinde mich in einer Schleife zum Befüllen einer Listbox und will den nächsten zu schreibenden Eintrag in grauer statt schwarzer Schrift haben (PS: in Xojo)”?[/quote]

Ist doch nun wirklich nicht so schwer.

CellTextPaint

ein bestimmtes Wort einfärben

if me.Cell(row, column) = "mein Wort" then g.ForeColor = &c5B518800 end if

bestimmte Zelle einfärben

if row = 3 and column = 0 then g.ForeColor = &c88111100 end if

ganze Zeile einfärben

if row = 5 then g.ForeColor = &c88111100 end if

Guten Morgen. Danke für eure Bemühungen. Die Beispiele meines Namensvetters sind ja schon sehr konkret. Und für sich genommen natürlich auch verständlich.

Mein Problem ist vielmehr, die Dinge nach OO-/Xojo-Logik zusammenzubringen. Hier ist offenbar die Grenze meiner Fähigkeit zur Deduktion erreicht.

Also vielleicht noch mal ganz einfach, von Anfang an. In einer Methode namens LadeClients tue ich eben das:

If rsClients <> Nil Then While Not rsClients.EOF ListClients.AddRow _ rsClients.Field("CLT_LABEL").StringValue, _ rsClients.Field("CLT_ID").StringValue rsClients.MoveNext Wend rsClients.Close End If
Soweit, so gut. In der betreffenden Tabelle (bzw. dem Recordset) befindet sich ein weiteres Feld namens “CLT_ACTIVE” (Boolean), das ich zwar nicht anzeigen, aber zum Kriterium für die Textfarbe des Eintrags in der Listbox machen will.

Deshalb war es für mich nahe liegend, zwischen While und AddRow eine Abfrage einzubauen, sinngemäß:

If rsClients.Field("CLT_ACTIVE").StringValue = "True" Then Textfarbe = Schwarz Else Textfarbe = Grau End If
Und dazu hatte ich nach einer passenden Eigenschaft gesucht, mittels derer ich die Textfarbe des folgenden Eintrags entsprechend hätte manipulieren können.

Okay, so einfach geht es wohl nicht, das immerhin habe ich verstanden. Was ich nicht verstanden habe: Was genau muss jetzt im Event Handler CellTextPaint stehen, und wie funktioniert die Interaktion, wie stelle ich die Verbindung her?

PS @Ulrich: Ja, ein Beispiel in der Art hatte ich gesucht, aber leider nicht gefunden. Wenn man einmal den Fuß in der Tür hätte, könnte das im weiteren Verlauf noch sehr hilfreich sein, im Moment fehlt mir allerdings immer noch der Anfang des roten Fadens (siehe oben).

Du bist schon auf der richtigen Spur. Mach eine Property ins Fenster namens TextFarbe. Dann kommt in das CellTextPaintEvent:

if TextFarbe = "schwarz" then g.ForeColor = xxx elseif TextFarbe = "grau" then g.ForColor = xxxx end if

Natürlich ist das nur als Beispiel gemeint und man nimmt dann Konstanten statt einem String. Eine direkte Verbindung gibt es sonst nicht. Oh, und nicht das invalidate vergessen. Das sagt der Listbox, daß sie sich bei der nächsten Gelegenheit neu malen soll. Wahrscheinlich ist das die Verbindung.

Wenn du zur Darstellung von Farbe etc. auf Daten zurückgreifen musst, die nicht sichtbarer Bestandteil der Tabelle sind – also so wie von dir beschrieben CLT_ACTIVE –, kannst du diese Daten trotzdem in der Listbox halten, um sie dann auszuwerten. Beliebt ist z.B., eine unsichtbare Spalte anzulegen, in der die Daten doch stehen, die aber durch die columnWidths property sozusagen “rechts rausgeschoben” wird – in deinem Beispiel also (50,50,0), damit die ersten beiden Spalten zusammen auf 100 % Tabellenbreite kommen.
Dann machst du im CellTextPaint event genau das, was du geschrieben hast: Du fragst die 3. Spalte der aktuellen Zeile ab und vergibst nach ihrem Wert die Farbe.

Andere Möglichkeit: Beim Aufbauen der Listbox einen Zeilenzähler mitlaufen lassen und ihn verwenden, um den Celltag zu setzen:

Dim Zeile as Integer If rsClients <> Nil Then While Not rsClients.EOF ListClients.AddRow _ rsClients.Field("CLT_LABEL").StringValue, _ rsClients.Field("CLT_ID").StringValue ListClients.Celltag(Zeile, 0) = if (rsClients.Field("CLT_ACTIVE").BooleanValue, "schwarz", "grau") Zeile = Zeile + 1 rsClients.MoveNext Wend rsClients.Close End If

Und dann im CellTextEvent den Celltag(row, 0) auslesen.

CellTag ist ein Variant, du kannst also auch direkt die Farbe als Farbe dort reinstellen. Oder eben, wie Beatrix schon sagte, Textkonstanten nehmen statt jedesmal einen neuen Text zu erzeugen.

Hallo Beatrix, hallo Ulrich, danke für eure weiteren Konkretisierungen. Und für eure Geduld mit einem kognitiv limitierten Veteran der längst vergessenen Organisationsprogrammierung (vor dreißig Jahren auf einer Siemens-Großrechenanlage mit BS 2000 (Assembler, Cobol) sowie auf einem PC unter CP/M (Basic) gelernt und danach einige Jahre unter MS DOS mit Clipper Branchenlösungen entwickelt).

Dummerweise bin ich gerade durch meine eigentliche, hauptberufliche Arbeit “abgelenkt”. Ich werde das aber später alles ausprobieren und mich dann wieder melden.

Solltet ihr jedoch nichts mehr von mir hören, dann habe ich aufgegeben und meinen Rechner in der nahe gelegenen Havel versenkt. :wink:

Schon alleine aus Umweltschutzgründen: Tu’s nicht!

Die Synapsenverzerrungen beim OOP-Lernen kennen die allermeisten von uns nur zu gut. Die alte, linare Programmiermethode scheint sich völlig mit dem OOP-Kram zu beißen, man könnte sich die Haare raufen und eigentlich hat man sich doch schon immer mehr für Gartenbau interessiert …
Also bei mir war das so. Irgendwann allerdings, wenn man kaum noch mag, macht es Klick und ein ganzer Haufen fällt plötzlich an den richtigen Ort. Und nach ein paar weiteren dieser kathartischen Erlebnisse schließlich sieht man, dass das alte Wissen überhaupt nicht veraltet ist und das neue Programmieren gar nicht wirklich neu – im Prinzip turnt die ganze Zeit das Betriebssystem um dich herum und erzeugt die Illusion von Klassen und Objekten. In Wirklichkeit ist da nach wie vor einfach linear aufgebauter Speicher mit in den allermeisten (Anwender-)Fällen auch völlig linear ablaufenden Algorithmen.
Aber diese Lernphase ist hart – keine ironische Überspitzung beabsichtigt!

Viel Erfolg, wann immer deine Arbeit dir wieder Zeit lässt.

Je komplizierter das Programm wird, desto wichtiger is OOP. Wenn irgendetwas nicht mehr in den Kopf pat oder ein Algorithmus zu kompliziert wird, dann wird es Zeit fr OOP. Ich mache das auch nicht berall.

Bezglich der Synapsenverzerrungen kann ich nur sagen, da mein letztes Software-Release sich bei einigen Kunden aufhngt. Seufz, nichts neues also…

Ich habe gestern Abend und heute Morgen noch lange herumgebastelt und alle hier angebotenen Varianten probiert (soweit ich sie verstanden hatte). Leider vergeblich.

CellTag-Variante; ‘LadeClients’:

ListClients.Celltag(ZeileNr, 0) = if (rsClients.Field("CLT_ACTIVE").BooleanValue, "Schwarz", "Grau")

Und in CellTextPaint:

If Me.CellTag(Me.ListIndex, 0) = "Schwarz" Then g.ForeColor = RGB(0,0,0) Else g.ForeColor = RGB(100,100,100) End If

Fehlermeldung beim Debuggen: OutOfBoundsException (If-Zeile)

Andere Variante: Speichern des Feldwertes CLT_ACTIVE als String in der Listbox und Abfrage des Wertes in CellTextPaint.

If Me.Cell(Me.ListIndex, 2) = "True" Then g.ForeColor = RGB(0,0,0) Else g.ForeColor = RGB(100,100,100) End If

Ergebnis: Beim ersten Aufruf sind alle Eintrge grau, beim Anklicken wechseln die Farben der Eintrge munter zwischen Schwarz und Grau, unabhngig vom jeweiligen Inhalt des Feldes “CLT_ACTIVE”. Mal sind einer, mehrere oder alle Eintrge grau oder schwarz, ohne erkennbare Systematik.

Zudem hatte ich probeweise an verschiedenen Stellen InvalidateCell hinzugefgt, Variable statt ListIndex genutzt, Reihenfolgen getauscht und was wei ich noch alles versucht. Ohne nennenswerten Effekt.

Falls jemand noch DEN Hinweis hat, der das Ganze mit einem Schlag auflst, dann nehme ich den natrlich gerne entgegen.

Ansonsten lasse ich die Textfarbe erst mal Textfarbe sein und wende mich anderen Baustellen zu.

[quote=206135:@Axel Eickhoff]If Me.CellTag(Me.ListIndex, 0) = “Schwarz” Then
g.ForeColor = RGB(0,0,0)
Else
g.ForeColor = RGB(100,100,100)
End If[/quote]
Me.ListIndex ist falsch, Du musst die vom Event zur Verfügung gestellte Variable row verwenden:

If Me.CellTag(row, 0) = "Schwarz" Then g.ForeColor = RGB(0,0,0) Else g.ForeColor = RGB(100,100,100) End If

CellTextPaint und CellBackgroundPaint werden für jede Zelle vom System aufgerufen. Damit man weiss, welche Zelle man gerade bemalt oder beschriftet, werden row und column als Argumente übergeben. Bei CellTextPaint kommt dann noch x und y als Argumente dazu: die Position wo der Text hingeschrieben werden sollte.

Ein paar Bemerkungen:

Obiger Code sollte noch in eine zweite If-Klausel gefasst werden, sonst wird zuviel “gemalt”, nämlich bei jedem CellTextPaint, egal ob Spalte 0, 1, 2 oder n:

If column = 0 Then // column ist eines der Argumente die dem CellTextPaint vom System übergeben werden If Me.CellTag(row, 0) = "Schwarz" Then g.ForeColor = RGB(0,0,0) Else g.ForeColor = RGB(100,100,100) End If End If

Immer schauen, dass Du in beiden Paint-Events der Listbox beide Argumente zum eingrenzen verwendest: row und column – ansonsten ist die Wahrscheinlichkeit groß, dass die gleichen Dinge mehrfach gemalt werden.

So nervig die Xojo-Dokumentation manchmal ist, ich hatte die Erfahrung gemacht, dass ich im 2010 als ich mit Xojo begann, viel zu viel rumcodiert habe, statt die jeweiligen Seiten in der Dokumentation konzentriert durchzulesen.

Bei mir ging bei OOP das Licht auf, als mir jemand erzählte, dass ich in Gedanken folgendes mache soll für einen Methodenaufruf:

EinObjekt.EineMethode(arg1, arg2, arg3)

entspricht in prozeduralem Stil:

EineMethode(EinObjekt, arg1, arg2, arg3)

Das ist auch was ein Compiler einer OO-Sprache macht: den Methodenaufruf in eine simple Funktion übersetzen, wobei üblicherweise das erste Argument der Pointer auf das Objekt ist.

Hallo Eli, das war’s. Funktioniert. Danke! Auch für die weiteren Informationen. Mir war nämlich nicht klar, wann das “Ereignis” CellTextPaint genau eintritt und auf was es sich dann genau bezieht (das meinte ich mit “Verbindung”).

Kannst du (oder jemand anderes) mir vielleicht auch noch sagen, warum es mit der Variablen ‘ZeileNr’ statt ‘row’ nicht funktioniert hat? (Damit hatte ich es zuerst versucht.) In der Methode wiederum funktioniert ‘row’ nicht.

Und was hat es mit dem “Invalidate” auf sich, das ich laut Beatrix nicht vergessen sollte? Ich habe das jetzt überall rausgenommen, aber es wird offenbar nirgendwo vermisst.

Der Ablauf ist folgender:

Das System (das Xojo Framework) beschliet, dass die Listbox neu gezeichnet werden muss. Fr jede Zeile Fr jede Spalte Rufe CellBackgroundPaint auf mit row (Zeile) and column (Spalte) als Argumenten Fr jede Zeile Fr jede Spalte Rufe CellTextPaint auf mit row (Zeile) and column (Spalte) als Argumenten

Gegenfrage: wieso denkst Du, dass das funktionieren sollte mit ‘ZeileNr’?

Das sagt dem Xojo Framework, das bei der nchsten Gelegenheit, der obige Ablauf initiiert werden soll.

Weil ich davon ausgegangen bin, dass ‘ZeileNr’ und ‘row’ zum betreffenden Zeitpunkt denselben Inhalt haben: einen numerischen Wert, der die aktuelle Zeilennummer repräsentiert.

So weise ich den Tag in der Methode zu:

ListClients.Celltag(ZeileNr, 0) = "Blabla"

Von daher dachte ich, dass ich ihn im Event-Handler auch mit derselben Adressierung wieder abfragen könnte:

If ListClients.CellTag(ZeileNr, 0) = "Blabla" Then ...

Falsch gedacht?

So in etwa habe ich mir das auch erklärt, aber da es in meinem Beispiel augenscheinlich(!) auch ohne funktioniert, ist mir nicht klar, wann und wo man dieses Invalidate einsetzt. Sollte ich das sicherheitshalber wieder hinzufügen? Oder wird der “Impuls” dann doppelt ausgelöst?

[quote=206171:@Axel Eickhoff]Von daher dachte ich, dass ich ihn im Event-Handler auch mit derselben Adressierung wieder abfragen könnte:
If ListClients.CellTag(ZeileNr, 0) = “Blabla” Then …
Falsch gedacht?[/quote]
Ja. ZeileNr existiert im EventHandler gar nicht. Du kannst auf die Parameter zurückgreifen, die der Event dir liefert, oder du kannst natürlich die Listbox als solche unter ihrem Namen ansprechen und irgendwas mit ihren Properties machen.
Da ZeileNr vermutlich eine lokale Eigenschaft ist, die du beim Befüllen der Listbox erzeugst, existiert sie nicht außerhalb der Methode, in der du sie anlegst.

Die Variable ‘ZeileNr’ hatte ich als Property angelegt, namentlich bekannt war sie dem Event-Handler also immerhin (sonst htte Xojo ja schon beim Kompilieren einen Fehler angezeigt, nicht erst zur Laufzeit). Das aber nur nebenbei, zu meiner Ehrenrettung. :wink:

Ich habe zum besseren Verstndnis mal eine MessageBox in den Event-Handler eingebaut, der mir die Werte von ZeileNr und row ausgibt: ZeileNr ist immer 10, row wird hochgezhlt.

Das heit fr mich: Offenbar wird erst die Schleife in der Methode vollstndig abgearbeitet und die Liste komplett aufgebaut, weshalb ‘ZeileNr’ am Ende den Wert 10 hat (10 Datenstze/Listbox-Eintrge). Und erst dann wird CellTextPaint aktiv und arbeitet seinerseits die Liste komplett ab, also quasi 10 mal nacheinander. Weshalb ‘ZeileNr’ und ‘row’ auch nicht denselben Wert haben knnen.

Okay, euch war das sicher klar, mir aber nicht. Sollte ich das also jetzt richtig verstanden haben(?), dann wre ich immerhin ein kleines Stck weiter (obwohl mir die Vorgehensweise zum Setzen der Textfarbe ber einen Event-Handler grundstzlich immer noch suspekt ist, soviel Sturheit gestehe ich mir zu).

Hast du, bist du!
Es ist bei der Listbox nicht so, dass du eine Zeile füllst und sie dann sofort gemalt wird – in dem Fall würde deine Methode in der Tat funktionieren. Stattdessen wird sozusagen eine eigene Datenbank-ähnliche Struktur angelegt, und wenn die fertig ist, geht’s ab zur Grafikabteilung damit.
Mithin einer der Gründe, warum Betriebssysteme optisch manchmal trotz enorm viel leistungsfähigerer Rechner als früher Hänger haben oder ähnliches – es passiert einfach unter der Haube unglaublich viel mehr, als man auf den ersten Blick denkt. Dass es dann meistens doch so wirkt, als würde alles gleichzeitig und reibungslos funktionieren, ist dann ein gutes Zeichen für eben doch sehr leistungsfähige Rechner dahinter …

Danke für die Bestätigung! Immerhin ein kleines Erfolgserlebnis nach reichlich Frust. :slight_smile:

Wie gesagt: Diese geistige Schwerarbeit (und das jetzt nicht, um dir irgendwie liebzureden – es ist eine solche, wenn man sich auf OOP umschult) kennen die meisten hier mit Sicherheit.
Vielleicht hilft folgender Gedanke noch ein bisschen: Deine Grundidee war linearer Programmierung geschuldet – du erzeugst die Zeile, und sofort kümmert sich das System. Bei OOP ist es aber so, dass du einem Objekt irgendwas zur Arbeit übergibst. Es kümmert sich darum, wenn das OS (und es selbst) der Meinung sind, dass jetzt ein guter Zeitpunkt wäre. Und wenn der gekommen ist, gibt es das über einen Event bekannt. Der ist dann für dich immer die Möglichkeit, selbst etwas zu modifizieren oder den Handler nicht zu implementieren und damit das System seinen ganz normalen Job erledigen zu lassen.

Auch auf die Gefahr, mich zu weit aus dem Fenster zu lehnen: Ich bin mir nicht sicher, ob man nun wirklich jede Vorgehensweise bei Xojo mit dem Grundkonzept des Objektorientierten Programmierens begründen kann und sollte, so als sei es eine gottgebene Gesetzmäßigkeit, an der kein Weg vorbei führt.

Ich denke, es gibt auch innerhalb der OOP große Spielräume bei der Gestaltung von Verfahren und Abläufen.

In der Xojo-Doku finden sich beispielweise rund 80 verschiedene Properties, mit denen sich eine Listbox in ihrem Erscheinungsbild bis auf Zellen-Ebene manipulieren lässt, und zwar direkt, also ohne den Umweg über einen Event-Handler.

Offenbar befand man die Farbe für Text und Hintergrund einer Zelle/Zeile einfach nicht als wichtig genug, um sie ebenfalls auf diese Weise zugänglich zu machen. Aber das ist m. E. eine Entscheidung der Xojo-Entwickler - also der Entwickler von, nicht mit Xojo -, keine Frage von OOP oder nicht OOP.

Ich meine das nicht mal als Kritik. Denn es ist natürlich eines jeden Entwicklers gutes Recht, Dinge so umzusetzen, wie er sie für richtig hält, bzw. wie er glaubt, dass seine Zielgruppe sie erwartet. Da geht man entweder mit - oder sucht sich eine Alternative.

Xojo ist halt, das wird mir in solchen Fällen immer wieder bewusst, eine vollwertige Programmiersprache, mit der sich im Grunde so ziemlich jede Art von Software realisieren lässt. Diese Vielseitigkeit und die damit einhergehende Komplexität hat aber eben auch den Nachteil, dass manche Dinge deutlich aufwändiger zu realisieren sind als es bei spezialisierten Entwicklungsumgebungen der Fall wäre (siehe Datenbankzugriff).

An dieser Schnittstelle kommen dann die Entwickler von Plugins und Erweiterungen ins Spiel, welche die eine oder andere Lücke schließen (was für Amateure wie mich aber aus Kostengründen keine Option darstellt).

Lange Rede, kurzer Sinn: Ich finde Xojo gut und werde es nicht schlecht reden - schon gar nicht ein einem Xojo-Forum -, weil es nicht zu 100 Prozent meinen persönlichen Bedürfnissen entspricht. Aber punktuell zu meckern ist ja erlaubt. :wink:

Wenn Du einmal OOP verstanden hast wirst Du Dir nie mehr wünschen prozedural zu programmieren.
Ich bin sicher das Du mit einiger Übung schnell dahinter kommst wie’s funktioniert.

Beispiel (zwinker):
Stell Dir vor Du spielst Tennis: Dann fuchtelst Du ja auch nicht mit dem Schläger rum wenn der Ball noch beim Gegner ist!
Erst beim Event “Ball kommt” reagierst Du mit einem wundervollen Return ;-))

Bitte nicht die Geduld verlieren - das kommt schon noch.