Tvorba aplikací s grafickým rozhraním. Metodika vývoje aplikací pomocí GUI pro programování Forms C

Poslední aktualizace: 07.10.2019

Rozhraní představuje typ odkazu, který může definovat nějakou funkcionalitu – sadu metod a vlastností bez implementace. Poté je tato funkce implementována třídami a strukturami, které tato rozhraní používají.

Definice rozhraní

Chcete-li definovat rozhraní, použijte klíčové slovo rozhraní. Názvy rozhraní v C# obvykle začínají velkým písmenem I , například IComparable, IEnumerable (takzvaná maďarská notace), ale není to povinný požadavek ale spíše styl programování.

Co může rozhraní definovat? Obecně mohou rozhraní definovat následující entity:

  • Vlastnosti

    Indexery

  • Statická pole a konstanty (od C# 8.0)

Rozhraní však nemohou definovat nestatické proměnné. Například nejjednodušší rozhraní, které definuje všechny tyto komponenty:

Rozhraní IMovable ( // konstantní const int minSpeed ​​​​= 0; // minimální rychlost // statická proměnná static int maxSpeed ​​​​= 60; // maximální rychlost // metoda void Move(); // pohyb // řetězec vlastností Název ( get; set ; ) // jméno delegáta void MoveHandler(string message); // definování delegáta pro událost // událost události MoveHandler MoveEvent; // událost pohybu )

PROTI tento případ je definováno rozhraní IMovable, které představuje nějaký pohybující se objekt. Toto rozhraní obsahuje různé komponenty, které popisují schopnosti pohybujícího se objektu. To znamená, že rozhraní popisuje některé funkce, které by měl mít pohyblivý objekt.

Metody a vlastnosti rozhraní nemusí mít implementaci, v tomto se blíží abstraktním metodám a vlastnostem abstraktních tříd. V tomto případě rozhraní definuje metodu Move, která bude reprezentovat nějaký pohyb. Nemá žádnou implementaci, nebere žádné parametry a nic nevrací.

Totéž platí v tomto případě pro vlastnost Name. Na první pohled to vypadá jako automatická vlastnost. Ale ve skutečnosti se jedná o definici vlastnosti v rozhraní, které nemá žádnou implementaci, ne vlastnost auto.

Další bod v deklaraci rozhraní: pokud jeho členové - metody a vlastnosti nemají modifikátory přístupu, ale ve skutečnosti je standardně přístup public , protože účelem rozhraní je definovat funkcionalitu pro implementaci jeho třídou. To platí také pro konstanty a statické proměnné, které mají ve třídách a strukturách standardně modifikátor private. V rozhraních mají ve výchozím nastavení modifikátor public. A například bychom mohli odkázat na konstantu minSpeed ​​​​a proměnnou maxSpeed ​​​​rozhraní IMovable:

Static void Main(string args) ( Console.WriteLine(IMovable.maxSpeed); Console.WriteLine(IMovable.minSpeed); )

Ale také, počínaje C# 8.0, můžeme explicitně specifikovat modifikátory přístupu pro komponenty rozhraní:

Rozhraní IMovable ( public const int minSpeed ​​​​= 0; // minimální rychlost private static int maxSpeed ​​​​= 60; // maximální rychlost public void Move(); chráněný interní řetězec Name ( get; set; ) // jméno veřejného delegáta void MoveHandler(string message); // definování delegáta pro veřejnou událost události MoveHandler MoveEvent; // událost pohybu )

Počínaje C# 8.0 rozhraní podporují výchozí implementace metod a vlastností. To znamená, že můžeme definovat plnohodnotné metody a vlastnosti v rozhraních, která mají implementaci stejně jako v běžných třídách a strukturách. Pojďme například definovat výchozí implementaci metody Move:

Rozhraní IMovable ( // implementace výchozí metody void Move() ( Console.WriteLine("Walking"); ) )

S implementací výchozích vlastností v rozhraních je situace poněkud komplikovanější, protože nemůžeme definovat nestatické proměnné v rozhraních, a tudíž ve vlastnostech rozhraní nemůžeme manipulovat se stavem objektu. Můžeme však také definovat výchozí implementaci pro vlastnosti:

Rozhraní IMovable ( void Move() ( Console.WriteLine("Walking"); ) // implementace výchozí vlastnosti // vlastnost pouze pro čtení int MaxSpeed ​​​​( get ( return 0; ) ) )

Stojí za zmínku, že pokud má rozhraní soukromé metody a vlastnosti (tedy s modifikátorem private), musí mít výchozí implementaci. Totéž platí pro jakékoli statické metody a vlastnosti (ne nutně soukromé):

Rozhraní IMovable ( public const int minSpeed ​​​​= 0; // minimální rychlost private static int maxSpeed ​​​​= 60; // maximální rychlost // zjistěte čas potřebný k překonání vzdálenosti rychlostí static double GetTime (dvojitá vzdálenost, dvojnásobná rychlost ) = > vzdálenost / rychlost; static int MaxSpeed ​​​​( get ( return maxSpeed; ) set ( if (hodnota > 0) maxSpeed ​​​​= hodnota; ) ) ) class Program ( static void Main(string args) ( Console.WriteLine (IMovable.MaxSpeed); IMovable.MaxSpeed ​​​​= 65;Console.WriteLine(IMovable.MaxSpeed);double time = IMovable.GetTime(100, 10);Console.WriteLine(time); ) )

Modifikátory přístupu k rozhraní

Stejně jako třídy mají rozhraní standardně interní úroveň přístupu, což znamená, že takové rozhraní je dostupné pouze v rámci aktuálního projektu. Ale s modifikátorem public můžeme rozhraní učinit veřejným:

Veřejné rozhraní IMovable ( void Move(); )

Stojí za zmínku, že Visual Studio má speciální komponentu pro přidání nového rozhraní v samostatném souboru. Chcete-li do projektu přidat rozhraní, můžete kliknout pravým tlačítkem myši na projekt a v zobrazeném okně kontextová nabídka vyberte Přidat -> Nová položka... a v dialogovém okně pro přidání nové součásti vyberte Rozhraní .

V tomto článku budeme hovořit o vytváření jednoduchých aplikací pomocí formulářů v C ++. Chci to hned upřesnit: vývoj „formových“ C++ aplikací bude probíhat v prostředí Microsoft Visual Studio (obejdeme hlavního konkurenta Borland Software). Stojí za zmínku, že ve Visual Studiu existují dva způsoby, jak vytvořit aplikaci s formuláři, rozhodnutí je učiněno v době vytváření nového projektu.

První z nich je použití Windows Forms, který implementuje GUI a součástí Microsoft .NET Framework. Tento přístup zjednodušuje přístup k prvkům rozhraní. Microsoft Windows zabalením Win32 API do spravovaného kódu. Pokud dáte své myšlenky do srozumitelnější formy, pak je tento přístup velmi podobný vytváření konzolové aplikace, ale je trochu složitější. používá formuláře.

Druhý způsob je založen na využití Microsoft Foundation Classes (MFC), knihovny, která se stará o budování aplikačního frameworku. Na rozdíl od prvního MFC po vybalení používá vzor MVC (Model-View-Cont roller). Tento přístup je složitější než první, ale spoléhat se na něj můžete snadno vytvořit framework pro velmi zajímavé aplikace, např. textový editor nebo použijte komponentu Ribbon a vytvořte menu jako v notoricky známém MS Office 2010.

Vytvoření aplikace v MS Visual Studio

Vytvoříme novou aplikaci: Soubor->Nový->Projekt. V okně, které se objeví, jako na obrázku výše, najděte a vyberte Windows Forms Application, poté zadejte název (app1) a umístění nového projektu a potvrďte jeho vytvoření kliknutím na tlačítko „OK“.

Než přistoupíte přímo k programování, měli byste pochopit, co je to událost. Událost je akce, která nastane za určitých podmínek. Za nejjednodušší (a nejběžnější a) lze považovat Load, Click ... podívejme se na některé z nich podrobněji:

  • Aktivováno – událost, která nastane při aktivaci prvku.
  • Click – nastane, když se na prvek jednou klikne.
  • DoubleClick – poklepejte na prvek.
  • HelpRequested – spustí se při stisku klávesy .
  • Barva – spustí se při překreslování prvku.
  • MouseLeave – Událost se spustí, když kurzor opustí hranice prvku.

Nezapomeňte, že události specifické pro prvek závisí na jeho typu. Chcete-li zobrazit všechny události dostupné pro objekt formuláře, vyberte jej a v okně vlastností vyberte ikonu blesku. Níže je část událostí pro elementForm1. Jak vidíte, pro událost Load je vybrána funkce Form1_Load, takže kód obsažený v této funkci bude volán při načtení formuláře.

Otevřete soubor Form1.h, bude zde následující kód:

Soukromé: System::Void Form1_Load(System::Object^ odesílatel, System::EventArgs^ e)( )

Toto je stejná funkce Form1_Load, která se spouští při načtení formuláře. Pojďme si to ověřit přidáním komponenty TextBox do formuláře.

Chcete-li to provést, otevřete prostředek formuláře a vyberte jej. Dále vyberte panel nástrojů Toolbox a přetáhněte komponentu TextBox do formuláře. Upravte funkci Form1_Load takto:

Private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) ( textBox1->Text = "Ahoj, světe!"; //textBox1 je název textového pole, které jste přidali)

Spusťte projekt, v důsledku toho by se měla zobrazit následující zpráva:

To je prozatím vše, pokračování v následujících lekcích.

Hned udělám výhradu, že C++ je můj oblíbený jazyk, píšu v něm téměř „od dětství“ a popírám jeho důležitost jako nejlepší z nejlepší jazyky pro psaní programů pro jakýkoli účel, nebudu. Navíc nevidím důvod zakládat další holivar nebo měřit "ukazatele". Tento článek je pouze popisem špatné zkušenosti s jazykem, vysvětlením některých jeho aspektů, jejichž znalost v budoucnu pomůže dalším programátorům.

Jednoho dne jsem narazil na vyvíjející se knihovnu tříd GUI. Z hlediska C++ a konkrétněji jeho tříd, instancí a hierarchií se tento jazyk zdá neuvěřitelně blízký konceptu ovládání GUI, zejména prvků, jako jsou widgety, okna tříd a podokna. OO modely C++ a okenní systém jsou však odlišné. C++ byl zamýšlen jako „statický“ jazyk s rozsahem tokenů, statickou kontrolou typu a hierarchiemi definovanými v době kompilace. Okna a jejich objekty jsou na druhé straně dynamické povahy, obvykle žijí mimo jedinou proceduru nebo blok, kterým byly vytvořeny; Hierarchie widgetů jsou z velké části definovány rozložením, viditelností a proudy událostí. Základy grafiky uživatelské rozhraní, jako jsou dynamické a geometrické hierarchie oken a řízení, tok událostí, nejsou přímo podporovány syntaxí C++ ani její sémantikou. Tyto funkce tedy musí být replikovány v kódu GUI C++. To vede k duplikaci grafické sady nástrojů nebo funkčnosti správce oken, kód se "nafoukne", jsme nuceni opustit mnoho "silných" funkcí C++ (například kontrola typu při kompilaci). Článek obsahuje několik jednoduché příklady C++/GUI „bez dokování“.

Nevytvářejte konstruktory (nebo je alespoň nepoužívejte)

Když výsledná třída přepíše virtuální metodu nadřazené třídy, mějte na paměti, že přepsání se neprojeví během provádění konstruktoru základní třídy. To je obzvláště nepříjemné, když objekty vyžadují widgety, které reagují na události GUI. Předpokládejme třídu Základní_okno byl určen k vytvoření vanilkového černobílého okna na obrazovce:

ClassBasic_Window(
veřejnost:
Basic_Window(Rect rect) (gt_create_window(rect,visible,this); )
virtuální void handle_create_event() ( set_background(WHITE); )
};

Tady gt_create_window() je zodpovědný za nízkoúrovňové volání hlavní sady grafických nástrojů (např. xvt_win_create()). Tato funkce alokuje místo pro data sady nástrojů, upozorní správce oken, zaregistruje tento objekt jako posluchač události a ve výše uvedeném příkladu inicializuje grafický výstup do okna na obrazovce.
Předpokládejme, že chceme vytvořit instanci Základní_okno, ale s červeným pozadím. Obvykle, chcete-li změnit chování třídy, musíte z ní extrahovat a přepsat odpovídající virtuální metody. Píšeme:

Třída RedWindow: public Basic_Window(
virtuální void handle_create_event() ( set_background(RED); )
veřejnost:
RedWindow(obdélník) : Basic_Window(obdélník) ()
};
redWindow red_window(default_rect);

Ale červené_okno bude vypadat bíle, ne červeně! Vytvořit RedWindow, musí být nejprve vytvořen rodičovský objekt. Po dokončení Basic_Window::Basic_Window(), virtuální stoly RedWindow působit, metoda handle_create_event() stane neplatným a konstruktor RedWindow() provedeno. Konstruktér Basic_Window() registruje objekt grafického nástroje, který okamžitě začne odesílat události do objektu (např. událost CREATE). Konstruktér Basic_Window() ještě není dokončeno (není zaručeno), takže přepsaná virtuální metoda ještě není zavedena. Bude tedy zpracována událost CREATE Basic_Window::handle_create_event(). Virtuální stoly RedWindow třídy budou vytvořeny pouze tehdy, když je základní třída plně vytvořena, to znamená, když je okno již na obrazovce. Změna barvy okna v této fázi povede k nepříjemné chybě.

Existuje jednoduché řešení: zabraňte každému konstruktoru v registraci objektu sady nástrojů GUI. Zpracování událostí bude strukturováno tak, aby zdrželo konec inicializace pro odvozené třídy. Je velmi lákavé představovat si widgety na obrazovce jako „obličej“ objektu GUI aplikace v paměti. Jak ukazuje příklad výše, toto spojení mezi obrazovkou a objektem C++ není tak snadné implementovat: rodí se odděleně.

Žádné syntaktické prostředky pro přepínání událostí

Předpokládejme, že knihovna tříd obsahuje GUI třídy PictWindow který zobrazí fotografii v okně:

Třída PictWindow(
obrázek obrázek;
veřejnost:
virtual void repaint() ( gt_draw_pict(picture); )
...
};

Rádi bychom překryli malý obdélník v určité oblasti obrázku. Za tímto účelem se můžeme pokusit o podtřídu PictWindow:


Rectect;
virtual void repaint() ( gt_draw_rect(rect); )
};

Bohužel, když vytvoříme instanci OvWindow, v prázdném okně uvidíme pouze obdélník a žádný obrázek. Od té chvíle OvWindow::repaint() předefinuje PictWindow::repaint(), poslední funkce nebude volána, když se bude okno kreslit. Museli jsme realizovat OvWindow Tak:

Třída OvWindow: veřejné PictWindow(
Rectect;
virtual void repaint() ( PictWindow::repaint(); gt_draw_rect(rect); )
veřejnost:
OvWindow(void): PictWindow()()
};

Konstruktér OvWindow stanovil zdůraznit, že metoda OvWindow::repaint() musí být odložen do nadtřídy, jak to dělají konstruktéři. Konstruktor odvozeného objektu totiž od začátku volá konstruktor odpovídajícího objektu. repaint() by měla být odložena na svou rodičovskou: metodu v základní třídě, která ji přepíše.

Sečteno a podtrženo: Špatná kompatibilita C++ / GUI

C++ byl navržen jako „statický“ jazyk:

  • se sledováním tokenů
  • statická kontrola typu
  • se statickou hierarchií tříd
  • žádný svoz odpadu
  • se systémem zpráv bez definovaných hierarchií v době kompilace

GUI objekty:

  • vyznačující se dynamickými objekty a často jedinými svého druhu
  • mají tendenci žít daleko za hranicemi, ve kterých byly vytvořeny
  • hierarchie jsou do značné míry určeny tokem událostí a jejich umístěním, nikoli třídní dědičností
  • hierarchie jsou vytvářeny a ničeny za běhu, často v reakci na nepředvídatelné akce uživatele

C++ není navrženo tak, aby podporovalo dynamické zabezpečení pro zasílání zpráv a přenosy (kromě výjimek). To vše vede k duplikaci grafické sady nástrojů a funkčnosti správce oken, růstu kódu, používání nebezpečných funkcí a odmítání mnoha silné stránky C++.

závěry

Všechny tyto „zádrhely“ samozřejmě nejsou fatální. C++ je všestranný a výkonný jazyk, a proto je schopen vyjádřit všechny možné výpočetní algoritmy. Pokud tedy aplikace vyžaduje dynamické funkce, jako jsou ty, které najdete v tcl/tk, Schéma/Tk, dovětek a podobně; pomocí C++ můžete vždy udělat něco podobného. Na druhou stranu, proč nepoužít jazyk, kde jsou všechny tyto funkce přítomny?

1.1. Ahoj Qt!

Níže je uveden text nejjednoduššího programu Qt:

1 #zahrnout 2 #zahrnout 3 int main(int argc, char *argv) 4 ( 5 QApplication app(argc, argv); 6 QLabel *label = new QLabel("Ahoj, Qt!", 0); 7 app.setMainWidget(label); 8 label ->show(); 9 return app.exec(); 10 ) Zde na řádcích 1 a 2 jsou zahrnuty definice tříd QApplication a QLabel.

Řádek 5 vytváří instanci třídy QApplication, která spravuje prostředky aplikace. Argumenty argc a argv jsou předány konstruktoru QApplication, protože Qt má schopnost zpracovávat argumenty příkazového řádku.

Řádek 6 vytváří vizuální komponentu QLabel, která zobrazuje „Ahoj, Qt!“. V terminologii Qt se nazývají všechny vizuální komponenty, které tvoří GUI widgety(widgety). Tlačítka, nabídky, posuvníky a různé rámečky jsou widgety. Některé widgety mohou obsahovat další widgety, například hlavní okno aplikace je nejběžnějším widgetem, který může obsahovat QMenuBar , QToolBar , QStatusBar atd. Argument 0 předaný konstruktoru QLabel (na řádku 6) je „prázdný“ ( null) ukazatel, který indikuje, že tento widget nemá "master", tzn není součástí jiného widgetu.

Řádek 7 přiřazuje aplikaci "hlavní" widget. Když uživatel zavře "hlavní" widget aplikace (například kliknutím na tlačítko "X" v záhlaví okna), program se ukončí. Pokud program hlavní widget nepřiřadí, bude nadále běžet na pozadí i poté, co uživatel zavře okno.

Na řádku 8 se štítek zviditelní. Widgety jsou vždy vytvářeny neviditelně, aby měl programátor možnost upravit nastavení zobrazení dříve, než se stanou viditelnými.

Řádek 9 přenáší řízení do knihovny Qt. Od této chvíle program přejde do pohotovostního režimu, kdy nedělá nic, jen čeká. akce uživatele jako je stisknutí klávesy nebo tlačítka myši.

Vygeneruje se jakákoli akce uživatele událost(jinými slovy "zpráva"), v reakci na kterou může program zavolat jednu nebo více funkcí. V tomto smyslu se aplikace s grafickým rozhraním zásadně liší od běžných programů s dávkou zpracování dat, které po obdržení vstupu od uživatele samostatně zpracují, produkují výsledky a dokončí svou práci bez dalšího lidského zásahu.

Obrázek 1.1. Okno aplikace ve Windows XP


Nyní je čas otestovat naši aplikaci. Nejprve ale musíte mít nainstalovaný Qt 3.2 (nebo novější) a aby vaše proměnná prostředí PATH obsahovala správnou cestu k adresáři bin. (V systému Windows se nastavení proměnné PATH provádí automaticky během instalace knihovny Qt)

Zkopírujte text programu do souboru s názvem hello.cpp v adresáři hello.

Přejděte do tohoto adresáře a zadejte příkaz:

Qmake -project vytvoří soubor projektu nezávislý na platformě (hello.pro) a poté vydá následující příkaz: qmake hello.pro Tento příkaz vytvoří soubor Makefile založený na souboru projektu. Zadejte příkaz make pro kompilaci programu a poté jej spusťte zadáním Ahoj(ve Windows) popř ./Ahoj(na Unixu) popř otevřete hello.app(v systému Mac OS X). Pokud používáte Windows a používáte Microsoft Visual C++, musíte místo příkazu make zadat příkaz nmake. Jak Alternativní možnost-- můžete vytvořit projekt Visual Studio ze souboru hello.pro spuštěním příkazu: qmake -tp vc hello.pro a poté zkompilovat program ve Visual Studiu.

Obrázek 1.2. Štítek s formátovaným textem.


Teď se pojďme pobavit. Pojďme se změnit vzhledštítky přidáním formátování textu ve stylu HTML. Chcete-li to provést, vyměňte vedení

QLabel *label = new QLabel("Ahoj, Qt!", 0); na QLabel *label = nový QLabel("

Ahoj " "Qt!

", 0); a znovu sestavit aplikaci.


1.2. Zpracování signálu.

Následující příklad ukazuje -- jak zajistit, aby aplikace reagovala na akce uživatele. Tato aplikace obsahuje tlačítko, které po kliknutí ukončí program. Původní text velmi podobný předchozímu příkladu, až na to, že nyní je jako hlavní widget místo QLabel použit QPushButton a je přidán kód, který opravuje skutečnost, že je stisknuto.

Obrázek 1.3. Ukončete aplikaci.


1 #zahrnout 2 #zahrnout 3 int main(int argc, char *argv) 4 ( 5 QApplication app(argc, argv); 6 QPushButton *button = new QPushButton("Quit", 0); 7 QObject::connect(button, SIGNAL(clicked() ), 8 &app, SLOT(quit())); 9 app.setMainWidget(button); 10 button->show(); 11 return app.exec(); 12 ) Widgety Qt mají schopnost odesílat signály, oznamující, že uživatel provedl nějakou akci nebo že widget změnil svůj stav. Například instance třídy QPushButton odešlou signál clicked() do aplikace, když uživatel stiskne tlačítko. Signál lze „propojit“ s funkcí obsluhy (takové funkce obsluhy v Qt se nazývají sloty). Když tedy widget vyšle signál, slot se automaticky zavolá. V našem příkladu jsme připojili signál clicked() z tlačítka do slotu quit() instance třídy QApplication. Volání SIGNAL() a SLOT() jsou definice maker a podrobněji se jim budeme věnovat v další kapitole.

Nyní pojďme vytvořit aplikaci. Doufejme, že jste již vytvořili adresář quit a umístili do něj soubor quit.cpp. Vydejte příkaz qmake, vytvořte soubor projektu a poté podruhé vytvořte soubor Makefile:

Qmake -project qmake quit.pro Nyní sestavte aplikaci pomocí příkazu udělat a spustit to. Pokud kliknete na tlačítko "Ukončit" nebo stisknete klávesu "Mezerník" na klávesnici, aplikace se ukončí.

V následujícím příkladu si ukážeme, jak lze signály a sloty použít k synchronizaci dvou widgetů. Tento program vyzve uživatele k zadání věku. Můžete to provést buď pomocí ovládacích tlačítek počítadla, nebo pomocí posuvníku.

Obrázek 1.4. Věk aplikace.


Aplikace obsahuje tři widgety: QSpinBox , QSlider a QHBox (plocha vodorovného rozložení). Hlavním widgetem aplikace je QHBox . Komponenty QSpinBox a QSlider jsou umístěny uvnitř QHBoxu a jsou podřízených , ve vztahu k němu.

Obrázek 1.5. Widgety aplikace Age.


1 #zahrnout 2 #zahrnout 3 #zahrnout 4 #zahrnout 5 int main(int argc, char *argv) 6 ( 7 aplikace QApplication (argc, argv); 8 QHBox *hbox = nový QHBox(0); 9 hbox->setCaption("Zadejte svůj věk"); 10 hbox-> setMargin(6); 11 hbox->setSpacing(6); 12 QSpinBox *spinBox = nový QSpinBox(hbox); 13 QSlider *slider = nový QSlider(Qt::Horizontal, hbox); 14 spinBox->setRange(0, 130 ); 15 posuvník->setRange(0, 130); 16 QObject::connect(spinBox, SIGNAL(valueChanged(int)), 17 slider, SLOT(setValue(int))); 18 QObject::connect(slider, SIGNAL (valueChanged(int)), 19 spinBox, SLOT(setValue(int))); 20 spinBox->setValue(35); 21 app.setMainWidget(hbox); 22 hbox->show(); 23 return app.exec( ); 24) Řádky 8 až 11 vytvářejí a konfigurují QHBox. SetCaption() se volá k zobrazení textu v titulku okna. Poté nastaví velikost bílého prostoru (6px) kolem a mezi dílčími widgety.

Řádky 12 a 13 vytvoří QSpinBox a QSlider a přiřadí QHBox jako vlastníka.

I když jsme explicitně nenastavili polohu nebo velikost widgetů QSpinBox a QSlider, jsou přesto velmi úhledně umístěny uvnitř QHBoxu. Právě k tomu je QHBox určen. Provádí automatické umisťování dílčích widgetů, přiřazuje jim souřadnice a velikosti umístění v závislosti na jejich požadavcích a jejich vlastním nastavení. Qt má mnoho tříd, jako je QHBox, které nám šetří starosti s ručním nastavováním pozice a velikosti vizuálních komponent.

Řádky 14 a 15 nastavují povolené limity pro počítadlo a posuvník. (Můžeme s jistotou předpokládat, že našemu uživateli pravděpodobně nebude více než 130 let.) Dvě volání connect() na řádcích 16 až 19 synchronizují posuvník a číselník tak, aby vždy zobrazovaly stejnou hodnotu. Kdykoli se změní hodnota jednoho z widgetů, odešle signál valueChanged(int), který přejde do slotu setValue(int) druhého widgetu.

Řádek 20 nastavuje počáteční hodnotu (35) počítadla. Když k tomu dojde, spinner odešle signál valueChanged(int) s hodnotou vstupního argumentu rovnou 35. Toto číslo je předáno do slotu setValue(int) widgetu QSlider, který nastaví hodnotu widgetu na 35. QSlider poté odešle signál valueChanged(int) , protože jeho hodnota se právě změnila, a zavolá tak slot setValue(int) widgetu QSpinBox. Tentokrát ale počítadlo nevyšle signál, protože jeho hodnota již byla rovna 35. To zabraňuje nekonečné rekurzi. Obrázek 1.6 ukazuje tuto situaci.

Obrázek 1.6. Změna jedné hodnoty způsobí změnu jiné.


Řádek 22 zviditelní QHBox (spolu se všemi dílčími widgety).

Přístup rozhraní Qt je velmi snadno pochopitelný a extrémně flexibilní. Obecně platí, že programátor vybere widgety, které potřebuje, umístí je do oblastí rozložení (layoutů), které následně převezmou odpovědnost za umístění widgetů, a nastaví vlastnosti widgetů. V konečné fázi jsou prostřednictvím mechanismu signálů a slotů vytvořeny vztahy s widgety, které určují chování uživatelského rozhraní.

1.3. Práce s systém nápovědy.

Systém nápovědy v Qt je snad nejzákladnějším nástrojem pro každého vývojáře. Popisuje všechny třídy a funkce v této knihovně. (Dokumentace pro Qt 3.2 obsahuje více než 400 tříd a 6 000 funkcí.) V této knize se setkáte s mnoha třídami a funkcemi Qt, ale ne se všemi. Proto je nutné, abyste se seznámili se systémem nápovědy Qt.

Styly widgetů
Snímky obrazovky, které jsme dosud viděli, byly pořízeny na Windows XP. Vzhled widgetů se však liší v závislosti na platformě, na které aplikace běží. Na druhou stranu je Qt schopno napodobit vzhled a chování kterékoli z podporovaných platforem.



Poslední aktualizace: 26.05.2019

V Xamarin.Forms je vizuální rozhraní tvořeno stránkami. Stránka je objekt třídy Page , zabírá celý prostor na obrazovce. To je to, co vidíme na obrazovce mobilní zařízení je stránka. Aplikace může mít jednu nebo více stránek.

Stránka přijímá jeden z kontejnerů rozvržení jako obsah, který zase obsahuje standardní vizuální prvky, jako jsou tlačítka a textová pole, a také další prvky rozvržení.

Vezměme projekt HelloApp vytvořený v předchozím tématu (nebo vytvořte nový). Ve výchozím nastavení je celé rozhraní vytvořeno ve třídě App, která se nachází v souboru App.xaml.cs a představuje aktuální aplikaci:

Jeho výchozí kód je:

Použití systému; pomocí Xamarin.Forms; pomocí Xamarin.Forms.Xaml; jmenný prostor HelloApp ( veřejná částečná třída App: Aplikace ( public App() ( InitializeComponent(); MainPage = nová MainPage(); ) chráněné přepsání void OnStart() ( // Ošetření při spuštění aplikace ) chráněné přepsání void OnSleep() ( / / Zpracovat, když aplikace spí ) chráněné přepsání void OnResume() ( // Zpracovat, když se aplikace obnoví ) ) )

Třída App začíná konstruktorem, kde se nejprve zavolá metoda InitializeComponent(), která inicializuje objekt, a poté se nastaví vlastnost MainPage. Prostřednictvím této vlastnosti se nastavuje třída App domovská stránka aplikací. V tomto případě je definována třídou HelloApp.MainPage, což je třída definovaná v souborech MainPage.xaml a MainPage.xaml.cs.

Tato cesta ale není jediná. Xamarin.Forms umožňuje vytvořit vizuální rozhraní buď pomocí kódu C# nebo deklarativně pomocí jazyka xaml, podobného html, nebo kombinací těchto přístupů.

Vytvoření rozhraní z kódu C#

Do projektu HelloApp přidáme běžnou třídu C#, kterou nazveme StartPage .

A definujte v této třídě následující obsah:

Použití Xamarin.Forms; jmenný prostor HelloApp ( třída StartPage: ContentPage ( public StartPage() ( Záhlaví štítku = new Label() ( Text = "Dobrý den z Xamarin Forms" ); this.Content = záhlaví; ) ) )

Tato třída představuje stránku, takže dědí z třídy ContentPage. Konstruktor vytvoří popisek s textem, který se nastaví jako obsah stránky (this.Content = záhlaví).

Chcete-li označit MainPage jako úvodní stránka, změňte třídu aplikace:

Použití Xamarin.Forms; jmenný prostor HelloApp ( veřejná částečná třída App: Aplikace ( public App() ( InitializeComponent(); MainPage = new StartPage(); ) chráněné přepsání void OnStart() ( // Ošetření při spuštění aplikace ) chráněné přepsání void OnSleep() ( / / Zpracovat, když aplikace spí ) chráněné přepsání void OnResume() ( // Zpracovat, když se aplikace obnoví ) ) )

Vlastnost MainPage nyní odkazuje na nově vytvořenou StartPage.

Za zmínku také stojí, že Visual Studio má připravenou šablonu pro přidávání nových tříd stránek s nejjednodušším kódem. Chcete-li tedy přidat novou stránku, musíte při přidávání nového prvku vybrat šablonu Obsahové stránky (C#):

Tato třída je přidána do hlavního projektu řešení (v tomto případě je to HelloApp).

Přidaná třída stránky bude mít následující kód:

Použití systému; pomocí System.Collections.Generic; pomocí System.Linq; pomocí System.Reflection.Emit; pomocí System.Text; pomocí Xamarin.Forms; jmenný prostor HelloApp ( veřejná třída Stránka1: ContentPage ( veřejná Stránka1() ( Obsah = nový StackLayout ( Děti = ( nový štítek ( Text = "Hello Page" ) ) ); ) ) )

Tato třída bude také dědit ze základní třídy ContentPage a bude mít téměř stejnou organizaci jako třída MainPage vytvořená výše.

A také ve třídě aplikace můžeme tuto stránku nastavit jako úvodní stránku:

Použití Xamarin.Forms; jmenný prostor HelloApp ( veřejná částečná třída App: Aplikace ( public App() ( InitializeComponent(); MainPage = new Page1(); ) //........... ) )