Farbenmischer(gelöst)

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
McCry
Beiträge: 42
Registriert: Mi 20. Jul 2011, 21:49
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Na Hier
Kontaktdaten:

Farbenmischer(gelöst)

Beitrag von McCry »

Hi,
mir war langweilig und da habe ich ein bisschen mit Lazarus herumexperimentiert.
Als ich auf die CheckBox gestossen bin, mit denen man mehrere Möglichkeiten ankreutzen kann,
ist mir die Idee gekommen einen Farbenmischer zu programmieren.
Zurzeit gibt es nur Blau und Gelb als mögliche Farben.
Wenn ich nun Blau auswähle erscheint Blau.
Wenn ich Gelb auswähle erscheint Gelb.
Wen ich Blau UND Gelb auswähle erscheint BLAU.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
begin
  if CheckBox1.Checked then
                        begin
                          Label1.Caption:='Blau';
                        end
                       else if CheckBox2.Checked then
                                                  begin
                                                    Label1.Caption:='Gelb';
                                                  end
                                                 else if CheckBox1.Checked and CheckBox2.Checked then
                                                                                                  begin
                                                                                                    Label1.Caption:='Grün';
                                                                                                  end
                                                                                                 else begin
                                                                                                       Label1.Caption:='Bitte eine Farbe auswählen';
 
                                                                      end;
end;
Bitte helft mir.

MFG McCry
Zuletzt geändert von McCry am Sa 13. Aug 2011, 22:01, insgesamt 1-mal geändert.

Code: Alles auswählen

Signatur[color=#FF0000]:=[/color]McCry
Website[color=#FF0000]:=[/color][color=#0000FF]ritualist.bplaced.net[/color]

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Farbenmischer

Beitrag von Scotty »

Wenn die erste Bedingung zutrifft, werden die anderen nicht mehr ausgewertet. Schreib

Code: Alles auswählen

if cb1.Checked and not cb2.Checked then
if not cb1.Checked and cb2.Checked then
if cb1.Checked and cb2.Checked then
else
Besonders schön ist so ein Code allerdings nicht.

McCry
Beiträge: 42
Registriert: Mi 20. Jul 2011, 21:49
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Na Hier
Kontaktdaten:

Re: Farbenmischer

Beitrag von McCry »

Hi Scotty,
dein Vorschlag hat echt super funktioniert.
Danke

Ich werde heute noch weitere Farben
hinzufügen. Wenns dich interessiert,
kannst du es auf meiner HP downloaden.
Bei weiteren Fragen melde ich mich.


LG McCry

Code: Alles auswählen

Signatur[color=#FF0000]:=[/color]McCry
Website[color=#FF0000]:=[/color][color=#0000FF]ritualist.bplaced.net[/color]

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Farbenmischer

Beitrag von mschnell »

Dir ist langweilig, dann mach's doch etwas kreativer. :)

Die CheckBoxen nicht "platzieren", sondern programmatisch in OnFormCreat anlegen.

Alle lösen dasselbe Event aus.

Dann kannst Du im Checkbox - Event in einer Schelfe (1 shl i) falls die Box gecheckt ist addieren und das Ergebnis anschließend als Index für ein Feld verwenden, in dem die konstanten Strings für die Farben stehen.

Viel Spaß,
-Michael

McCry
Beiträge: 42
Registriert: Mi 20. Jul 2011, 21:49
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Na Hier
Kontaktdaten:

Re: Farbenmischer

Beitrag von McCry »

Hallo Mschnell,
da ich totaler Anfänger im Gebiet
Lazarus bin (pascal kann ich schon etwas
länger) kann ich mit deinem Tipp nicht
so viel anfangen.
Trotzdem Danke



McCry

Code: Alles auswählen

Signatur[color=#FF0000]:=[/color]McCry
Website[color=#FF0000]:=[/color][color=#0000FF]ritualist.bplaced.net[/color]

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Farbenmischer

Beitrag von Socke »

McCry hat geschrieben:da ich totaler Anfänger im Gebiet Lazarus bin (pascal kann ich schon etwas länger) kann ich mit deinem Tipp nicht so viel anfangen.
Wenn ich mir die "Programme" anschaue, die ich damals in meiner Schulzeit (vor ca. 4 Jahren) gebaut habe, sind die aus meiner jetzigen Sicht auch ziemlich primitiv. Wenn man aber schon einige Jahre dabei ist, kennt man alle Tricks und vergisst leicht, dass man damit am Anfang auch noch nichts hätte anfangen können.
Mein Rat: Mach einfach mal so, wie du es für gut befindest, und schau in zwei Jahren noch mal drüber :D
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Farbenmischer

Beitrag von MAC »

oh ja, das ist immer amüsant sich allte Programme anzuschaun :D


das mschnell gemeint hat ist folgendes:

dein Programm ist im Moment ziemlich statisch.
Wenn du irgendwas ändern willst musst immer wieder eine if bedingung bei deiner abfrage hinzufügen und alle anderen abfragen um 1 teil erweitern...

Du könntest dagegen wirken in dem du z.B: Die eigenschaft "Items" der Checkgroupbox anschauen.
Damit kann man sehr einfach viele Einträge erstellen...
Es ist sogar einfach dynamisch zur Programmzeit weitere Checkboxen hinzuzufügen (ist anders auch möglich, aber nicht direkt zum start geeignet, da etwas "komplizierter"...)

Vorteil währe , du könntest alle Checkboxen in eine Schleife durchgehen und die antwort ist auch nicht statisch, sondern du gibst z.B. Weiß den wert 16777215 und schwarz 0 und rot 255...
Dann kannst du die Farben mischen lassen und eine Endfarbe anzeigen...

Code: Alles auswählen

Signatur := nil;

McCry
Beiträge: 42
Registriert: Mi 20. Jul 2011, 21:49
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Na Hier
Kontaktdaten:

Re: Farbenmischer

Beitrag von McCry »

Hi MAC,
deinen Vorschlag werde ich gleich mal ausprobieren.
Aber eins versteh ich noch nicht so ganz: wie mische ich die Farben mit Zahlen?
Wie teile ich den Farben ihre Nummer zu?


Danke schonmal,
McCry

Code: Alles auswählen

Signatur[color=#FF0000]:=[/color]McCry
Website[color=#FF0000]:=[/color][color=#0000FF]ritualist.bplaced.net[/color]

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Farbenmischer

Beitrag von MAC »

Die meisten Betriebsysteme machen das Bitweise, also 8 Bit stehen jeweils für den Rotanteil / Grünanteil / Blauanteil (/ Alphaanteil)
Kennst du vielleicht aus der Farbgebung im Internet, wo schonmal häufig so etwas auftaucht
FARBE
Was im Editor so aussieht

Code: Alles auswählen

[color=#FF0000]FARBE[/color]
die ersten 2 FF stehen im Hexadezimalsystem für 255
danach folgen 00 für den Grün und Blau anteil.
Folglich besitzt diese Farbe eine Rotanteil von 255, einen Grünanteil von 0 uznd einen Blauanteil von 0.
--> Rot

Es gibt ürigens schon einige Funktionen die dir helfen...
mit Red(integer) bekommst du z.B den Rotanteil direkt rausgefiltert.
das geht auch mit Green() und Blue()
mit RGBtoColor {evt RGBtoTColor } kannst du das ganze wieder zusammen rechnen lassen...
Oder du machst es halt selber:
Farbe := rot + grün *256 + blau *256*256

Code: Alles auswählen

Signatur := nil;

Eclipticon
Beiträge: 292
Registriert: Sa 5. Feb 2011, 20:38
OS, Lazarus, FPC: Windows XP VirtualBox (FPC 2.6.4, Laz 1.2.4)
CPU-Target: 32Bit
Wohnort: Wien

Re: Farbenmischer

Beitrag von Eclipticon »

Wobei zu bemerken waere, dass die einzelnen Bytes in TColor (wie schon aus MACs Zuweisung hervorgeht) BBGGRR angeordnet sind, nicht wie ueblich RRGGBB.

Straightdog
Beiträge: 10
Registriert: Mo 1. Aug 2011, 18:52

Re: Farbenmischer

Beitrag von Straightdog »

Wenn ich es richtig verstehe, geht es hier nicht um das Mischen von Bildschirmfarben, sondern um das Zuordnen von Farbnamen für bestimmte Mischungen einer Reihe von Grundfarben.

Ich versuche es mal etwas ausführlicher:

Du hast eine bestimmte Anzahl von Grundfarben.
Du möchtest jeder Farbmischung (d.h. jeder Kombination dieser Grundfarben) einen Namen geben.

Dein Ansatz war es, jeder Grundfarbe eine CheckBox zuzuordnen und die Namen der (Misch-)farben dann mit if-then-else zu bestimmen. Das ist ein direkter Ansatz und völlig in Ordnung, wenn man wenige (z.B. 2) Grundfarben hat. Bei 4 Grundfarben gibt es aber bereits 16 Kombinationen - und da wird die if-then-else Abfrage doch etwas unübersichtlich.

Was mschnell dir nun geraten hat, ist dies: Benutze Bits!

Das Rechnen mit Bits stammt zwar aus der Computer-Steinzeit, aber auch heute ist es recht nützlich zu wissen, wie es geht (und wenn du jemals etwas Systemnahes programmieren möchtest, dann musst du jedes Bit beim Vornamen kennen).

Ziel ist es, am Ende den Namen der (Misch-)Farbe möglichst einfach ermitteln zu können. Am besten wäre es, wir hätten für jede Farbmischung einen eindeutigen Integer-Wert, den wir dann als Index eines Arrays benutzen könnten. Also etwa

Code: Alles auswählen

var
  Farbname: array [1..n] of string = ('Farbe1', 'Farbe2', ...);
 
...
 
Label1.Caption := Farbname[Farbmischung];
Die Frage ist also diese: wie berechnen wir den Wert für Farbmischung so, dass wir ihn wie oben gezeigt verwenden können?

Die Antwort: wir ordnen jeder Grundfarbe (also jeder CheckBox) ein Bit zu:

Code: Alles auswählen

CheckBox  Bit (Binär)  Wert als Integer
1         00000001      1
2         00000010      2 
3         00000100      4 
4         00001000      8
5         00010000     16
Mischen tun wir die Grundfarben dann, indem wir ihre Werte (Bits) bitweise mit Oder verbinden. Pascal hat keinen extra-Operator für bitweises Oder, sondern nutzt - wie in Booleschen Ausdrücken - ebenfalls "or" (in C++ ist das z.B. anders, dort gibt es "||" für Boolesche Ausdrücke und "|" für bitweises Rechnen).

Wenn du jetzt einen Wert wie (binär) 00010101 hast, dann kannst du sofort sehen, dass er eine Mischung der ersten, dritten und fünften Grundfarbe repräsentiert (das Bit für die erste Grundfarbe steht ganz rechts). Und du hast auch sofort einen Integerwert, den du als Array-Index benutzen kannst, nämlich 1 + 4 + 16 = 21.

Fragt sich, wie du aus der Nummer der Checkbox schnell das zugehörige Bit berechnen kannst. Schau dir die Binärdarstellung der Bits nochmal an: die 1 wandert jedesmal eine Stelle nach links. Und genau das ist es, was der Operator shl macht: er verschiebt den Wert x um n Stellen nach links. Also:

Code: Alles auswählen

FarbBit := 1 shl (Nummer_der_CheckBox - 1);
Da wir für die erste Checkbox die Eins nicht verschieben müssen, arbeiten wir mit (Nummer_der_CheckBox - 1). 1 shl n entspricht übrigens 2 hoch n, du arbeitest hier also mit Zweierpotenzen.

Nächstes Problem: Woher bekommen wir die Nummer der Checkbox?

Viele Wege führen nach Rom. Am flexibelsten ist es, ein Checkbox-Array anzulegen (der Index der Checkbox in diesem Array ist ihre Nummer) und die Checkboxen dann zur Laufzeit zu erzeugen:

Code: Alles auswählen

const 
  Grundfarben = 4;
 
type
 
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
  public
    Checkboxen: array [1..Grundfarben] of TCheckBox;
  end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  for i := 1 to Grundfarben do  
  begin
    Checkboxen[i] := TCheckBox.Create(self); 
    with Checkboxen[i] do
    begin
      Caption := '...';
      Width := ...;
      Height := ...;
      Left := ...;
      Top := ...;
      ...
    end;
  end;
  ...
end;

Dies hat einen Hauptvorteil: Flexibilität. Und einen Hauptnachteil: du siehst die Checkboxen erst, wenn das Programm läuft. Im Lazarus Formular-Designer bleiben sie unsichtbar und du kannst sie nicht beschriften, positionieren, usw. Darum würde ich, wenn die Anzahl der Grundfarben feststeht, eher einen anderen Weg gehen:

Bau dein Formular ganz normal auf und lass Lazarus die Namen der Checkboxen automatisch vergeben. Du erhältst dann CheckBox1, CheckBox2, CheckBox3, usw. - deine Checkboxen haben also eine Nummer im Namen. Und diese Nummer benutzen wir, mit Hilfe der Methode FindComponent:

Code: Alles auswählen

GesuchteCheckbox := FindComponent('CheckBox' + IntToStr(Nummer_der_Checkbox));
Zuletzt bleibt noch die Frage, wie du das Array mit den Farbnamen aufbauen musst. Zunächsteinmal, wie groß muss es sein? Naja, du hast 2 hoch n Möglichkeiten, n Grundfarben zu mischen. Und wie wir 2 hoch n berechnen, wissen wir ja schon (shl). Wir fangen das Array bei Null an, denn auch "keine Grundfarbe" ist eine mögliche Farbmischung. Also:

Code: Alles auswählen

const
  Grundfarben = 4;
 
  Farbname: array [0..(1 shl Grundfarben)-1] of string = (
    'Keine Farbe',           // 0000
    'Grundfarbe 1',          // 0001
    'Grundfarbe 2',          // 0010
    'Mischfarbe (2+1)',      // 0011
    'Grundfarbe 3',          // 0100
    'Mischfarbe (3+1)',      // 0101
    'Mischfarbe (3+2)',      // 0110
    'Mischfarbe (3+2+1)',    // 0111
    'Grundfarbe 4',          // 1000
    'Mischfarbe (4+1)',      // 1001
    'Mischfarbe (4+2)',      // 1010
    'Mischfarbe (4+2+1)',    // 1011
    'Mischfarbe (4+3)',      // 1100
    'Mischfarbe (4+3+1)',    // 1101
    'Mischfarbe (4+3+2)',    // 1110
    'Mischfarbe (4+3+2+1)'); // 1111
Zuletzt noch - als Beispiel - eine Funktion, die den Namen der Mischfarbe liefert:

Code: Alles auswählen

function TForm1.BerechneFarbnamen: string;
var
  i: Integer;
  Mischfarbe: Integer;
begin
  Farbwert := 0;
  for i := 1 to Grundfarben do
    if (FindComponent('CheckBox' + IntToStr(i)) as TCheckBox).Checked then
      Farbwert := Farbwert or (1 shl (i-1));  
  Result := Farbname[Farbwert];
end;
PS: alles ungetestet und ohne Gewähr

Antworten