Předvánoční slevová akce PHP týden
Pouze tento týden sleva až 80 % na PHP e-learning!
Využij předvánočních slev a získej od nás 20 % bodů zdarma! Více zde

Lekce 3 - Dokončení prvního okna v Qt a C++ - Tlačítko

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, První okno v Qt a C++, jsme si vytvořili svou první formulářovou aplikaci v Qt frameworku pro C++. V dnešním Qt tutoriálu do našeho prázdného okna vložíme první komponentu, kterou bude tlačítko, které po kliknutí okno zavře.

Rozložení okna

Pro tento úkol si však musíme více povědět o QMainWindow, hlavně o jeho vnitřním grafickém rozložení. To demonstruje diagram níže:

Grafické rozložení QMainWindow

Všimněte si, že okno se dělí na pět základních oblastí:

  • První a poslední je určena pro hlavní nabídku a stavový řádek.
  • Mezi mini je oblast pro panely nástrojů, kde jeden toolbar můžete posouvat (myší nebo programově) dokola, případně čtyři panely umístit po všech stranách nebo různě experimentovat s jejich rozmístěním v této oblasti.
  • Další část dock widgets je určena různé doplňující widgety, které mají být trvale součástí okna. Tuto možnost jsem zatím nijak moc nevyužil, snad jen pokusně. To ovšem neznamená, že se k ní podrobněji nedostaneme.
  • Poslední součást Hlavního Okna je centrální widget. Zde se bude odehrávat vše podstatné, neboť právě tady je místo pro GUI, tedy grafické uživatelské rozhraní naší aplikace.

Widget a manažery rozložení

Abychom mohli do okna něco přidat, je třeba si vytvořit tedy centrální pomocný widget. Použijeme naprosto základní QWidget, od nějž jsou odvozeny všechny ostatní grafické (a i další) části aplikace.

Manažery rozložení

Další důležitou informací je, že Qt využívá systém manažerů rozložení - layouty, které vydají na samostatnou lekci. Kdychom totiž komponenty ve formuláři umístili na absolutní souřadnice, okno by nereagovalo na zvětšení/změnšení nebo dokonce na změnu rozlišení nebo DPI. Layouty umožňují komponenty na formuláři automaticky uspořádávat a každý to dělá různým způsobem (např. vedle sebe nebo do tabulky). My dnes použijeme tzv. QHBoxLayout, který komponenty skládá vedle sebe a případně je zalomí na další řádek, pokud na formuláři již na další není místo.

Přidání tlačítka do projektu

Otevřeme tedy minulý projekt s oknem, abychom nemuseli začínat odznovu, a trochu si jej poupravíme.

mainwindow.h

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Do hlavičkového souboru přidáme pomocný widget, zmíněný layout a potom i samotné tlačítko:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QPushButton>
#include <QHBoxLayout>
#include <QWidget>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QWidget * central;
    QHBoxLayout *layout;
    QPushButton *cudlik;
};

Třídě jsme přidali následující atributy:

  • QPushButton - Tlačítko.
  • QHBoxLayout - Jednoduchý layout, který jednotlivé prvky skládá vedle sebe do řádky a když je řádka plná, prostě přejde na další. Layouty jsou způsob, jakým komponenty na formuláře umisťujeme. V našem případě pouze jednoho tlačítka bychom mohli použít klidně i některý jiný.
  • QWidget - Komponenta nám poslouží jako obsah centrální části hlavního okna. Při rozsáhlejších programech bychom si pro něj vytvořili samostatnou třídu. Zatím to však není nutné.

mainwindow.cpp

Přejdeme do souboru mainwindow.cpp a inicializujeme zde ukazatele na všechny tři instance a ještě provedeme několik úprav, které si hned popíšeme. Výsledný kód souboru vypadá takto:

#include "mainwindow.h"

#include <QIcon>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    resize(640,480);
    setWindowTitle("Můj první program");

    /* setToolTip("Toto okno nic nedělá"); */

    setWindowIcon(QIcon(":/img/mainIcon"));
    central = new QWidget(this);

    layout = new QHBoxLayout();
    central->setLayout(layout);

    cudlik = new QPushButton("Zavři mě");
    cudlik->setToolTip("Zavřu celé okno!!!");

    layout->addWidget(cudlik);

    setCentralWidget(central);
}

MainWindow::~MainWindow()
{
    if (cudlik != NULL) { delete cudlik; }
    if (layout != NULL) { delete layout; }
    if (central != NULL) { delete central; }
}

V kódu provádíme následující:

  • Vytvoříme si instanci widgetu a layoutu: central = new QWidget(this);, layout = new QHBoxLayout();
  • Našemu widgetu nastavíme daný layout: central->setLayout(layout);
  • Dále potřebujeme ono důležité tlačítko a zároveň mu přidělíme text (lze třeba i ikonu): cudlik = new QPushButton("Zavři mě"); Pokud chcete, můžete tlačítko doplnit i o rychlou nápovědu: cudlik->setToolTip("Zavřu celé okno!!!");
  • Tlačítko umístíme do layoutu. Protože je jen jedno a nemá nastavenou velikost, tak vyplní celou šířku okna: layout->addWidget(cudlik);
  • Poslední krok je náš widget umístit do centrální oblasti okna: setCentralWidget(central);

Pozornost věnujte destruktoru okna - všechny objekty vytvořené pomocí operátoru new jsou po testu na jejich existenci poctivě smazány operátorem delete. Berme to jako nutný zvyk, aby nedocházelo k zaplnění paměti, která sice nikomu již nepatří, ale již se nedá alokovat. Prostě jakmile někde použijete new, raději okamžitě v destruktoru zapište příkaz pro zrušení objektu. Osobně vím, že pokud to neudělám hned, může se stát, že zapomenu.

Tak to je celé. Můžeme vyzkoušet:

Qt Tlačítko v C++

Tlačítko ještě samozřejmě po kliknutí nic neudělá.

Reakce kliknutí na tlačítko

Naším přáním bylo, aby tlačítko po stisknutí zavřelo okno. Zde se dostáváme k mimořádně silnému nástroji, který se nazývá signály a sloty. O co kráčí? Každá třída odvozená od QObject může posílat a přijímat zprávy (informace o událostech) z dalších tříd a reagovat na ně. Dokonce je možný oboustranný přenos.

Signály

Pro naše tlačítko existuje již předdefinovaný signál v rodičovské třídě QAbstractButton. Nás bude zajímat signál clicked(bool checked = false), který je vyvolán pokud na komponentu bylo kliknuto. V jiných programovacích jazycích se tomuto mechanismu často říká události.

Trochu problém je v tom, že signál se pouze zařadí do fronty událostí a pak už je mu jedno co se s ním stane. To je naše starost, aby byl správně zpracován.

Sloty

My potřebujeme, aby signál přijala aplikace. K tomu nám pomůže třída QApplication, která je odvozena od QCoreApplication a obsahuje slot (možný příjemce signálu) quit(), který aplikaci ukončí.

mainwindow.cpp

Nyní je nutné programu oznámit, že má tento signál i slot propojit. Myslím, že uvést jen dva dané řádky kódu bude stačit:

// mainwindow.cpp
...
#include <QApplication>
...
connect(cudlik, SIGNAL(clicked()), qApp, SLOT(quit()), Qt::QueuedConnection);

Co jsme to vlastně provedli?

  • Vložením knihovny QApplication jsme získali možnost přístupu k unikátnímu ukazateli na celou aplikaci pomocí makra qApp.
  • Metoda connect, která je definována v základní třídě QObject, propojuje signály a sloty. Říká, že tlačítko spolu se signálem clicked() chceme spojit s aplikací a jejím slotem quit().
  • Qt::QueuedConnection je taková dobrá praxe, jež umožní řadit události do fronty. Jinak by se mohlo stát, že aplikace ještě něco potřebuje dokončit a při ukončení by to nestihla. Pak třeba přijdete o nějaká data, uložení konfigurace atp.

Tak a máme to celé, stačí přeložit spustit a vyzkoušet, že aplikace opravdu funguje. Příště, v lekci Řetězce v Qt - QString a QChar, si představíme třídu QString, která se nám bude v dalších lekcích hodit.


 

Stáhnout

Staženo 40x (81.75 kB)
Aplikace je včetně zdrojových kódů v jazyce C++

 

 

Článek pro vás napsal virlupus.soft
Avatar
Jak se ti líbí článek?
2 hlasů
Autor se věnuje webovým aplikacím a skladově-účetnímu softwaru. Snaží se uvést zpět PC-Fand v Javě i Pythonu. Lexiální analýze a parserování. Studuje fyziku na MFF UK. Učil IT na střední škole.
Předchozí článek
První okno v Qt a C++
Všechny články v sekci
Okenní/formulářové aplikace v Qt pro C++
Miniatura
Následující článek
Řetězce v Qt - QString a QChar
Aktivity (5)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!