Některé možností pro snadnou tvorbu úlohy

Transkript

Některé možností pro snadnou tvorbu úlohy
Některé možností pro snadnou tvorbu úlohy
Petr Novák ([email protected])
Verze 1.01.00 (30.03.2015)
Obsah
1
Základní plocha úlohy ...................................................................................................................... 1
1.1
Grid .......................................................................................................................................... 1
1.2
Canvas...................................................................................................................................... 3
1.3
Společné .................................................................................................................................. 5
1.3.1
Velikost podkladu ............................................................................................................ 5
1.3.2
Obrázek jako podklad ...................................................................................................... 5
1.4
Speciální efekty........................................................................................................................ 6
1.4.1
Canvas + Grid ................................................................................................................... 6
2
Text .................................................................................................................................................. 6
3
Další celkem užitečné poznámky ..................................................................................................... 7
4
Poznámky ........................................................................................................................................ 7
1 Základní plocha úlohy
Základní plocha úlohy může být tvořena v podstatě libovolným grafickým prvkem pocházejícím od
„Systém.Windows.FrameworkElement“. Zde jsou uvedeny některé nejčastěji používané grafické
prvky pro základní plochu úlohy a příkladu jejich využití.
1.1 Grid
Vložení vlastního grafického prvku „Grid“ do základního „Grid“ vytvářeného frameworkem je
následující:
// použití „Grid“ (mřížka) jako základní plochy úlohy
taskGUIItems[…] = new TaskGUIItem() { number = …, guiItem = EnumGUIItem.Grid };
Do vlastního vloženého „Grid“ lze přidat libovolný počet řádků a sloupců pomocí:
Grid grid = taskGUIItems[EnumNumber.First];
// vymazaní všech existujících řádků
grid.RowDefinitions.Clear();
// tolik řádků kolik je potřeba
for (int i = 0; i < rows_number; i++)
{
// do seznamu řádků se přidá nový / další řádek
grid.RowDefinitions.Add(
// vložení jednoho nového řádku
new RowDefinition()
// jeho šířka je v podstatě 10% (vysvětleno dále)
{ Height = new GridLength(10, GridUnitType.Star) });
}
// vymazaní všech existujících sloupců
grid.ColumnDefinitions.Clear();
// tolik sloupců kolik je potřeba
for (int i = 0; i < columns_number; i++)
{
// do seznamu sloupců se přidá nový / další sloupec
grid.ColumnDefinitions.Add(
// vložení jednoho nového sloupce
new ColumnDefinition()
// jeho šířka je v podstatě 10% (vysvětleno dále)
{ Width = new GridLength(10, GridUnitType.Star) });
}
Při zadání šířky pro řádek i sloupec se používá (mimo jiné):
// šířka je (přesně) 10 obrazových bodů
GridLength(10)
// šířka je minimálně 10 obrazových bodů, ale roztáhne se poměrově k celku
GridLength(10, GridUnitType.Star)
Pokud je zadáno samotné číslo bez „GridUnitType.Star“, tak jde o počet obrazových bodů, jak
bude řádek, nebo sloupec široký bez ohledu na celkovou velikost / plochu „Grid“ (i toho
podkladového z framework). Je-li použito současně „GridUnitType.Star“, tak dřívější zadané číslo
označuje minimální velikost a jakýsi poměr roztažení tohoto řádku / sloupce pokud je šířka / výška
„Grid“ vetší než součet základních velikostí všech vytvořených řádků / sloupců. Při použití
„GridUnitType.Star“ je vhodné čísla považovat, pro jednoduchost, za procenta a to následovně:
// tento řádek při roztahování
new RowDefinition() { Height =
// tento řádek při roztahování
new RowDefinition() { Height =
// tento řádek při roztahování
new RowDefinition() { Height =
bude zabírat 20% z
new GridLength(20,
bude zabírat 20% z
new GridLength(20,
bude zabírat 60% z
new GridLength(60,
celkové výšky „Grid“
GridUnitType.Star) });
celkové výšky „Grid“
GridUnitType.Star) });
celkové výšky „Grid“
GridUnitType.Star) });
Celkově tedy 100% pro snazší orientaci. Při roztahování „Grid“ příslušným směrem se boudou
vytvořená řádky / sloupce rovněž automaticky roztahovat v zadaném procentuálním poměru.
Vložit jakýkoli grafický prvek do vlastního „Grid“ lze následovně:
// prvek přidávaný do „Grid“
Image img = new Image();
// jeho přidání pouze pokud již v „Grid“ není
if (!g.Children.Contains(img)) g.Children.Add(img);
// nastavení umístění na tento sloupec (čísla jsou 0, 1, 2, …)
Grid.SetColumn(img, columnNumber);
// nastavení umístění na tento řádek (čísla jsou 0, 1, 2, …)
Grid.SetRow(img, rowNumber);
Pokud je potřeba umístit vkládaný prvek přes několik řádků (na výšku) nebo několik sloupců (na šířku)
od zadaného počátečního, lze použít následující:
// prvek bude vložen přes 5 sloupců, bude tedy zabírat, 5 sloupců (na šířku)
Grid.SetColumnSpan(img, 6);
// prvek bude vložek přes 6 řádků, bude tedy zabírat 6 řádků (na výšku)
Grid.SetRowSpan(img, 6);
Poznámky:
- Pro kontrolu vytvoření požadovaných řádků / sloupců lze snadno nastavit zobrazení jejich
kontrolních obrysů pomocí grid.ShowGridLines = true.
- Pro kontrolu skutečné velikosti vytvořeného „Grid“ je vhodné nastavit pro něho nějaké
pozadí, například grid.Background = new SolidColorBrush(Colors.LightGray). Zejména
při ladění úlohy.
1.2 Canvas
Vložení vlastního grafického prvku „Canvas“ do základního „Grid“ vytvářeného frameworkem je
následující:
// použití „Grid“ (mřížka) jako základní plochy úlohy
taskGUIItems[…] = new TaskGUIItem() { number = …, guiItem = EnumGUIItem.Canvas };
Na „Canvas“ lze přidat téměř jakýkoli grafický prvek, například:
// vytvořená grafického prvku „Image“
Image img = new Image();
// jeho vložení na „Canvas“
taskGUIItems[EnumNumber.First].canvas.Children.Add(frmElmSet);
// horizontální souřadnice středu (ve skutečnosti se nastavuje levý-horní roh)
Canvas.SetLeft(img, positionX - img.Width / 2);
// vertikální souřadnice středu (ve skutečnosti se nastavuje levý-horní roh)
Canvas.SetTop(img, positionY - img.Height / 2);
Často může být požadavek na přesun grafických prvků po „Canvas“. Toto lze uskutečnit následovně
(využití položky „Tag“ je popsáno dále):
// událost při stisku tlačítka myši na „Image“
img.MouseLeftButtonDown += (sender, e) =>
{
// událost je od „Image“
Image imgTemp = (Image)sender;
// vyzvednutí informací o tomto „Image“
ClassMyInfo classMyInfo = (ClassMyInfo)imgTemp.Tag;
// tímto „Image“ se nyní pohybuje
classMyInfo.moveYes = true;
// uložení místa uchycení tohoto „Image“ (pro hezký přesun, třeba za jeho roh)
classMyInfo.moveOrig.X =
// pozice kurzoru na „Canvas“ v ose X
(double)e.GetPosition(taskGUIItems[EnumNumber.First].canvas).X –
// odečtení levého rohu umístění „Image“ na „Canvas“
Canvas.GetLeft(image);
// obdobně pro osu Y
classMyInfo.moveOrig.Y =
(double)e.GetPosition(taskGUIItems[EnumNumber.First].canvas).Y –
Canvas.GetTop(image);
// myš bude svázána s tímto prvkem po dobu jeho pohybu (velmi vhodné)
image.CaptureMouse();
};
// událost při posunu „Image“
img.MouseMove += (sender, e) =>
{
// událost je od „Image“
Image imgTemp = (Image)sender;
// vyzvednutí informací o tomto „Image“
ClassMyInfo classMyInfo = (ClassMyInfo)imgTemp.Tag;
// pouze pokud se tímto „Image“ (již) pohybuje
if (classMyInfo.moveYes == true)
{
// nastavení jeho nové pozice v ose X (podle počátečního uchopení)
Canvas.SetLeft(image,
// aktuální pozice myši na „Canvas“
(double)e.GetPosition(taskGUIItems[EnumNumber.First].canvas).X –
// odečtení ofsetu při jeho uchopení
classMyInfo.moveOrig.X);
// obdobně pro osu Y
Canvas.SetTop(image,
(double)e.GetPosition(taskGUIItems[EnumNumber.First].canvas).Y –
classMyInfo.moveOrig.Y);
}
};
// událost při uvolnění tlačítka myši na „Image“
img.MouseLeftButtonUp += (sender, e) =>
{
// událost je od „Image“
Image imgTemp = (Image)sender;
// vyzvednutí informací o tomto „Image“
ClassMyInfo classMyInfo = (ClassMyInfo)imgTemp.Tag;
// tímto „Image“ se již nepohybuje
classMyInfo.moveYes = false;
// myš již není vázána na tento „Image“
frmElmUserTemp.ReleaseMouseCapture();
};
Třída „ClassMyInfo“ může být pro tuto ukázku následující:
public class Connection
{
// příznak zda se objektem právě pohybuje
public bool moveYes = false;
// pozice uchopení objektu před jeho pohybem
public Point moveOrig = new Point();
// další vlastní položky
// …
}
1.3 Společné
…
1.3.1
Velikost podkladu
U vlastního grafického prvku lze nastavit jeho skutečnou velikost. Nejjednodušší je jeho roztažení na
maximální velikost podle políčka v podkladovém „Grid“ z framework pomocí:
// roztažení na maximální velikost podle podkladového políčka z „Grid“
canvas.HorizontalAlignment = HorizontalAlignment.Stretch;
canvas.VerticalAlignment = VerticalAlignment.Stretch;
Případně vystředit na střed políčka v podkladovém „Grid“ z framework pomocí:
// vystředění podle podkladového políčka z „Grid“
canvas.HorizontalAlignment = HorizontalAlignment.Center;
canvas.VerticalAlignment = VerticalAlignment.Center;
Pokud je požadavek na nastavení nějaké přesnější velikosti vloženého prvku, například pro formát
použitého podkladového obrázku, lze programový kód v metodě „TaskOnSizeChange()“ vytvořit
takto:
// aby byl zachován poměr stran u obrázku použitého pro 'Background'
// měřítko podle nejmenší velikost v některém směru (šířka / výška)
double scale = Math.Min(
// maximální možné měřítko pro šířku
TaskGridGlobal.ColumnDefinitions[0].ActualWidth / backgroundImage.RowWidth(),
// maximální možné měřítko pro výšku
TaskGridGlobal.RowDefinitions[0].ActualHeight / backgroundImage.RowHeight());
// nastaveni velikosti 'Canvas' podle menšího zjištěného měřítka
taskGUIItems[EnumNumber.First].canvas.Width = backgroundImage.RowWidth() * scale;
taskGUIItems[EnumNumber.First].canvas.Height = backgroundImage.RowHeight() * scale;
1.3.2
Obrázek jako podklad
Jakýkoli obrázek lze použít jako podklad například pro „Canvas“, „Grid“ a další. Tvorba je následující:
// načtení obrázku jako binární pole (byte[])
byte[] imageBytes = await iFramework.ServerAppDataFiles.LoadFilesAsBinary(path, name);
// vytvoření „Image“ například pro vložení do „Grid“ nebo „Canvas“
Image image = new Image()
{
// pomocná metoda poskytne binární data pro vytvoření „Image“
Source = XUtils.Graphics.ImageCommon.BitmapImageFromBytes(imageBytes)
};
// obrázek bude vložen jako pozadí pro …
grid / canvas.Background =
// pozadí bude formou štětce typu „ImageBrush“
new ImageBrush()
{
// štětec bude tvořen tímto obrázkem
ImageSource = image,
// roztažení obrázku na velikost podkladu, zachování poměru stran
Stretch = Stretch.Uniform
};
1.4 Speciální efekty
…
1.4.1
Canvas + Grid
Pokud bychom chtěli umístit nějaké grafické komponenty defaultně do mřížky („Grid“), ale přitom
umožnit s nimi plynule pohybovat mezi jeho políčky pomocí myší lze postupovat následovně:
-
-
Do základového políčka frameworku vložíme „Canvas“. Velikost nastavíme podle potřeby.
Na „Canvas“ vložíme (ještě) „Grid“ o zcela stejné velikosti jako dříve vložený „Canvas“. „Grid“
by měl mít průsvitné pozadí („Background = Transparent“).
V „Grid“ vytvoříme tolik políček, kolik potřebujeme pro vložení defaultně umístěných
grafických prvků (obrázky, čtverce, …). Tedy vložíme a nastavíme jejich pozice v „Grid“.
Pokud se uchopí grafický prvek myší (stisk tlačítka myši), tak jej odejmeme z „Grid“ (z
políčka), vypočteme jeho aktuální souřadnici levého horního rohu podle pozice políčka, kde
se nacházel v „Grid“ a vložíme jej na „Canvas“ na tuto souřadnici (na bodové souřadnice).
Při pohybu myši (držení a přesunu grafického prvku) používáme pouze bodové pozice z
„Canvas“.
Pokud je grafický prvek upuštěn (uvolnění tlačítka myši), tak jej odebereme z „Canvas“
(bodové souřadnice) a vložíme jej zpět na „Grid“ (políčka) a to do políčka, jemuž je poslední
známá souřadnice z „Canvas“ nejblíže.
Takto zle zcela snadno vytvořit velmi efektivní přesun grafických prvků mezi políčky v „Grid“ pomocí
přetažení myší.
2 Text
Při zobrazení textu je vhodné znát několik velmi užitečných zásad. Pokud chce, aby se text stále
zobrazovat co největší možná a to sám od sebe postupujeme takto (možná to jde i jednodušeji):
// „Border“ umožňuje nastavit pozadí pod text
Border border = new Border()
{
// nastavení pozadí pod text
Background = XUtils.Graphics.SolidColorBrushes.GetByColor(Colors.LightGray),
// do „Border“ je vložen „Viewbox“, který vše v sobě roztáhne na max. velikost
Child = new Viewbox()
{
// ve „Viewbox“ je vložen „TextBlock“ pro snadné zobrazení textu
Child = new TextBlock()
{
// zobrazovaný text
Text = „…“,
// text bude tučný (dobře viditelný)
FontWeight = FontWeights.Bold,
// text bude zarovnaný na střed v „TextBlock“
TextAlignment = TextAlignment.Center,
// text bude touto barvou
Foreground = XUtils.Graphics.Brushes.GetSolidColorBrush(Colors.Black)
}
}
};
V tomto případě se není nutno vůbec starat o velikost fontu v „TextBlock“. Ten obsažený text vždy
zvětší na takové největší font, aby byl „TextBlock“ zadaným texten zcela vyplněn.
3 Další celkem užitečné poznámky
Každý grafický prvek obsahuje položky zvanou „Tag“ do které lze vložit svoji zcela vlastní hodnotu.
Význam této položky je neocenitelný, pokud programátor pochopí její využití. Například vytvoříme
grafický prvek „Image“, „Rectangle“, „Line“, ... Současně vytvoříme nějakou svoji třídu obsahující
informace o tomto grafickém prvku s názvem „ClassMyInfo“. Při tvorbě grafického prvku (a jeho
umístění na „Canvas“) do jeho položky „Tag“ vložíme obsah naší třídy „ClassMyInfo“:
// vytvoření „Image“ a vložení do jeho položky „Tag“ odkaz na vlastní třídu
Image img = new Image() { Tag = new ClassMyInfo(…) }
Poté při stisku tlačítka na tomto grafickém prvku velmi snadno z položky „Tag“ vyzvedneme všechny
potřebné informace:
// událost při kliku na „Image“
img.MouseLeftButtonDown += (sender, e) =>
{
// parametr „Sender“ přetypovat na „Image“ (víme, že jde o „Image“)
Image imgTemp = (Image)sender;
// z „Image“, z jeho položky „Tag“ vyzvedneme odkaz na naší třídu
ClassMyInfi classMyInfo = (ClassMyInfo)imgTemp.Tag;
// zpracování …
Není tedy vůbec nutno vytvářet nějaké složité slovníky, v nich uchovávat ukazatele na spoustu
grafických prvků a při kliku na nějaký prvek tento slovník procházet pro zjištění na který grafický
prvek byl ve skutečnosti klik vykonán. Stačí každému grafickému prvku do položky „Tag“ vložit odkaz
na třídu nesoucí jeho informace, tu poté vyzvednout a podle toto s grafickým prvkem zacházet.
4 Poznámky
-
Téměř každý grafický prvek obsahuje položky „Padding“ a „Margin“. První představuje
prázdný okraj vně prvku a druhý prázdný kraj uvnitř prvku (pro vložení dalšího prvku do jeho
-
vnitřku). Lze zadat pouze jednu stejnou hodnotu pro všechny čtyři strany „Padding = new
Thickness(šířka)“ nebo pro každou stranu zvlášť „Padding = new Thickness(levá, horní,
pravá, dolní)“.
Pokud u některého grafického prvku nelze nastavit „Border…“ (kraj) nebo „Background…“
(pozadí), protože je prostě neobsahují, tak lze původní grafický prvek umístiti do „Border“ a
v něm tyto vlastnosti nastavit podle potřeby. Grafický prvek „Border“ umožňuje vytvořit
nejen libovolně barevné a široké okraje, ale rovněž i zaoblené.