Java – pokročilá grafika (Area, BasicStroke, GradientPaint)
Poté, co se podrobněji podíváme na třídu Area, budeme se zabývat především kreslením různými pery a štětci. Seznámíme se s třídou BasicStroke, která slouží k vytváření nových per, a s třídou GradientPaint, která umožňuje vytvářet štětce barevných přechodů.
Area
Třída Area, jak bylo uvedeno v předchozím článku, umožňuje pracovat s uzavřenými oblastmi a provádět s nimi různé operace.
Třída Area obsahuje dva konstruktory – Area()
a Area(Shape s)
. Při použití bezparametrického konstruktoru Area() dostáváme prázdnou oblast, do níž můžeme další tvary přidávat pomocí metody add
. Konstruktor Area(Shape s)
přebírá jako parametr objekt Shape, podle něhož objekt Area vytvoří. Pokud objekt Shape předávaný konstruktoru Area(Shape s)
reprezentuje otevřený tvar, uzavře se automaticky.
Nezbytnými metodami pro operace s oblastmi jsou subtract(Area a)
, intersect(Area a)
, add(Area a)
a exclusiveOr(Area a)
. Vyjádřeno v množinové terminologii je metoda subtract odčítáním, metoda intersect průnikem, metoda add sjednocením a metoda exclusiveOr je logickou operací XOR. Jak vypadá výsledek použití těchto metod můžete vidět na následujícím obrázku:
K užitečným metodám patří také metoda createTransformedArea(AffineTransform af)
, která vrací nový objekt Area, vytvořený transformací daného objektu Area pomocí objektu AffineTransform af
.
Třída Area obsahuje i několik metod sloužících k dotazování se na povahu tvaru, který reprezentuje. Metoda isEmpty()
vrací true, pokud objekt Area neobsahuje žádný geometrický tvar. Metoda isRectangular()
zjišťuje, zda je reprezentovaný tvar obdélníkem, a analogicky metoda isPolygonal()
zjišťuje, zda je reprezentovaný tvar mnohoúhelníkem. Metoda isSingular()
vrací true, pokud je hranice oblasti spojitá, tzn. v jejím objektu PathIterator (viz předchozí článek) je použita hodnota SEG_MOVETO pouze jednou.
Kreslení různými pery
K nastavení stylu pera slouží v Javě metoda setStroke(Stroke s)
třídy Graphics2D, která jako parametr přebírá instanci třídy implementující rozhraní Stroke. Toto rozhraní není pro naše potřeby nikterak zajímavé, neboť vše potřebné nám poskytuje třída BasicStroke. (Navíc rozhraní Stroke definuje pouze jedinou metodu – public Shape createStrokedShape(Shape s))
.
Prakticky jediné, co ze třídy BasicStroke využijeme, je její konstruktor, jehož pět variant shrnuje tento výpis:
BasicStroke()
BasicStroke(float width)
BasicStroke(float width, int cap, int join)
BasicStroke(float width, int cap, int join, float miterlimit)
BasicStroke(float width, int cap, int join, float miterlimit, float[] dash, float dash_phase)
Bezparametrický konstruktor BasicStroke() vytváří pero o šířce jednoho bodu, se standardními hodnotami zbývajících atributů (viz dále). Konstruktor BasicStroke(float width)
vytváří pero se šířkou rovnou width a zbývajícími atributy rovnými standardním hodnotám. Konstruktor BasicStroke(float width, int cap, int join)
přidává k předchozímu ještě styly zakončení čar a styly spojení mezi jednotlivými navazujícími čarami. Hodnota cap určuje styl zakončení a může nabývat jedné z hodnot CAP_BUTT, CAP_ROUND a CAP_SQUARE definovaných ve třídě BasicStroke. Výsledek jejich použití můžete vidět na následujícím obrázku:
Stejně jako parametr cap i parametr join určující styl spojení jednotlivých čar může nabývat tří různých hodnot: JOIN_BEVEL, JOIN_MITER a JOIN_ROUND. Jak vypadá výsledek jejich použití, je opět patrné z obrázku:
Parametr miterlimit se používá pouze ve spojení s hodnotou JOIN_MITER parametru join a určuje, za jakých podmínek bude spojení čar zakončeno oseknutím, jako je tomu při použití hodnoty JOIN_BEVEL, a kdy naopak bude spojení ostré, jak je to možné vidět u hodnoty JOIN_MITER na obrázku. Pokud je poměr vzdálenosti vnitřního a vnějšího vrcholu spojení ku šířce pera větší než hodnota miterlimit, dojde k oseknutí, jinak bude realizována druhá z výše uvedených možností (ostré zakončení). To je velice užitečné, protože při velmi malých hodnotách úhlu svíraného spojovanými čárami by se nám spojení začalo protahovat k nekonečnu (minimálně někam mimo obrazovku).
A konečně se dostáváme k poslednímu konstruktoru třídy BasicStroke, kterému se vedle již zmíněných parametrů předávají další dva. Tento konstruktor slouží k vytváření čárkovaných, tečkovaných a jinak přerušovaných čar. Hodnoty uložené v tomto poli určují délku jednotlivých vykreslovaných a nevykreslovaných úseků v pořadí, jak jdou za sebou. Hodnota dash_phase pak určuje, kdy se má začít s vykreslováním přerušovaných úseků.
Vytvoření a nastavení pera šířky 5, které bude vykreslovat čárkované čáry s vykreslovanou částí délky 20 a mezerou délky 10, se spojením JOIN_MITER (miterlimit=10) a zakončením CAP_ROUND, bude vypadat následovně:
//…
float dash[] = {20,10};
BasicStroke bs2 = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER, 10, dash, 0);
//…
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D)g;
G2.setStroke(bs);
//…
}
//…
Ještě nám zbývá povědět si, jaké jsou hodnoty jednotlivých atributů pera vytvořeného voláním konstruktoru BasicStroke(float width). Jsou to JOIN_MITER jako styl spojení s hodnotou miterlimit rovnou 10 a CAP_SQUARE pro zakončení.
GradientPaint
Kromě nastavování per umožňuje třída Graphics2D rovněž nastavovat různé štětce (štětcem v tomto případě rozumíme způsob, jakým je volena barva jednotlivých bodů). K nastavení štětce slouží metoda setPaint(Paint p)
třídy Graphics2D, která jako parametr přebírá instanci třídy implementující rozhraní Paint, například Color, TexturePaint nebo GradientPaint.
Třída GradientPaint vytváří štětec, pomocí něhož můžeme vykreslovat barevné přechody. Opět ve většině případů využijeme pouze její konstruktor. Tentokrát se nebudeme zabývat všemi konstruktory, protože se od sebe liší jen způsobem předávání parametrů (Point2D nebo dvě souřadnice bodu atd.).
Konstruktor této třídy je GradientPaint(float x1, float y1, Color color1, float x2, float y2, Color color2, boolean cyclic)
. Parametry x1, y1 a x2, y2 jsou souřadnice prvního a druhého řídícího bodu. Řídící body určují úsečku, na které se postupně mění barva z color1 (na prvním řídícím bodu) na color2 (na druhém řídícím bodu). Pokud je parametr cyclic roven true, pak se na prodloužení této úsečky osově promítnou body úsečky a s takto vzniklou novou úsečkou se provede totéž. Pokud je naopak parametr cyclic roven false, mají body na prodloužení této úsečky barvu bližšího řídícího bodu. Ostatní body jsou určeny barvou bodu ležícího na přímce dané řídícími body, který leží na kolmici k této přímce vedené bodem, jehož barva nás zajímá.
Výsledek použití následujících konstruktorů ukazuje obrázek níže:
//…
//vytvoření objektu GradientPaint pro levý obrázek
GradientPaint gr = new GradientPaint(0,0,Color.red,100,0,Color.green,true);
//vytvoření objektu GradientPaint pro pravý obrázek – zatím jako komentář
//GradientPaint gr = new GradientPaint(0,0,Color.red,100,0,Color.green,false);
//…
//V metodě paint pak nastavíte štětec takto:
g2.setPaint(gr);
//…
K vytváření nových štětců slouží ještě třída TexturePaint, se kterou se seznámíme v příštím článku, který bude z velké části postaven na obsáhlejším příkladu použití dosud popsaných technik.
Mohlo by vás také zajímat
-
10 nejpopulárnějších programovacích jazyků a jejich využití
9. listopadu 2023 -
AI v programování: Jak používat GitHub Copilot (část 1)
12. února 2024 -
Členská sekce: 4 důvody proč ji mít na svém webu
12. března 2024 -
Od iPhonu po Android: Ultra HDR přináší nový standard fotografií
1. listopadu 2024
Nejnovější
-
Jak rozšířit úložiště Macu za pětinovou cenu?
16. prosince 2024 -
Nové trendy v doménách pro osobní projekty – DIY, LIVING a LIFESTYLE
9. prosince 2024 -
Jak chránit webové stránky před Web/AI Scrapingem
27. listopadu 2024 -
Jaký monitor je nejlepší k novému Macu Mini?
25. listopadu 2024