Table of Contents
Další druhy panelů
Základní třída pro pohyblivé panely
V programu z minulého týdnu jsem upravil třídu Area tak,
aby zadanému panelu přidala kód pro pohyb pomocí myši
Třídy pro jednotlivé panely jsou ozdvozené ze třídy UserControl
( Když byly odvozené ze třídy Area,
která někdy ještě nemusela být přeložena,
tak VisualStudio nemohlo zobrazit panel v “design” režimu. )
Nyní třídy pro jednotlivé panely v konstruktoru zavolají new Area (this);
třída Area připojí své metody jako reakci na pohyb myši nad příslušným panelem.
Pohyb panelu pomocí levého tlačítka myši
a zvětšování pomocí prostředního tlačítka
u některých panelů funguje jen na barevném okraji panelu,
uvnitř je umístěn jiný grafický prvek jako např. takulka s daty.
Samotná třída Area není odvozena z vizuálního prvku.
public class Area { private Control control; public Area (Control control0) { control = control0; control.MouseDown += Area_MouseDown; control.MouseMove += Area_MouseMove; control.MouseUp += Area_MouseUp; } private int X0, Y0; private bool press = false; private void Area_MouseDown (object sender, MouseEventArgs e) { X0 = e.X; Y0 = e.Y; press = true; } private void Area_MouseMove (object sender, MouseEventArgs e) { if (press) { if (e.Button == MouseButtons.Left) { control.Left += e.X - X0; control.Top += e.Y - Y0; } else if (e.Button == MouseButtons.Middle) { control.Width += e.X - X0; control.Height += e.Y - Y0; X0 = e.X; Y0 = e.Y; } } } private void Area_MouseUp (object sender, MouseEventArgs e) { press = false; } }
Panel s obrázky
Původní kód z kapitoly o pohyblivých panelech jsem přemístil do třídy ImageArea odvozené ze třídy UserControl.
public partial class ImageArea : UserControl { public ImageArea (string path = "") { InitializeComponent (); new Area (this); if (path != "") BackgroundImage = new Bitmap (path); } private void colorMenuItem_Click (object sender, EventArgs e) { colorDialog.Color = this.BackColor; if (colorDialog.ShowDialog () == DialogResult.OK) BackColor = colorDialog.Color; } private void imageMenuItem_Click (object sender, EventArgs e) { if (openDialog.ShowDialog () == DialogResult.OK) { BackgroundImage = new Bitmap (openDialog.FileName); } } private void borderMenuItem_Click (object sender, EventArgs e) { borderMenuItem.Checked = ! borderMenuItem.Checked; if (borderMenuItem.Checked) BorderStyle = BorderStyle.FixedSingle; else BorderStyle = BorderStyle.None; } private void stretchMenuItem_Click (object sender, EventArgs e) { stretchMenuItem.Checked = ! stretchMenuItem.Checked; if (stretchMenuItem.Checked) BackgroundImageLayout = ImageLayout.Stretch; else BackgroundImageLayout = ImageLayout.None; } }
HTML panel
Třída HtmlArea obsahuje komponentu typu WebBrowser umístěnou na celé ploše panelu.
Konstruktor má jako parametr cestu k html souboru, který v panelu zobrazí.
WebBrowser cestu k souboru dostane jak typ Uri, kde uvedeme file: a zpětná lomítka nahradíme obyčejnými lomítky.
Panelu ještě přídáme vlastnost Browser, která dovoluje pouze číst odkaz na komponentu webBrowser a nedovoluje zápis.
Vlastnost se objeví v tabulce PropertyGrid mezi vlastnostmi panelu v oddělení Data
public partial class HtmlArea : UserControl { public HtmlArea (string path) { InitializeComponent (); new Area (this); webBrowser.Url = new Uri ("file:///" + path.Replace ('\\', '/').Replace("//", "/")); } [ Category ("Data") ] public WebBrowser Browser { get => webBrowser; } }
Textový panel
Podobně třída TextArea obsahuje TextBox zobrazujícíobsah textového souboru.
V konstruktoru funkce File.ReadAllText přečte obsah celého souboru a výsledkem je jeden řetězec znaků.
Vlastnost TextBox poskytuje odkaz na textovou komponentu, jen je funkce get zapsána trochu jinak, než v předchozím odstavci.
public partial class TextArea : UserControl { public TextArea (string path) { InitializeComponent (); new Area (this); textBox.Text = File.ReadAllText (path); } [Category ("Data")] public TextBox Editor { get { return textBox; } } }
Tabulka s daty připomínající spreadsheet
V tomto panelu se o zobrazení postará komponenta grid typu DataGridView
V konstruktoru se pokusíme přečíst soubor obsthující data oddělená čárkami (.csv)
- Funkce File.ReadAllLines načte celý textový soubor a uloží ho do pole řetězců znaků lines
- Nejprve musíme najít nejdelší řádku a určit maximální počet sloupců
- Do komponenty grid snadno přidáváme řádky jako seznam řetězců List < string >
- Připravíme si seznam complete, který bude obsahovat seznamy tvořící jednotlivé řádky List < List < string > >
- Proměnná complete je jen ukazatel inicializovaný na null, celý seznam seznamů musíme ještě vytvořit
List< List < string > > complete = new List < List < string > > ();
- Projdeme jednotlivé řádky, které máme v poli lines
- Pro každou řádku vytvoříme zatím prázdný seznam data, do kterého budeme přidávat jednotlivé sloupce
- Funkce line.Split (',') rozdělí řádku, v místech kde jsou čárky, na jednotlivé textové položky item
- Položky item přidáme do seznamu data
- Do proměnné cnt uložíme pocět položek v seznamu data.Count
- V proměnné columns skladujeme dosud největší počet sloupců
- Seznam data představující jednu řádku přidáme do seznamu seznamů complete
foreach (string line in lines) { List<string> data = new List<string> (); foreach (string item in line.Split (',')) { data.Add (item); } int cnt = data.Count; if (cnt > columns) columns = cnt; complete.Add (data); }
- Komponentě grid typu GridView nastavíme počet sloupců
- A potom můžeme přidávat jednotlivé řádky, které metodou ToArray převedeme na pole řetězců
grid.ColumnCount = columns; foreach (var data in complete) grid.Rows.Add (data.ToArray());
Celý panel zobrazující tabulku dat
public TableArea (string path) { InitializeComponent (); string [] lines = File.ReadAllLines (path); int columns = 0; List< List < string > > complete = new List < List < string > > (); foreach (string line in lines) { List<string> data = new List<string> (); foreach (string item in line.Split (',')) { data.Add (item); } int cnt = data.Count; if (cnt > columns) columns = cnt; complete.Add (data); } grid.ColumnCount = columns; foreach (var data in complete) grid.Rows.Add (data.ToArray()); } [ Category ("Data") ] public DataGridView Table { get => grid; } }
Panel s grafy
Grafy zobrazí komponenta chart typu Chart
Na webu jsem nalezl krátký příklad jak zobrazit sloupcový graf se třemi hodnotami
// http://csharpexamples.com/c-chart-control-example/ chart.Series.Clear (); chart.Titles.Add (""); Series data = chart.Series.Add ("first"); data.Points.Add (10); data = chart.Series.Add ("second"); data.Points.Add (20); data = chart.Series.Add ("third"); data.Points.Add (30);
Nebo kruhový diagram
// https://stackoverflow.com/questions/34104484/how-to-build-a-pie-chart-based-on-int-values chart.Series.Clear (); Series data = chart.Series.Add (""); data.ChartType = SeriesChartType.Pie; data.Points.AddXY ("first", 10); data.Points.AddXY ("second", 20); data.Points.AddXY ("third", 30);
- Graf vymažeme a do proměnné data dáme odkaz na pomocný objekt s daty
- Funkce File.ReadAllLines načte do pole lines jednotlivé řádky
- Řádky rozdělíme na položky oddělené čárkami, pole položek se jmenuje items
- Poznamenáme si počet položet na řádce do proměnné cnt
- Do proměnné value uložíme první položku, pokud existuje
- Do name uložíme druhou položku, obě jako řetězec znaků
- Funkce int.TryParse převede řetěrec znaků na celé číslo a uloží do proměnné number, pokud převédst lze
- Jméno a hodnotu přidáme do grafu data.Points.AddXY (name, number);
public partial class ChartArea : UserControl { public ChartArea (string path) { InitializeComponent (); new Area (this); chart.Series.Clear (); Series data = chart.Series.Add (""); string[] lines = File.ReadAllLines (path); foreach (string line in lines) { string [] items = line.Split (','); int cnt = items.Length; string value = (cnt >= 1) ? items[0] : ""; string name = (cnt >= 2) ? items[1] : ""; int number = 0; int.TryParse (value, out number); data.Points.AddXY (name, number); } } [ Category ("Data")] public Chart Chart { get => chart; } }