Qt-ohjelmointi
Signals & Slots

Signaalien ja Slottien avulla oliot voivat kommunikoida keskenään. QObject-luokan connect-funktiolla ensimmäisen olion signaali-funktio voidaan kytkeä toisen olion slot-funktioon.

connect-funktion syntaksi on seuraava

QObject::connect(object1, SIGNAL(signaali-funktio), object2, SLOT(slot-funktio) );

connect()-funktiolla on siis neljä parametriä: lähettäjä, lähettäjän signaali, vastaanottaja ja vastaanottajan slot.

Signaalin ja slotin välinen yhteys voidaan poistaa. Poistamista tarvitaan harvoin, sillä Qt purkaa yhteyden olion tuhoutuessa. Purkaminen tapahtuu kutsumalla disconnect()-funktiota samoilla parametreillä, millä connect()-funktiotakin kutsuttiin.

Qt:n Signals ja slots systeemi korvaa callbackien käytön. Sitä voidaan käyttää siis esimerkiksi asynkronisten-funktioiden kanssa tai tilanteissa joissa avataan uusi form ja sieltä pitää saada jokin tieto alkuperäiseen ikkunaan.

Seuraavassa esimerkissä ideana on, että avataan uusi form ja siellä annettu nimi halutaan saada alkuperäiseen formiin (mainwindow). esimerkissä kokeillaan kahdenlaista signaalia: toinen ei välitä dataa ja toinen välittää.

  1. Tee QtWidget sovellus(nimeltään signalSlot), jossa MainWindow:ssa on kaksi buttonia btnData1 ja btnData2 (kuva1)
  2. Luo uusi Qt Designer Form Class ja anna nimeksi Form1
  3. Lisää Form1:een lineEdit ja kaksi buttonia btnSave1 ja btnSave2(kuva2). Lisää buttoneille clicked slot
  4. Lisää Form1:een
    • private muuttuja QString fname ja sille getter ja setter
    • private osioon
      void mySignal1();
      void mySignal2(QString);
      
    • btnSave1:n clicked metodiin koodi
      setFname(ui->textName->text());
      emit mySignal1();
      this->close();
      
    • btnSave2:n clicked metodiin koodi
      setFname(ui->textName->text());
      emit mySignal2(fname);
      this->close();
      
  5. MainWindow:ssa
    • buttoneille btnData1 ja btnData2 clicked slotit
    • mainwindow.h tiedostoon private osaan Form1 *objectForm1;
    • mainwindow.h tiedoston private.slots osaan
      void data1Slot();
      void data2Slot(QString);
      
    • mainwidow.cpp konstruktoriin objectForm1=new Form1(this);
    • mainwindow btnData1:n clicked metodiin
      connect(objectForm1, SIGNAL(mySignal1()), this, SLOT(data1Slot()));
      objectForm1->open();
      
    • mainwindow btnData2:n clicked metodiin
      connect(objectForm1, SIGNAL(mySignal2(QString)), this, SLOT(data2Slot(QString)));
      objectForm1->open();
      
    • mainwidow.cpp tiedostoon
      void MainWindow::data1Slot()
      {
          QString data1=objectForm1->getFname();
          qDebug() << data1;
      }
      
      void MainWindow::data2Slot(QString data2)
      {
          qDebug() << data2;
      }
      

Huomioita edellisestä esimerkistä

  1. mysignal1() ei välitä dataa
  2. mySignal2(QString) välittää QString-tyyppistä dataa
  3. huomaa miten näiden signaaleja käsittelevät connect-metodien toteutukset poikkeavat toisistaan:
        connect(objectForm1, SIGNAL(mySignal1()), this, SLOT(data1Slot()));
        connect(objectForm1, SIGNAL(mySignal2(QString)), this, SLOT(data2Slot(QString)));
        

Kumpaa kannattaa käyttää? Edellisessä esimerkissä kumpikin toimii, mutta mySignal1:n tapauksessa SLOT-funktiossa on erikeen haettava data:

    QString data1=objectForm1->getFname();)
    



kuva1


kuva2

HTTP request

Kun suoritetaan HTTP-request, niin connect-metodin toteutus voi olla seuraava:

    connect(manager, SIGNAL(finished (QNetworkReply*)),this, SLOT(getBookSlot(QNetworkReply*)));
    
Tässä tapauksessa tuota finished-signaalia ei kirjoiteta itse, vaan se emitoidaan automaattisesti, kun HTTP-reply on saatu.



Toggle Menu