IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

5. diel - Jednoduchá kalkulačka v Qt a C ++ - Layout

V minulej lekcii, Reťazca v Qt - QString a QChar , sme niečo povedali o reťazcoch v Qt a v C ++. Dnes začneme tvoriť už nejakú zaujímavejšie aplikáciu, veľmi jednoduchú kalkulačku. Bude mať dve vstupné polia a štyri základné operácie: násobenie, delenie, sčítanie a odčítanie.

Dnes nám bude stačiť obyčajné okno bez toolbarov, menu, stavového riadku a takých podobných vymožeností:-) Qt je založené na architektúre MVC, teda presnejšie povedané na architektúre Model - View, pretože pohľad zastupuje aj funkciu Controller - spracovanie požiadaviek. Ak ste sa s touto architektúrou ešte nestretli, dôležité je, že oddeľujeme kód logiky aplikácie (v našom prípade teraz trieda s výpočtami pre kalkulačku) od prezentácie, čo je v našom prípade kód definujúce a obsluhujúci formulár. Nikdy teda nebudeme vykonávať nič zložité priamo v súbore s formulárom, ale iba tu prevoláte metódy nejaké ďalšie triedy, v ktorej bude ďalší kód umiestnený.

Návrh aplikácie

Celý návrh môžeme urobiť niekoľkými spôsobmi:

  • Od modelu - teda prvýkrát navrhnúť, čo bude základ logiky, a to potom zobraziť vo formulári.
  • Od view - pohľadu: teda preskúmať, čo budeme zobrazovať, a potom si k tomu urobiť logickú časť.
  • Od každého niečo - postupne niečo zobraziť. Potom urobiť kus logiky, zas to zobraziť, alebo aj opačne.

Tu som zvolil druhú variantu. Vytvoríme si najprv kompletné okno a jeho rozvrhnutie, čím sa rozhodneme, čo kde má byť zobrazené. Až potom, v budúcej lekcii, si vytvoríme triedu, ktorá nám potrebné dáta poskytne, keď o ne požiadame.

Návod na použitie aplikácie

Kalkulačka bude fungovať takto:

  • Zadáme celé číslo do jedného potom do druhého vstupného poľa
  • Zvolíme operáciu medzi číslami
  • Zvolíme číselnú sústavu na zobrazenie
  • Stlačíme tlačidlo pre výsledok. Ten sa ukáže, ak nenastala chyba. Pri chybe zadaní, alebo iné chybe, sa zobrazí krátky dialóg pomocou QMessageBox.

Založenie projektu

Projekt tentoraz založíme len na QWidget, ktorý môžeme použiť aj ako základ aplikácie. Skoršie lekcie mali za úlohu ukázať základ komplexné aplikácie az čoho sa skladá celé okno, preto sme v nich použili QMainWindow. V kalkulačke však nebudeme potrebovať menu, toolbar a iné veci. Práve preto radšej použijeme QWidget, ktorý bude fungovať ako plnohodnotné okno aj s ikonou, titulkom, frontom udalostí a všetkým potrebným.

Nový projekt už založiť vieme. Len v jednej chvíli to chce maličkú zmenu. Predovšetkým si pomenujeme triedu okna Kalkulacka, hlavne žiadna diakritické znamienka, a QMainWindow zmeníme na QWidget:

Založenie projektu pre kalkulačku v C ++ a Qt frameworku - Qt - Okenné / formulárové aplikácie v C ++

Tiež som si pre vás pripravil ikonu okna:

Ikona okna kalkulačky v C ++ - Qt - Okenné / formulárové aplikácie v C ++

Tú už tiež vieme nastaviť. Pridáme nový súbor Qt - Resource. Pokojne si ikonu môžete stiahnuť a použiť. Alebo si urobiť svoju či nájsť inú vhodnú. Inak je postup vlastne rovnaký ako v predchádzajúcich lekciách.

Návrh používateľského rozhrania

Som zo starej školy a rád používam papier a ceruzku. Proste keď chcem urobiť nejakú grafiku v programe, tak si ju nakreslím na papier a potom sa rozhodnem aká technika na to bude najlepšie. Ani tu to nebude inak:

Návrh užívateľského rozhrania pre Qt aplikáciu v C ++ - Qt - Okenné / formulárové aplikácie v C ++

Keď som sa dlho pozeral na obrázok vyššie, došlo mi, že tabuľka (mriežka) je úplne ideálny pre rozvrhnutie všetkých prvkov. Použijeme teda QGridLayout. Je to veľmi flexibilný rozvrhnutie. Každý prvok má svoju vlastnú "bunku", avšak môže ich mať aj niekoľko - ako v riadku tak i v stĺpci. Tiež je možné nastaviť aj rôzne medzery medzi bunkami. Výsledný formulár pre kalkulačku bude potom vyzerať nasledovne:

Kalkulačka v Qt a C ++ - Qt - Okenné / formulárové aplikácie v C ++

Nemohol som odolať a preto výsledok budeme zobrazovať ako na naozajstnom segmentovom displeji kalkulačky. Je pravda, že ovládací prvok QLCDNumber vie zobraziť len celé čísla, zato v niekoľkých sústavách - šesťnástková, decimálna, osmičková a binárne. Toho predsa musíme tiež využiť, preto pridáme aj štyri prepínače - QRadioButton, ktoré umožní zmeniť zobrazenie pre danú číselnú sústavu.

Aby sme nemuseli riešiť, aké číslo alebo text používateľ zadal, použijeme pre každý operand (číslo) zvláštne vstup. Ten bude bohužiaľ len textový QLineEdit, z ktorého získame reťazec QString, teda aj tak si budeme musieť zabezpečiť, aby užívateľ naozaj vložil celé číslo a nie čosi podivného.

Dlho som rozmýšľal, či pre voľbu operácie použiť tlačidlá, zoznam alebo rozbaľovací zoznam - ComboBox... Výhra padla opäť na RadioButton, užívateľsky je to pre tento účel prívetivé. Lenže tu budeme mať dve sady prepínačov a Qt všetko, čo sa definuje v jednom kontexte, berie, že to k sebe patria. Teda tieto dve skupiny musíme od seba oddeliť. K tomu doslova nabáda trieda QButtonGroup.

Pre zobrazenie výsledku výpočtu bude potom najlepšie obyčajné tlačidlo.

Kalkulacka.h

Najprv si modifikujeme hlavičkový súbor kalkulačky, kde doplníme potrebné ukazovatele. Inak si myslím, že v tomto súbore nie je extra čo vysvetľovať. O všetkých použitých triedach si ešte podrobnejšie povieme pri súbore kalkulacka.cpp. Obsah kalkulacka.h je nasledujúci:

#ifndef KALKULACKA_H
#define KALKULACKA_H

#include <QWidget>
#include <QGridLayout>
#include <QLCDNumber>
#include <QRadioButton>
#include <QButtonGroup>
#include <QLineEdit>
#include <QPushButton>

class Kalkulacka : public QWidget
{
    Q_OBJECT

public:
    Kalkulacka(QWidget *parent = 0);
    ~Kalkulacka();

    QGridLayout *mainLayout;

    QLCDNumber *display;

    QRadioButton *btnDec;
    QRadioButton *btnHex;
    QRadioButton *btnOct;
    QRadioButton *btnBin;

    QButtonGroup *numeralButtons;

    QLineEdit *leftOperand;
    QLineEdit *rightOperand;

    QRadioButton *btnPlus;
    QRadioButton *btnMinus;
    QRadioButton *btnTimes;
    QRadioButton *btnDivide;

    QButtonGroup *operationButtons;

    QPushButton *btnEqual;
};

#endif // KALKULACKA_H

Kalkulacka.cpp

Rovno prejdeme aj do súboru s implementáciou a vložíme do neho nasledujúci kód, ktorý si vzápätí vysvetlíme:

#include "kalkulacka.h"

#include <QIcon>

Kalkulacka::Kalkulacka(QWidget *parent)
    : QWidget(parent)
{
    mainLayout = new QGridLayout();

    display = new QLCDNumber();
    mainLayout->addWidget(display, 1, 1, 1, 4);

    btnHex = new QRadioButton("HEX", this);
    btnDec = new QRadioButton("DEC", this);
    btnOct = new QRadioButton("OCT", this);
    btnBin = new QRadioButton("BIN", this);

    numeralButtons = new QButtonGroup();

    mainLayout->addWidget(btnDec, 2, 1);
    mainLayout->addWidget(btnHex, 2, 2);
    mainLayout->addWidget(btnBin, 2, 3);
    mainLayout->addWidget(btnOct, 2, 4);

    numeralButtons->addButton(btnHex);
    numeralButtons->addButton(btnDec);
    numeralButtons->addButton(btnOct);
    numeralButtons->addButton(btnBin);

    leftOperand = new QLineEdit();
    rightOperand = new QLineEdit();

    mainLayout->addWidget(leftOperand, 3, 1, 1, 2);
    mainLayout->addWidget(rightOperand, 3, 3, 1, 2);

    btnPlus = new QRadioButton("+", this);
    btnMinus = new QRadioButton("-", this);
    btnTimes = new QRadioButton("*", this);
    btnDivide = new QRadioButton("/", this);

    operationButtons = new QButtonGroup();

    operationButtons->addButton((btnPlus));
    operationButtons->addButton((btnMinus));
    operationButtons->addButton((btnTimes));
    operationButtons->addButton((btnDivide));

    mainLayout->addWidget(btnPlus, 4, 1);
    mainLayout->addWidget(btnMinus, 4, 2);
    mainLayout->addWidget(btnTimes, 4, 3);
    mainLayout->addWidget(btnDivide, 4, 4);

    btnEqual = new QPushButton(tr("Spočítej"));

    mainLayout->addWidget(btnEqual, 5, 1, 1, 4);

    setLayout(mainLayout);

    btnDec->setChecked(true);
    btnPlus->setChecked(true);
}

Kalkulacka::~Kalkulacka()
{
    if (btnEqual != NULL) { delete btnEqual; }

    if (operationButtons != NULL) { delete operationButtons; }

    if (btnPlus != NULL) { delete btnPlus; }
    if (btnMinus != NULL) { delete btnMinus; }
    if (btnTimes != NULL) { delete btnTimes; }
    if (btnDivide != NULL) { delete btnDivide; }

    if (leftOperand != NULL) { delete leftOperand; }
    if (rightOperand != NULL) { delete rightOperand; }

    if (numeralButtons != NULL) { delete numeralButtons; }

    if (btnHex != NULL) { delete btnHex; }
    if (btnDec != NULL) { delete btnDec; }
    if (btnBin != NULL) { delete btnBin; }
    if (btnOct != NULL) { delete btnOct; }

    if (mainLayout != NULL) { delete mainLayout; }

    setWindowIcon(QIcon(":/img/mainIcon"));
    resize(640, 480);
}

Na úplnom začiatku sme vytvorili objekt tabuľkového layoutu a následne objekt LCD a umiestnili ho do layoutu pomocou mainLayout->addWidget(display, 1, 1, 1, 4);. Tu stojí za všimnutie parametre, ktorý mi sú:

  • ukazovateľ na widget
  • riadok v tabuľke - počítané od 1 do n
  • stĺpik v tabuľke - opäť od 1 do n
  • počet zlúčených riadkov, cez ktoré má ovládací prvok presahovať (pre hodnotu 1 sa nič nestane)
  • počet zlúčených stĺpcov, tu teda prvok zaberie 4 stĺpce

Potom vyrobíme prvú skupinu prepínačov pre prechody z jednej číselnej sústavy do druhej a umiestnime ju do layoutu pomocou mainLayout->addWidget(btnDec, 2, 1);... Tak pridáme aj skupiny tlačidiel: operationButtons->addButton((btnPlus));... Tu si možno všimnúť, že dva parametre sme vynechali, pretože nie sú potrebné a Qt nám to umožňuje. Jednoducho len volíme riadok a stĺpec.

Pre istotu znovu pre zapamätanie: QGridLayout si svoje pozície čísluje od jednotky, nie od nuly ako pole v C.

leftOperand = new QLineEdit(); a rightOperand = new QLineEdit(); sú dve dôležité editačné políčka na vloženie dvoch vstupných čísel. Samozrejme je hneď umiestnime do "tabuľky" rozloženie prvkov ako mainLayout->addWidget(leftOperand, 3, 1, 1, 2);. Každé z nich bude zaberať polovicu riadku, teda 2 stĺpce.

Nasledujú "prepínače" pre početné operácie. Tu asi nie je tiež nie je veľmi čo vysvetľovať, pretože je to rovnaký postup, ktorý bol použitý u * prepínačov "číselných sústav.

Celý layout nakoniec vložíme do widgetu pomocou setLayout(mainLayout); a pre istotu, aby bolo jasné, že počítame v dekadickej sústave a základné operácie je sčítanie, nastavíme dané prepínače ako aktívny / zapnutej: btnDec->setChecked(true); a btnPlus->setChecked(true);

A úplne na koniec si nastavíme ikonu a veľkosť okna: setWindowIcon(QIcon(":/img/mainIcon")); resize(640, 480);

Ako posledný máme tlačidlo pre výpočet. Také už sme robili skoro na začiatku kurzu. Avšak tu je drobná zmena, ktorá asi bude neskôr dosť dôležitá a myslím, že sa z nej stane aj dosť dobrý zvyk.

Medzinárodné rozhranie

btnEqual = new QPushButton(tr("Spočítej"));

Na kódu vyššie je samozrejme zaujímavé použitie funkcie tr(QString). Tá sa dá vyložiť ako: Prelož reťazec. Teda ak všetky reťazce budeme uzatvárať do tejto funkcie, máme aplikáciu pripravenú k prípadným viacjazyčným mutáciám. Počas kurzu si tieto možnosti ešte predstavíme.

Záver

Tým máme hotové rozvrhnutie aplikácie. Pokojne si ju preložte a spustite. Síce nič zatiaľ nerobí, ale vyzerá pekne:-)

Nabudúce, v lekcii Jednoduchá kalkulačka v Qt a C ++ - Model , si vytvoríme jednoduchý model. Síce je kalkuačka jednoduchá, ale pracujeme v MVC (MV) frameworku, tak by bolo dobré dodržať túto architektúru. Naozaj sa bude hodiť neskôr, keď si osvojíme dobré návyky čo najskôr. Nabudúce tiež ošetríme užívateľské vstupy a sprevádzkujeme prepínače.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 79x (12.46 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C++

 

Predchádzajúci článok
Reťazca v Qt - QString a QChar
Všetky články v sekcii
Qt - Okenné / formulárové aplikácie v C ++
Preskočiť článok
(neodporúčame)
Jednoduchá kalkulačka v Qt a C ++ - Model
Článok pre vás napísal Virlupus
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje webovým aplikacím, skladově-účetnímu softwaru, 3D grafice, lexiální analýze a parserování. Studuje fyziku na MFF UK. Učil IT na střední škole.
Aktivity