Haideti inapoi in laboratorul de Qt
sa vedem cum au facut programatorii de la Nokia si/sau Digia - aceiasi sunt, o lectie despre butoane puse in niste GroupBox-uri la randul lor puse intr-un layout.
Nota: Daca ati cautat cursul din C11, el este pe pagina anterioara acesteia.
Impartirea proiectului in fisiere si clase:
- un program main.cpp clasic care instantiaza clasa ferestrei principale definita mai jos.
- o declaratie a clasei ferestrei principale: window.h
- o implementare a clasei ferestrei principale: window.cpp
PROGRAMUL PRINCIPAL
Creati main.cpp-ul absolut clasic:
Programul principal include clasa noastra window.h
Sursa:
#include <QApplication>
#include "window.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window window;
window.show();
return app.exec();
}
DECLARATIA CLASEI DE FEREASTRA
Sursa:
#ifndef WINDOW_H
#define WINDOW_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QGroupBox;
QT_END_NAMESPACE
//! [0]
class Window : public QWidget
{
Q_OBJECT
public:
Window(QWidget *parent = 0);
private:
QGroupBox *createFirstExclusiveGroup();
QGroupBox *createSecondExclusiveGroup();
QGroupBox *createNonExclusiveGroup();
QGroupBox *createPushButtonGroup();
};
//! [0]
#endif
Comentarii la setul [0] de linii de cod:
- este o clasa banala, numita Window, derivata public din QWidget, deci are tot ce are QWidget, inclusiv geometrie etc.
- Macroul Q_OBJECT ne spune ca este o clasa cu sloturi si semnale sau ca va fi o clasa cu sloturi si semnale in viitor, daca o mai dezvoltam.
- Constructorul este cel care realizeaza propriuzis fereastra, in codul lui se vor programa construirile tuturor elementelor: layout-ul, (adica schema aceea de cutie cu globuri de craciun, impartita in patrate), GroupBox-urile - remarcati ca anuntam ca vom folosi acea clasa !, restul.
- class QGroupBox; este un fel de declaratie in avans, care e mai rapida la compilare decat includerea clasei cu #include.
- sunt patru metode mari ale obiectului Window, rolul lor este sa construiasca , probabil, portiuni din obiect. Cand constructorul ar fi foarte se poate imparti asa in parti semnificative, si relativ independente. Ele pot fi si programate si testate separat.
In practica n-ar fi rau sa le comentati, cu // in fata, pe ultimele 3 cat scrieti doar codul primeia, ca sa puteti testa cum functioneaza prima parte:
private:
QGroupBox *createFirstExclusiveGroup();
// QGroupBox *createSecondExclusiveGroup();
// QGroupBox *createNonExclusiveGroup();
// QGroupBox *createPushButtonGroup();
Nota: Aceste functii chiar construiesc partile din obiect si returneaza pointeri la ele, ca un fel de new mai evoluat. Acest lucru va conta la implementare.
Sfarsit de comentarii la setul [0] de linii de cod:
Fisierul Windows.cpp, complet:
#include <QtWidgets>
#include "window.h"
//! [0]
Window::Window(QWidget *parent)
: QWidget(parent)
{
QGridLayout *grid = new QGridLayout;
grid->addWidget(createFirstExclusiveGroup(), 0, 0);
grid->addWidget(createSecondExclusiveGroup(), 1, 0);
grid->addWidget(createNonExclusiveGroup(), 0, 1);
grid->addWidget(createPushButtonGroup(), 1, 1);
setLayout(grid);
setWindowTitle(tr("Group Boxes"));
resize(480, 320);
}
//! [0]
//! [1]
QGroupBox *Window::createFirstExclusiveGroup()
{
//! [2]
QGroupBox *groupBox = new QGroupBox(tr("Exclusive Radio Buttons"));
QRadioButton *radio1 = new QRadioButton(tr("&Radio button 1"));
QRadioButton *radio2 = new QRadioButton(tr("R&adio button 2"));
QRadioButton *radio3 = new QRadioButton(tr("Ra&dio button 3"));
radio1->setChecked(true);
//! [1] //! [3]
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(radio1);
vbox->addWidget(radio2);
vbox->addWidget(radio3);
vbox->addStretch(1);
groupBox->setLayout(vbox);
//! [2]
return groupBox;
}
//! [3]
//! [4]
QGroupBox *Window::createSecondExclusiveGroup()
{
QGroupBox *groupBox = new QGroupBox(tr("E&xclusive Radio Buttons"));
groupBox->setCheckable(true);
groupBox->setChecked(false);
//! [4]
//! [5]
QRadioButton *radio1 = new QRadioButton(tr("Rad&io button 1"));
QRadioButton *radio2 = new QRadioButton(tr("Radi&o button 2"));
QRadioButton *radio3 = new QRadioButton(tr("Radio &button 3"));
radio1->setChecked(true);
QCheckBox *checkBox = new QCheckBox(tr("Ind&ependent checkbox"));
checkBox->setChecked(true);
//! [5]
//! [6]
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(radio1);
vbox->addWidget(radio2);
vbox->addWidget(radio3);
vbox->addWidget(checkBox);
vbox->addStretch(1);
groupBox->setLayout(vbox);
return groupBox;
}
//! [6]
//! [7]
QGroupBox *Window::createNonExclusiveGroup()
{
QGroupBox *groupBox = new QGroupBox(tr("Non-Exclusive Checkboxes"));
groupBox->setFlat(true);
//! [7]
//! [8]
QCheckBox *checkBox1 = new QCheckBox(tr("&Checkbox 1"));
QCheckBox *checkBox2 = new QCheckBox(tr("C&heckbox 2"));
checkBox2->setChecked(true);
QCheckBox *tristateBox = new QCheckBox(tr("Tri-&state button"));
tristateBox->setTristate(true);
//! [8]
tristateBox->setCheckState(Qt::PartiallyChecked);
//! [9]
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(checkBox1);
vbox->addWidget(checkBox2);
vbox->addWidget(tristateBox);
vbox->addStretch(1);
groupBox->setLayout(vbox);
return groupBox;
}
//! [9]
//! [10]
QGroupBox *Window::createPushButtonGroup()
{
QGroupBox *groupBox = new QGroupBox(tr("&Push Buttons"));
groupBox->setCheckable(true);
groupBox->setChecked(true);
//! [10]
//! [11]
QPushButton *pushButton = new QPushButton(tr("&Normal Button"));
QPushButton *toggleButton = new QPushButton(tr("&Toggle Button"));
toggleButton->setCheckable(true);
toggleButton->setChecked(true);
QPushButton *flatButton = new QPushButton(tr("&Flat Button"));
flatButton->setFlat(true);
//! [11]
//! [12]
QPushButton *popupButton = new QPushButton(tr("Pop&up Button"));
QMenu *menu = new QMenu(this);
menu->addAction(tr("&First Item"));
menu->addAction(tr("&Second Item"));
menu->addAction(tr("&Third Item"));
menu->addAction(tr("F&ourth Item"));
popupButton->setMenu(menu);
//! [12]
QAction *newAction = menu->addAction(tr("Submenu"));
QMenu *subMenu = new QMenu(tr("Popup Submenu"));
subMenu->addAction(tr("Item 1"));
subMenu->addAction(tr("Item 2"));
subMenu->addAction(tr("Item 3"));
newAction->setMenu(subMenu);
//! [13]
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(pushButton);
vbox->addWidget(toggleButton);
vbox->addWidget(flatButton);
vbox->addWidget(popupButton);
vbox->addStretch(1);
groupBox->setLayout(vbox);
return groupBox;
}
//! [13]
Sfarsitul fisierul Windows.cpp.
Comentariile pe sectiuni:
In imagine: sectiunea [0]
Comentariile sectiunii [0]:
- clasa Windows e derivata din QWidget, iar constructorul ei va face si initializarea partii mostenite, apeland constructorul clasei QWidget.
Asa se explica acel: ": QWidget(parent)".
- in general se pot folosi aceiasi parametri, daca convin, in acest caz pointerul la obiectul parinte.
- In acolada constructorului sunt instructiuni:
-- Se instantiaza un QGridLayout, pointerul la el, returnat de new este grid.
-- Acest grid, fiind din clasa QGridLayout, poseda metoda pentru a adauga alte obiecet cu adrese cunoscute, in layout. Se numeste addWidget().
-- Layout-ul grila este impartit in patru parti, A, B, C, D. Parametrii 0 sau 1 sunt linia si coloana din matrice, B este pe pozitia 1,0 deci aranjarea e ca mai jos:
| 0 1
-------------
0| A C C = nonExclusievGroup
1| B D B = SecondExclusiveGroup
Fiecare addWidget adauga in grila in pozitia indicata obiectul creat la apel. Exemplu: grid->addWidget(createNonExclusiveGroup(), 0, 1);
adauga in grila obiectul din pozitia C, din dreapta sus. rand=0 coloana=1.
-i se pune ferestrei titlu, care poate fi tradus in viitor, de aici tr().
-se redimensioneaza fereastra.
Crearea grupului A: Primul grup exclusiv, comentarii [1]-[3]
- se creaza un GroupBox si trei radio butoane.
- primul radio buton este selectat: setChecked(). metoda e pe lista in doc clasei.
- deocamdata butoanele "plutesc in cutie"
- dar le vom aseza vertical intr-un VBoxLayout.
- si intregului grup ii aplicam layout-ul, astfel ca grupul se va prezenta organizat. [2] final.
- returnam adresa grupului nou creat.
Daca ar fi singur, grupul ar arata asa:
Crearea grupului B: Al doilea grup exclusiv, comentarii [4]-[6]
- si aici am un QGroupBox cu nume traductibil si tasta X pentru actionare
- grupul are propiretatea Checkable = true deci este activabil cu checkbox.
- grupul are proprietatea Checked = false , deci activarea sa este oprita, grupul este inactiv.
(Remarcati ca acest QGroupBox este cumva mai istet decat QButtonGroup).
- sunt create 3 radio butoane, cu nume traductibile si se sugereaza ca se vor putea actiona cu taste diferite: i,o,b
- primul radio buton e actionat
- e creat si un checkbox
- care este deja bifat
- pentru aranjare este creat un layout vertical: QVBoxLayout
- in layout sunt aranjate radio butoanele si checkbox-ul
- addStretch adauga un QSpacerItem, un fel de arculet care se extinde pe restul spatiului.
- se ataseaza groupbox-ului layout-ul, adica se ordoneaza frumos vertical ce este asezat in groupbox.
- se returneaza adresa groupbox-ului.
Daca ar fi singur, al doilea grup, pozitia B, ar arata asa:
Crearea grupului C: Al treilea grup nonexclusiv, comentarii [7]-[9]
- este creat un QGroupBox
- acesta are atributul "flat" ca sa nu arate ca un basorelief pe anumite stiluri. Hm.
- am si trei check-box-uri: checkBox1,checkBox2,tristateBox
- al doilea este bifat
- al treilea este intr-o faza intermediara, nici bifat nici nebifat (are un patrat in mijloc) cel putin pe acest stil.
- avem si un layout vertical
- in care sunt puse checkbox-urile si un arculetz.
- se returneaza adresa grupului.
Daca ar fi singur, al treilea grup, pozitia C, ar arata asa:
Crearea grupului D: Al patrulea grup nonexclusiv, comentarii [10]-[13]
- un groupbox cu check-box de activare [10]
- in grup e un prim buton normal
- al doilea buton, normal, este transformat in ToggleButton, ceea ce se face tratandu-l ca pe un checkbox ! Il facem sa aiba bit on,off si sa fie on.
toggleButton->setCheckable(true);
toggleButton->setChecked(true);
- al trilea buton este aplatizat. Chiar asa arata.
- dintr-un buton pot sa fac un Popup Button, tot cu un truc:
--- creez intai un meniu
--- si ii setez,ii atasez butonului un meniu [12]-[12]
QMenu *menu = new QMenu(this);
menu->addAction(tr("&First Item"));
menu->addAction(tr("&Second Item"));
menu->addAction(tr("&Third Item"));
menu->addAction(tr("F&ourth Item"));
popupButton->setMenu(menu);
....
Daca vreau si un submeniu, procedez ca la meniuri, adica
adaug o noua actiune in meniul vechi, creez un submeniu in care pun cateva
randuri iar noii actiuni din primul meniu ii atasez submeniul, vezi finalul
sectiunii [12]-[13].
- in final realizez un layout, pun toate piesele in el si il atasez grupului
- returnez adresa grupului.
Daca ar fi singur, al patrulea grup, pozitia D, ar arata asa:
Cu toate cele patru groupbox-uri, fereastra arata ca in imagine:
Sfarsit pentru azi.
-----------------------------------------------------------------------------------------------------------------
Nota: Explicatiile proprietatii flat suna asa in documentatie. In practica, pe Linux, la stilul curent, nu am vazut deosebiri.
This property holds whether the group box is painted flat or has a frame
A group box usually consists of a surrounding frame with a title at the top. If this property is enabled, only the top part of the frame is drawn in most styles; otherwise, the whole frame is drawn.
By default, this property is disabled, i.e., group boxes are not flat unless explicitly specified.
Note: In some styles, flat and non-flat group boxes have similar representations and may not be as distinguishable as they are in other styles.
-------------------------------------------------------------------------------------------------------------------
Codul de mai sus fiind sub o anumita licenta, sunt obligat sa includ fisierul cu licenta:
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
Niciun comentariu:
Trimiteți un comentariu