Kolory i pędzle
W XAML wpisujesz po prostu Background="Red". W C# taki zapis się nie skompiluje — bo kolor tła to nie tekst, tylko pędzel. Poznasz zapis kolorów nazwą i kodem szesnastkowym, gotowe pędzle z klasy Brushes, kolory składane z czerwieni, zieleni i niebieskiego oraz gradient w kodzie. Zadania egzaminacyjne bardzo często wymagają zmiany koloru po kliknięciu — po tej lekcji zrobisz to bez szukania w internecie.
Czego się dziś nauczysz
- Zapiszesz kolor w XAML nazwą oraz w postaci
#RRGGBBi#AARRGGBB. - Odróżnisz kolor (
Color) od pędzla (Brush). - Zmienisz kolor tekstu i tła z kodu za pomocą
Brushes. - Złożysz własny kolor z trzech składowych przez
Color.FromRgbiSolidColorBrush. - Sprawdzisz w kodzie, jaki kolor ma kontrolka.
- Utworzysz gradient w C#.
Kolor to nie tekst
Komunikat.Foreground = "Red"; // ✗ CS0029: Cannot implicitly convert type 'string' to 'Brush'
Właściwości Foreground i Background mają typ Brush — pędzel, czyli „czym malować”. Pędzel może malować jednym kolorem, gradientem albo nawet obrazkiem. XAML zamienia tekst "Red" na pędzel sam; w C# musisz podać gotowy obiekt pędzla.
| Pojęcie | Typ w C# | Co to jest |
|---|---|---|
| kolor | Color | sama wartość: ile czerwieni, zieleni, niebieskiego i przezroczystości |
| pędzel jednolity | SolidColorBrush | maluje jednym kolorem |
| pędzel z gradientem | LinearGradientBrush | maluje przejściem kolorów (lekcja 02) |
| gotowe pędzle | Brushes.Red, Brushes.Gold… | jednolite pędzle dla wszystkich nazwanych kolorów |
Wszystkie te klasy są w przestrzeni nazw System.Windows.Media. Dopisz na górze pliku using System.Windows.Media;.
Kolory w XAML
| Zapis | Przykład | Znaczenie |
|---|---|---|
| nazwa | Tomato, SteelBlue | ponad 140 nazwanych kolorów; edytor je podpowiada |
#RRGGBB | #FF8000 | czerwony FF (255), zielony 80 (128), niebieski 00 — pomarańczowy |
#AARRGGBB | #80FF8000 | pierwsza para to alfa — nieprzezroczystość: FF pełna, 80 połowa, 00 niewidoczny |
Transparent | Background="Transparent" | całkowicie przezroczysty |
kod szesnastkowy: każda para cyfr to liczba 0–255
Jak czytać kod szesnastkowy
Cyfry szesnastkowe to 0–9 i A–F (A = 10 … F = 15). Para FF to 15 · 16 + 15 = 255, 80 to 8 · 16 = 128. W C# liczbę w tym zapisie wypiszesz formatem X2: $"{255:X2}" daje FF.
Gotowe pędzle: Brushes
Dla każdego nazwanego koloru klasa Brushes ma gotowy pędzel. To najprostszy sposób zmiany koloru z kodu:
// na górze pliku: using System.Windows.Media;
Komunikat.Foreground = Brushes.Red; // kolor tekstu napisu
Komunikat.Background = Brushes.LightYellow;
Background = Brushes.WhiteSmoke; // tło okna (bez nazwy przed kropką)
Start.Background = Brushes.LightGreen; // tło przycisku
Pędzel można też przepisać z jednej kontrolki na drugą: Background = przycisk.Background; ustawi tło okna na takie samo, jakie ma kliknięty przycisk.
Kolor z liczb: Color.FromRgb
Gdy kolor wynika z obliczeń (np. temperatura, wynik testu), składasz go z trzech liczb 0–255 i tworzysz z niego pędzel:
Color pomaranczowy = Color.FromRgb(255, 128, 0); // R, G, B
Komunikat.Background = new SolidColorBrush(pomaranczowy);
Color polprzezroczysty = Color.FromArgb(128, 255, 128, 0); // A, R, G, B
Komunikat.Background = new SolidColorBrush(polprzezroczysty);
Składowe mają typ byte
Color.FromRgb przyjmuje liczby typu byte (0–255). Gdy masz zmienne int, rzutuj je: Color.FromRgb((byte)r, (byte)g, (byte)b) — ale najpierw sprawdź, że mieszczą się w zakresie. Rzutowanie 300 na byte nie zgłosi błędu, tylko da 44 (300 − 256).
Porównywanie kolorów
Często trzeba sprawdzić „czy pole jest już czerwone”. Pędzle z Brushes to zawsze te same obiekty, więc porównanie działa:
if (Pole.Background == Brushes.Red) // ✓ działa, gdy kolor ustawiono przez Brushes.Red
{
Pole.Background = Brushes.Green;
}
Ale dwa nowe pędzle tego samego koloru to dwa różne obiekty — porównanie da false. Wtedy porównuj kolory, a nie pędzle — albo, co zwykle jest prostsze, trzymaj stan w polu klasy (np. bool zaznaczone), a kolor traktuj tylko jako jego obraz.
Gradient w kodzie
Gradient z lekcji 02 utworzysz też w C# — przyda się, gdy kolory mają zależeć od danych:
// pionowy gradient: z góry (kolor 1) na dół (kolor 2)
Background = new LinearGradientBrush(Colors.LightSkyBlue, Colors.White, 90);
Trzeci parametr to kąt w stopniach: 0 — od lewej do prawej, 90 — z góry na dół. Zwróć uwagę: tu potrzebne są kolory (Colors.LightSkyBlue, typ Color), a nie pędzle (Brushes).
Mieszalnik kolorów RGB
Program składa kolor z trzech składowych. Przyciski − i + zmieniają czerwony, zielony i niebieski o 32. Podgląd pokazuje kolor i jego kod szesnastkowy, a napis w podglądzie sam zmienia się na biały, gdy tło jest ciemne. Wszystkie sześć przycisków obsługuje jedna metoda — co zmienić, mówi jej Tag.
po trzech kliknięciach „+” przy czerwonym i dwóch „−” przy niebieskim
<Window x:Class="Lekcja06.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Mieszalnik kolorów" Height="420" Width="380"
ResizeMode="CanMinimize"
WindowStartupLocation="CenterScreen">
<StackPanel Margin="15">
<!-- Podgląd: tło i kolor tekstu ustawia kod -->
<TextBlock x:Name="Podglad" Text="Twój kolor" Height="110"
FontSize="22" FontWeight="Bold"
TextAlignment="Center" Padding="0,38,0,0"/>
<TextBlock x:Name="Kod" FontSize="20" FontFamily="Consolas"
TextAlignment="Center" Margin="0,10,0,12"/>
<!-- Trzy wiersze: nazwa składowej, przyciski −/+ i wartość.
Tag mówi metodzie, którą składową i w którą stronę zmienić. -->
<StackPanel Orientation="Horizontal" Margin="0,0,0,6">
<TextBlock Text="Czerwony" Width="90" Foreground="DarkRed" FontWeight="Bold" VerticalAlignment="Center"/>
<Button Content="−" Width="40" Tag="R-" Click="Zmien_Click"/>
<TextBlock x:Name="WartoscR" Width="50" TextAlignment="Center" VerticalAlignment="Center"/>
<Button Content="+" Width="40" Tag="R+" Click="Zmien_Click"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,6">
<TextBlock Text="Zielony" Width="90" Foreground="DarkGreen" FontWeight="Bold" VerticalAlignment="Center"/>
<Button Content="−" Width="40" Tag="G-" Click="Zmien_Click"/>
<TextBlock x:Name="WartoscG" Width="50" TextAlignment="Center" VerticalAlignment="Center"/>
<Button Content="+" Width="40" Tag="G+" Click="Zmien_Click"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,12">
<TextBlock Text="Niebieski" Width="90" Foreground="DarkBlue" FontWeight="Bold" VerticalAlignment="Center"/>
<Button Content="−" Width="40" Tag="B-" Click="Zmien_Click"/>
<TextBlock x:Name="WartoscB" Width="50" TextAlignment="Center" VerticalAlignment="Center"/>
<Button Content="+" Width="40" Tag="B+" Click="Zmien_Click"/>
</StackPanel>
<Button Content="Szary (start)" Width="120" HorizontalAlignment="Left" Click="Reset_Click"/>
</StackPanel>
</Window>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Lekcja06;
public partial class MainWindow : Window
{
private const int Krok = 32;
// Składowe koloru: 0 (brak) … 255 (pełna)
private int r = 128;
private int g = 128;
private int b = 128;
public MainWindow()
{
InitializeComponent();
PokazKolor();
}
private void Zmien_Click(object sender, RoutedEventArgs e)
{
Button przycisk = (Button)sender;
string polecenie = $"{przycisk.Tag}"; // np. "R+" albo "B-"
int zmiana = Krok;
if (polecenie[1] == '-')
{
zmiana = -Krok;
}
if (polecenie[0] == 'R')
{
r = Ogranicz(r + zmiana);
}
else if (polecenie[0] == 'G')
{
g = Ogranicz(g + zmiana);
}
else
{
b = Ogranicz(b + zmiana);
}
PokazKolor();
}
private void Reset_Click(object sender, RoutedEventArgs e)
{
r = 128;
g = 128;
b = 128;
PokazKolor();
}
// Pilnuje zakresu 0–255
private int Ogranicz(int wartosc)
{
if (wartosc < 0)
{
return 0;
}
if (wartosc > 255)
{
return 255;
}
return wartosc;
}
private void PokazKolor()
{
Color kolor = Color.FromRgb((byte)r, (byte)g, (byte)b);
Podglad.Background = new SolidColorBrush(kolor);
// Na jasnym tle czarny napis, na ciemnym — biały
double jasnosc = 0.299 * r + 0.587 * g + 0.114 * b;
if (jasnosc > 128)
{
Podglad.Foreground = Brushes.Black;
}
else
{
Podglad.Foreground = Brushes.White;
}
WartoscR.Text = r.ToString();
WartoscG.Text = g.ToString();
WartoscB.Text = b.ToString();
Kod.Text = $"#{r:X2}{g:X2}{b:X2}";
}
}
Co dzieje się po kolei
- Składowe koloru są w polach
r,g,btypuint, startują od 128 — to szary. Konstruktor od razu wołaPokazKolor(), żeby podgląd i liczby były wypełnione. - Każdy z sześciu przycisków ma w
Tagdwuznakowe polecenie, np.R+alboB-. Pierwszy znak mówi, którą składową zmienić, drugi — w którą stronę. $"{przycisk.Tag}"zamieniaTagna tekst, apolecenie[0]ipolecenie[1]to pojedyncze znaki (char) — dlatego porównujemy je z'R'i'-'w apostrofach.Ograniczpilnuje zakresu 0–255. Od 128 w górę kolejne wartości to 160, 192, 224 i 255 (256 zostało przycięte).- W
PokazKolorwartościintsą rzutowane nabyte— bezpiecznie, bo zakres pilnujeOgranicz. Z koloru powstaje nowySolidColorBrush. - Jasność liczymy wzorem, który uwzględnia, że oko najmocniej reaguje na zieleń. Na jasnym tle napis jest czarny (
Brushes.Black), na ciemnym — biały. {r:X2}zapisuje liczbę szesnastkowo na dwóch znakach: 224 →E0, 64 →40.
Sprawdź trzy rzeczy
- Ustaw wszystkie składowe na 0, a potem na 255. Kod pokaże
#000000i#FFFFFF, a napis w podglądzie zmieni kolor. - Usuń wywołanie
Ograniczprzy czerwonym i klikaj „+”. Po przekroczeniu 255 kolor nagle zrobi się ciemny — rzutowanie nabyte„przekręca” liczbę. - Zmień jeden
Tagna"X+". Przycisk zacznie zmieniać niebieski — trafi do ostatniegoelse. W komentarzu zaproponuj, jak się przed tym zabezpieczyć.
Zestawienie elementów
| Element | Znaczenie | Uwagi |
|---|---|---|
Brush | pędzel | Typ właściwości Foreground i Background. |
Brushes.Red | gotowy pędzel jednolity | Dla każdego nazwanego koloru. Zawsze ten sam obiekt. |
Color | wartość koloru | Składowe A, R, G, B typu byte. |
Colors.Red | gotowy kolor | Typ Color, nie pędzel. |
Color.FromRgb(r, g, b) | kolor z trzech liczb | Każda 0–255. |
Color.FromArgb(a, r, g, b) | kolor z przezroczystością | a = 255 — pełny, 0 — niewidoczny. |
new SolidColorBrush(kolor) | pędzel z koloru | Każde new to nowy obiekt. |
new LinearGradientBrush(k1, k2, kąt) | gradient w kodzie | Kąt 0 — poziomo, 90 — pionowo. |
#RRGGBB, #AARRGGBB | kod koloru w XAML | Pary cyfr szesnastkowych. |
{liczba:X2} | liczba szesnastkowo | Dwa znaki, wielkie litery. |
(byte)liczba | rzutowanie na 0–255 | Bez sprawdzenia zakresu „przekręca” wartość. |
Zanim utkniesz
| Zapis | Problem |
|---|---|
Napis.Foreground = "Red"; | CS0029 — w C# potrzebny pędzel: Brushes.Red. |
Napis.Foreground = Colors.Red; | CS0029 — Colors daje kolor, a właściwość wymaga pędzla. Użyj Brushes.Red albo new SolidColorBrush(Colors.Red). |
brak using System.Windows.Media; | CS0103: The name 'Brushes’ does not exist in the current context. |
Color.FromRgb(r, g, b) ze zmiennymi int | CS1503 — potrzebne rzutowanie na byte. |
(byte)r, gdy r wynosi 300 | Wynik 44 bez żadnego błędu — sprawdzaj zakres przed rzutowaniem. |
Pole.Background == new SolidColorBrush(Colors.Red) | Zawsze false — dwa różne obiekty pędzla. |
Background="#FF80" | Za mało cyfr. Kod ma 3, 6 albo 8 cyfr: #F80, #FF8800, #FFFF8800. |
alfa na końcu: #FF800080 zamiast #80FF8000 | W WPF przezroczystość jest pierwszą parą, nie ostatnią (inaczej niż w CSS). |
Zadania
Każde zadanie wykonaj w nowym projekcie Aplikacja WPF. Wskazówkę otwórz dopiero wtedy, gdy utkniesz.
Okno ma duży napis (rozmiar 40, wyśrodkowany, z wewnętrznym odstępem 20) i trzy przyciski: Czerwone, Żółte, Zielone. Każdy ustawia tło napisu na odpowiedni kolor i tekst: „STÓJ”, „UWAGA”, „IDŹ”. Na żółtym tle tekst ma być czarny, na pozostałych — biały. Wszystkie trzy przyciski obsługuje jedna metoda.
pokaż wskazówkę
- Przyciski rozpoznasz porównaniem
senderz ich nazwami. - Najpierw ustaw kolor tekstu na biały dla wszystkich, a w gałęzi „żółte” zmień go na czarny.
Szkoła ma kolory identyfikacji: #1F3A93, #F2C14E, #2E8B57, #C0392B, #7F8C8D. Zrób rząd pięciu przycisków, których tło ma te kolory (ustawione w XAML), a napisem jest kod koloru. Kliknięcie przycisku ustawia na ten sam kolor tło okna i wypisuje „Wybrano: #F2C14E”. Jedna metoda dla wszystkich, bez żadnego if.
pokaż wskazówkę
- Pędzel możesz przepisać wprost: tło okna = tło klikniętego przycisku.
- Kod koloru jest już w
Contentprzycisku.
Okno pokazuje temperaturę, np. „12 °C — chłodno”, i przyciski −5, −1, +1, +5. Zakres od −20 do 40 °C. Kolor napisu zależy od temperatury: poniżej 0 — niebieski („mróz”), 0–15 — zielony („chłodno”), 16–25 — pomarańczowy („przyjemnie”), powyżej 25 — czerwony („upał”). Wszystkie cztery przyciski obsługuje jedna metoda, a wartość zmiany jest w Tag. W komentarzu wypisz temperatury, którymi sprawdziłeś granice przedziałów.
pokaż wskazówkę
Tagmoże zawierać liczbę ujemną, np."-5"—int.Parsesobie z nią poradzi.- Kolor i opis wybierz w jednej metodzie odświeżającej łańcuchem
if / else if.
Okno ma ciemne tło (#202020) i duży napis-„lampkę” (np. 200 × 200, tekst „💡” albo „LAMPA”). Przyciski Ciemniej i Jaśniej zmieniają przezroczystość żółtego tła lampki w 5 krokach: 0 %, 25 %, 50 %, 75 %, 100 %. Napis „Jasność: 50%” pokazuje stan, a przyciski na granicach zakresu stają się nieaktywne. Kolor buduj przez Color.FromArgb.
pokaż wskazówkę
- Trzymaj w polu numer poziomu 0–4, a alfę licz z niego: poziom · 255 / 4.
- Pamiętaj o rzutowaniu na
byte.
Okno ma pionowy gradient tła i przyciski Świt, Południe, Zachód, Noc. Każdy ustawia w kodzie inny gradient (np. świt: Pink → LightSkyBlue, noc: MidnightBlue → Black) oraz kolor napisu z nazwą pory dnia tak, żeby był czytelny. Przy starcie okno ustawia porę na podstawie aktualnej godziny.
pokaż wskazówkę
- Gradient w kodzie:
new LinearGradientBrush(kolor1, kolor2, 90)z kolorami zColors. - Napisz metodę z parametrem (np. numerem pory), którą wywołasz z przycisków i z konstruktora.
Okno pokazuje obok siebie dwa duże pola: cel (kolor ustalony w kodzie, np. 153, 204, 51) i Twój kolor. Gracz ustawia swój kolor przyciskami −/+ dla R, G i B (krok 51, więc możliwe wartości to 0, 51, 102, 153, 204, 255). Przycisk Sprawdź liczy odległość: suma różnic składowych (wartości bezwzględne) i wypisuje „Gorąco!” (0), „Ciepło” (do 102), „Letnio” (do 255) albo „Zimno” oraz liczbę prób. Po trafieniu wypisz „Trafione w 7 próbach!” i zablokuj przyciski. Przycisk Nowa gra ustawia inny cel (z tablicy kilku przygotowanych kolorów, po kolei) i zeruje próby.
pokaż wskazówkę
- Wartość bezwzględną daje
Math.Abs. - Kolory celów trzymaj w trzech tablicach (R, G, B) i polu z numerem aktualnego celu.
- Wszystkie przyciski −/+ możesz włożyć do jednego panelu i blokować go w całości.
Co trzeba zapamiętać
ForegroundiBackgroundmają typBrush— w C# podajesz pędzel, nie tekst.Brushes.Nazwa— gotowy pędzel;Colors.Nazwa— sam kolor.- Własny kolor:
new SolidColorBrush(Color.FromRgb(r, g, b)), z przezroczystością —Color.FromArgb. - W XAML: nazwa,
#RRGGBBalbo#AARRGGBB(alfa na początku). - Pędzle z
Brushesmożna porównywać; nowe pędzle — nie. Stan najlepiej trzymać w polu klasy. - Gradient w kodzie:
new LinearGradientBrush(kolor1, kolor2, kąt).
Dokumentacja: Microsoft Learn — klasa Brushes, SolidColorBrush.