Qt-ohjelmointi
Datan välitys

Harjoituksessa tutkitaan kuinka sovellukseen lisätään uusi Form ja kuinka tietoa voidaan välittää formilta toiselle.

show() ja exec()

Uusi ikkuna voidaan avata metodeilla show ja exec. Näiden toiminta on seuraava

  • show avaa uuden ikkunan "ei modaalina" eli aiempaa ikkunaa voidaan edelleen käyttää
  • exec avaa uuden ikkunan modaalina
Modal tarkoittaa sitä, että kun uusi ikkuna on auki, vanhaa ikkunaa ei voida käyttää ennen kuin uusi ikkuna on suljettu. Esimerkiksi tiedoston tallennus dialogi on modaalinen ikkuna.

  1. Tee uusi Qt Widget projekti (nimeltään sendData) ja lisää MainWindow:iin kaksi QPushButton:ia. Nimeä buttonit btnOpenSecondForm ja btnOpenThirdForm ja luo niille clicked-slotit.
  2. Klikkaa hiiren oikealla painikkeella kansiota Forms ja valitse Add New->Qt->Qt Designer Form Class->Widget ja anna nimeksi SecondForm.
    Lisää SecondForm:iin yksi QLabel ja nimeä se labelInfo.
  3. Tee samalla tavalla vielä toinen Form, jonka nimi on ThirdForm.
    Lisää ThirdForm:iin yksi QLabel ja nimeä se labelInfo.
  4. Lisää mainwindow.h tiedoston alkuun rivit
    #include "secondform.h"
    #include "thirdform.h"
    
  5. Kirjoita mainwindow:ssa btnOpenSecondForm buttonin clicked-slottiin koodi
    SecondForm *sf=new SecondForm(this);
    sf->show();
    
    Edellä SecondFormille annetaan argumenttina this, joka siis viittaa MainWindow luokan olioon. Tämän ansiosta oliota sf ei tarvitse tuhota, vaan se tuhoutuu automaattisesti, kun MainWindow olio tuhoutuu.
  6. Huom! SecondForm-olio tuhoutuu vasta, kun MainWindow olio tuhotaan. Jos MainWindow:ta ei suljeta, niin joka kerta kun klikataan "Avaa SecondForm" luodaan uusi SecondForm olio. Tällöin kannattaa laittaa SecondForm olio tuhoutumaan, kun ikkuna suljetaan. Se voidaan tehdä seuraavalla koodilla:

    SecondForm *sf=new SecondForm(this);
    sf->setAttribute(Qt::WA_DeleteOnClose); // Tuhoaa objektin kun ikkuna suljetaan
    sf->show();
    

Datan vienti Luokan muodostimeen
  1. Avaa tiedosto secondform.h ja muokkaa luokan muodostin (constructor) muotoon
    explicit SecondForm(QString name, QWidget *parent = nullptr);
    
    Sanan SecondForm päällä Refactor->Apply Function Signature Changes (jolloin muutos tehdään myös cpp-tiedostoon)
    Edellinen siis lisää muodostimeen QString tyyppisen parametrin nimeltään name
  2. Ja lisää sitten secondform.cpp:ssä rivin ui->setupUi(this); perään rivi
    ui->labelInfo->setText(name);
    
  3. Muokkaa mainwindow.cpp:ssä btnOpenSecondForm clicked eventin koodi seuraavaan muotoon
    SecondForm *objectSecondForm=new SecondForm("Jussi",this);
    objectSecondForm->show();
    
  4. Suorita sovellus ja testaa, että kun avaat secondformin, näet labelissa nimen Jussi
Edellä siis data vietiin SecondFormiin muodostimen kautta. Tehdään seuraavassa datan vienti ThirdFormiin Set-metodin kautta.
Datan vienti Luokan jäsenmuuttujalle
  1. Lisää thirdform.h:ssa privaatti muuttuja QString nameFromMain
  2. Lisää em. muuttujalle public-tyyppinen Setter koodilla
    void ThirdForm::setNameFromMain(const QString &newNameFromMain)
    {
        nameFromMain = newNameFromMain;
        ui->labelInfo->setText(nameFromMain);
    }
    
  3. Kirjoita sitten mainwindow.cpp:ssä btnOpenThirdForm buttonin clicked-slottiin koodi
    ThirdForm *objectThirdForm=new ThirdForm(this);
    objectThirdForm->setNameFromMain("Maija");
    objectThirdForm->show();
    
Datan vienti edelliseen ikkunaan

Jos sinun pitää saada uudesta formista data näkymään alkuperäisessä formissa, kannattaa käyttää signal-slot systeemiä. Tässä konkreettinen esimerkki:

Esimerkki: FourthForm lähettää tekstin takaisin MainWindow:iin

  1. Luo uusi Form nimeltään FourthForm ja lisää siihen:
    • QLineEdit nimeltään lineEditName
    • QPushButton nimeltään btnSendBack (teksti: "Lähetä takaisin")
  2. Lisää fourthform.h tiedostoon signals-osioon uusi signaali:
    signals:
        void dataSentBack(QString data);
    
  3. Lisää fourthform.cpp tiedostoon btnSendBack:n clicked slottiin:
    void FourthForm::on_btnSendBack_clicked()
    {
        QString text = ui->lineEditName->text();
        emit dataSentBack(text);  // Lähetetään signaali
        this->close();            // Suljetaan ikkuna
    }
    
  4. Lisää mainwindow.h tiedostoon:
    #include "fourthform.h"
    
    // private slots osioon:
    private slots:
        void onDataReceivedFromFourth(QString data);
    
  5. Lisää MainWindow:iin QLabel nimeltään labelResult joka näyttää palautetun datan.
  6. Lisää mainwindow.cpp tiedostoon uuden buttonin (btnOpenFourthForm) clicked slottiin:
    void MainWindow::on_btnOpenFourthForm_clicked()
    {
        FourthForm *fourthForm = new FourthForm(this);
        fourthForm->setAttribute(Qt::WA_DeleteOnClose);
    
        // Kytketään FourthForm:n signaali MainWindow:n slottiin
        connect(fourthForm, &FourthForm::dataSentBack,
                this, &MainWindow::onDataReceivedFromFourth);
    
        fourthForm->show();
    }
    
    void MainWindow::onDataReceivedFromFourth(QString data)
    {
        ui->labelResult->setText("Sain takaisin: " + data);
        qDebug() << "Data palautui:" << data;
    }
    

Miten tämä toimii?

  1. FourthForm emittoi signaalin dataSentBack(text) kun käyttäjä klikkaa "Lähetä takaisin" -nappia
  2. MainWindow kuuntelee tätä signaalia connect-kutsun kautta
  3. Kun signaali laukeaa, MainWindow:n slotti onDataReceivedFromFourth() suoritetaan
  4. MainWindow päivittää labelResult:n näyttämään saadun datan

Signal-slot järjestelmän edut:

  • ✅ Selkeä kommunikaatioketju - näet koodista mitkä komponentit keskustelevat keskenään
  • ✅ Löyhä kytkentä - FourthForm ei tiedä MainWindow:sta mitään, se vain lähettää signaalin
  • ✅ Helppo testata - voit kytkeä signaalin mihin tahansa slottiin
  • ✅ Qt:n suositeltu tapa - signal-slot on Qt:n ydin-ominaisuus



Toggle Menu