Programovanie

Namapujte si cestu k komponentom vlastného grafu

Naše vlastné komponenty grafu vyžadujú ručné kreslenie, takže budeme musieť podtriedu Plátno, čo je štandardný komponent poskytovaný na priamu manipuláciu s grafikou. Technika, ktorú použijeme, bude prekonať maľovať metóda Plátno pomocou vlastnej kresby, ktorú potrebujeme. Použijeme Grafika objekt, ktorý sa automaticky odovzdá do súboru maľovať metódu všetkých komponentov, prístup k farbám a metódam kreslenia.

Vytvoríme dve vlastné komponenty grafov: stĺpcový graf a čiarový graf. Začneme zostavením všeobecnej triedy rámca pre dva grafy, ktoré zdieľajú niektoré základné prvky.

Budovanie rámca všeobecných grafov

Čiarový graf a stĺpcový graf, ktoré vytvoríme, sú si dosť podobné na to, aby sme mohli vytvoriť všeobecný údaj

Graf

triedy, aby vykonali niektoré z nudných dispozičných prác. Po dokončení môžeme triedu rozšíriť o konkrétny druh grafu, ktorý potrebujeme.

Prvá vec, ktorú musíte urobiť pri návrhu vlastných grafických komponentov, je priložiť pero k papieru a nakresliť obrázok toho, čo potrebujete. Pretože počítame pixely, je ľahké sa pomýliť s umiestnením prvkov. Ak sa zamyslíte nad pomenovaním a umiestnením prvkov, pomôže vám to udržať kód čistší a ľahšie čitateľný neskôr.

Čiarový graf a stĺpcový graf používajú rovnaké rozloženie pre nadpis a riadky, takže začneme vytvorením všeobecného grafu obsahujúceho tieto dve funkcie. Rozloženie, ktoré vytvoríme, je zobrazené na obrázku nižšie.

Na vytvorenie všeobecného Graf trieda, podtriedu Plátno. Stredná oblasť je miestom, kde sa zobrazia skutočné údaje grafu; ponecháme to na rozšírenie Graf vykonávať. Ostatné prvky - záhlavie, zvislú čiaru vľavo, vodorovnú čiaru v dolnej časti a hodnoty rozsahu - implementujeme do základnej triedy. Mohli by sme určiť typ písma a natvrdo naprogramovať merania pixelov, ale používateľ by nemohol zmeniť veľkosť grafu. Lepším prístupom je meranie prvkov oproti prúd veľkosť komponentu, takže zmena veľkosti aplikácie bude mať za následok správnu veľkosť grafu.

Tu je náš plán: Vezmeme si String titul, an int minimálna hodnota a int maximálna hodnota v konštruktore. Poskytujú nám všetky informácie, ktoré potrebujeme na zostavenie rámca. Ponecháme si štyri premenné na použitie v podtriedach - hore, dole, vľavoa správny hodnoty pre hranice oblasti kreslenia grafu. Tieto premenné použijeme na výpočet umiestnenia položiek grafu neskôr. Začnime krátkym pohľadom na Graf deklarácia triedy.

import java.awt. *; import java.util. *; public class Graph extends Canvas {// potrebné premenné public int top; verejné int dno; public int left; verejné int právo; int názovVýška; int labelWidth; FontMetrics fm; int polstrovanie = 4; Názov reťazca; int min; int max; Vektorové predmety; 

Aby sme vypočítali správne umiestnenie prvkov grafu, musíme najskôr vypočítať oblasti v našom všeobecnom rozložení grafu, ktoré tvoria rámec. Aby sme vylepšili vzhľad komponentu, pridáme k vonkajším okrajom 4-pixlovú výplň. Nadpis pridáme do stredu hore, pričom zohľadníme oblasť výplne. Aby sme sa uistili, že graf nie je nakreslený nad textom, musíme od oblasti nadpisu odpočítať výšku textu. Musíme urobiť to isté pre min a max štítky rozsahu hodnôt. Šírka tohto textu je uložená v premennej štítokŠírka. Aby sme mohli robiť merania, musíme si nechať odkaz na metriku písma. The položky vektor sa používa na sledovanie všetkých jednotlivých položiek, ktoré boli pridané do komponenty Graf. Trieda používaná na uchovávanie premenných súvisiacich s položkami grafu je zahrnutá (a vysvetlená) po Graf triedy, ktorá sa zobrazuje ďalej.

 public Graph (názov reťazca, int min, int max) {this.title = title; this.min = min; this.max = max; items = new Vector (); } // koncový konštruktor 

Konštruktor vezme nadpis grafu a rozsah hodnôt a pre jednotlivé položky grafu vytvoríme prázdny vektor.

 public void reshape (int x, int y, int width, int height) {super.reshape (x, y, width, height); fm = getFontMetrics (getFont ()); titleHeight = fm.getHeight (); labelWidth = Math.max (fm.stringWidth (nové celé číslo (min) .toString ()), fm.stringWidth (nové celé číslo (max) .toString ())) + 2; hore = výplň + titleHeight; dno = veľkosť (). výška - polstrovanie; dolava = polstrovanie + labelWidth; vpravo = veľkosť (). šírka - polstrovanie; } // ukončiť tvar 

Poznámka: V JDK 1.1 sa pretvarovať metóda je nahradená public void setBounds (Obdĺžnik r). Podrobnosti nájdete v dokumentácii k API.

Prepíšeme pretvarovať metóda, ktorá sa dedí po reťazci z Komponent trieda. The pretvarovať metóda sa volá pri zmene veľkosti komponentu a pri jeho prvom rozložení. Túto metódu používame na zhromažďovanie meraní, aby sa vždy aktualizovali, ak sa zmení veľkosť súčasti. Získame metriky písma pre aktuálne písmo a priradíme názovVýška premenná maximálna výška tohto písma. Získame maximálnu šírku štítkov, vyskúšame, ktorý z nich je väčší, a potom ich použijeme. The hore, dole, vľavoa správny premenné sa počítajú z ostatných premenných a predstavujú hranice oblasti kreslenia stredového grafu. Tieto premenné použijeme v podtriedach Graf. Upozorňujeme, že všetky merania berú do úvahy a prúd veľkosť komponentu, takže prekreslenie bude správne pri akejkoľvek veľkosti alebo aspekte. Ak by sme použili pevne napísané hodnoty, veľkosť komponentu sa nedala zmeniť.

Ďalej nakreslíme rámec pre graf.

 public void paint (Grafika g) {// nakreslite nadpis fm = getFontMetrics (getFont ()); g.drawString (title, (size (). width - fm.stringWidth (title)) / 2, hore); // nakreslite max a min hodnoty g.drawString (new Integer (min) .toString (), padding, bottom); g.drawString (nové celé číslo (max). toString (), výplň, horná časť + titleHeight); // nakreslíte zvislú a vodorovnú čiaru g.drawLine (ľavá, horná, ľavá, spodná); g.drawLine (vľavo, dole, vpravo, dole); } // koncová farba 

Rámec je zakreslený v maľovať metóda. Nadpis a štítky nakreslíme na príslušné miesta. Na ľavom okraji oblasti na kreslenie grafu nakreslíme zvislú čiaru a na spodnom okraji vodorovnú čiaru.

V tomto ďalšom úryvku sme nastavili preferovanú veľkosť komponentu prepísaním preferovaná veľkosť metóda. The preferovaná veľkosť metóda sa tiež dedí z Komponent trieda. Komponenty môžu určiť preferovanú veľkosť a minimálnu veľkosť. Vybral som preferovanú šírku 300 a preferovanú výšku 200. Správca rozloženia túto metódu zavolá, keď rozloží komponent.

 public Dimension preferredSize () {return (new Dimension (300, 200)); }} // koniec grafu 

Poznámka: V JDK 1.1 sa preferovaná veľkosť metóda je nahradená verejná dimenzia getPreferredSize ().

Ďalej potrebujeme zariadenie na pridávanie a odstraňovanie položiek, ktoré sa majú zobraziť v grafe.

 public void addItem (názov reťazca, int hodnota, Colour col) {items.addElement (new GraphItem (name, value, col)); } // end addItem public void addItem (Názov reťazca, int hodnota) {items.addElement (new GraphItem (name, value, Color.black)); } // end addItem public void removeItem (String name) {for (int i = 0; i <items.size (); i ++) {if (((GraphItem) items.elementAt (i)). title.equals (name )) items.removeElementAt (i); }} // koniec removeItem} // koniec grafu 

Vymodeloval som pridať položku a Odstrániť položku metódy po podobných metódach v Voľba triedy, takže kód bude mať známy pocit. Všimnite si, že používame dva pridať položku metódy tu; potrebujeme spôsob, ako pridať položky s farbou alebo bez farby. Po pridaní položky nová GraphItem objekt sa vytvorí a pridá do vektora položiek. Po odstránení položky sa odstráni prvá vo vektore s týmto názvom. The GraphItem trieda je veľmi jednoduchá; tu je kód:

import java.awt. *; trieda GraphItem {názov reťazca; hodnota int; Farba farby; public GraphItem (názov reťazca, hodnota int, farba farby) {this.title = title; this.value = value; this.color = farba; } // koncový konštruktor} // koniec GraphItem 

The GraphItem trieda slúži ako držiteľ premenných týkajúcich sa položiek grafu. Zahrnul som Farba tu pre prípad, že sa použije v podtriede Graf.

Keď je tento rámec zavedený, môžeme vytvárať rozšírenia na prácu s každým typom grafov. Táto stratégia je celkom pohodlná; nemusíme ísť znova do problémov s meraním pixelov pre framework a môžeme vytvárať podtriedy, ktoré sa zameriavajú na vyplnenie oblasti kreslenia grafu.

Vytvorenie stĺpcového grafu

Teraz, keď máme grafický rámec, môžeme ho prispôsobiť rozšírením

Graf

a implementácia vlastného kreslenia. Začneme jednoduchým stĺpcovým grafom, ktorý môžeme použiť rovnako ako akýkoľvek iný komponent. Typický stĺpcový graf je znázornený nižšie. Vyplníme oblasť kreslenia grafu prepísaním

maľovať

metóda volania nadtriedy

maľovať

metódou (nakresliť rámec), potom vykonáme vlastnú kresbu potrebnú pre tento typ grafu.

import java.awt. *; verejná trieda BarChart rozširuje Graph {int pozíciu; prírastok int; public BarChart (Názov reťazca, int min, int max) {super (názov, min, max); } // koncový konštruktor 

Aby sme rovnomerne rozmiestnili položky, ponecháme si prírastok premenná na označenie sumy, ktorú pre každú položku posunieme doprava. Premenná polohy je aktuálna poloha a hodnota prírastku sa k nej pridáva zakaždým. Konštruktor jednoducho vezme hodnoty pre superkonštruktor (Graf), ktorý voláme výslovne.

Teraz sa môžeme pustiť do niektorých skutočných kresieb.

 public void paint (Grafika g) {super.paint (g); prírastok = (vpravo - vľavo) / (items.size ()); pozícia = vľavo; Farebná teplota = g.getColor (); pre (int i = 0; i <items.size (); i ++) {GraphItem item = (GraphItem) items.elementAt (i); int adjustValue = bottom - (((item.value - min) * (bottom - top)) / (max - min)); g.drawString (item.title, position + (increment - fm.stringWidth (item.title)) / 2, adjustValue - 2); g.setColor (item.color); g.fillRect (poloha, upravená hodnota, prírastok, spodná - upravená hodnota); poloha + = prírastok; g.setColor (teplota); }} // koniec farby} // koniec BarChart 

Pozrime sa podrobne na to, čo sa tu deje. V maľovať metóda, hovoríme nadtrieda maľovať metóda na vykreslenie rámca grafov. Potom nájdeme prírastok odčítaním pravého okraja od ľavého okraja a následným vydelením výsledku počtom položiek. Táto hodnota predstavuje vzdialenosť medzi ľavými okrajmi položiek grafu. Pretože chceme, aby bolo možné zmeniť veľkosť grafu, zakladáme tieto hodnoty na aktuálnej hodnote parametra vľavo a správny premenné zdedené z Graf. Pripomeňme, že vľavo, správny, horea dole hodnoty sú súčasné skutočné merania pixelov oblasti kreslenia grafu vykonané v pretvarovať metóda Graf, a preto sú k dispozícii pre naše použitie. Ak by sme svoje merania nezakladali na týchto hodnotách, graf by nebol zmeniteľný.

Obdĺžniky nakreslíme farbou, ktorú určuje znak GraphItem. Aby sme sa mohli vrátiť k pôvodnej farbe, nastavili sme dočasnú farbu farba premenná, ktorá drží aktuálnu hodnotu skôr, ako ju zmeníme. Cyklicky prechádzame vektorom položiek grafu, pričom pre každú vypočítame upravenú vertikálnu hodnotu, nakreslíme nadpis položky a vyplnený obdĺžnik predstavujúci jej hodnotu. Prírastok sa vždy pridá do premennej polohy x prostredníctvom slučky.

Upravená vertikálna hodnota zaisťuje, že ak sa komponent roztiahne vertikálne, graf zostane verný svojim vykresleným hodnotám. Aby sme to dosiahli správne, musíme vziať percento rozsahu, ktoré položka predstavuje, a túto hodnotu vynásobiť skutočným rozsahom pixelov v oblasti kreslenia grafu. Výsledok potom odpočítame od dole hodnotu na správne vykreslenie bodu.

Ako môžete vidieť na nasledujúcom diagrame, celková veľkosť vodorovných pixelov je vyjadrená symbolom pravá ľavá a celková vertikálna veľkosť je vyjadrená dole - hore.

O vodorovné natiahnutie sa postaráme inicializáciou pozíciu premenná k ľavému okraju a zvyšuje ju o prírastok premenná pre každú položku. Pretože pozíciu a prírastok premenné závisia od aktuálnych aktuálnych hodnôt pixelov, veľkosť komponentu sa vždy správne zmení v horizontálnom smere.

Aby sme zaistili, že vertikálne vykreslenie je vždy správne, musíme mapovať hodnoty položiek grafu so skutočnými umiestneniami pixelov. Existuje jedna komplikácia: max a min hodnoty by mali mať význam pre pozíciu hodnoty položky grafu. Inými slovami, ak sa graf začína na 150 a ide na 200, položka s hodnotou 175 by sa mala objaviť v polovici vertikálnej osi. Aby sme to dosiahli, nájdeme percento rozsahu grafu, ktoré položka predstavuje, a vynásobíme ho skutočným rozsahom pixelov. Pretože náš graf je obrátený od súradnicového systému grafického kontextu, od tohto čísla odčítame dole nájsť správny bod vykreslenia. Pamätajte, že počiatok (0,0) je v ľavom hornom rohu kódu, ale v ľavom dolnom rohu pre štýl grafu, ktorý vytvárame.

$config[zx-auto] not found$config[zx-overlay] not found