PDA

Visualizza la versione completa : [C++] Usare il metodo QObject::connect delle librerie Qt


gila89
19-10-2013, 14:24
Quello che devo realizzare è molto semplice ma non so come si fa perché è da poco che ho cominciato ad usare le librerie Qt.
Ho realizzato una finestra molto semplice nella quale compaiono 6 QRadioButton (A, B, C, D, E ed F rispettivamente) e un QPushButton chiamato VAI.
L'utente per prima cosa deve cliccare su uno dei 6 QRadioButton (per scegliere l'azione che vuole fare eseguire) e poi deve cliccare sul QPushButton per farla eseguire al programma.
N.B.:Per me è determinante sapere quale QRadioButton è stato premuto perché ognuno di essi corrisponde ad un metodo diverso.
Se stessimo parlando di HTML tutto questo sarebbe un banalissimo form, ma con le Qt come si fa?
P.S.:Ho provato con QObject::connect ma non riesco ad usarlo come vorrei.

MItaly
19-10-2013, 14:47
Io farei così:
definisci un'enum di qualche genere corrispondente alle azioni da effettuare; nel costruttore del QDialog, QMainWindow o quello che è memorizzalo in una property di ciascun radiobutton:


ui->rbPrimoPulsante->setProperty("azione", PrimaAzione);
ui->rbPrimoPulsante->setProperty("azione", SecondaAzione);
// eccetera

Quindi crea uno slot del form del tipo


public slots:
void rb_clicked(bool Checked);

e lega il signal clicked di tutti i radiobutton allo slot in questione, mettendo sempre nel costruttore:


connect(ui->rbPrimoPulsante, SIGNAL(clicked(bool)), this, SLOT(rb_clicked(bool));
// idem per gli altri radiobutton

Nel codice dello slot memorizza l'azione del pulsante premuto in una qualche variabile definita a livello di classe:


void NomeForm::rb_clicked(bool Checked)
{
if(Checked)
this->azione=sender()->getProperty("azione").toInt();
}

A quel punto puoi far generare automaticamente lo slot per il QPushButton al designer del form (click di destro sul button->go to slots->clicked()); qui dentro potrai controllare this->azione e in base a quello fare un'azione o l'altra.

YuYevon
19-10-2013, 14:51
Precisamente, cos'è che non riesci a fare? Devi connettere uno slot al bottone in questione che venga eseguito quando ci si clicka sopra, e nello slot vai a controllare i singoli radio buttons per determinare quale sia stato checkato (col metodo isChecked() della classe QRadioButton) e agire di conseguenza.
Specifica meglio il problema, magari postando del codice per ragionare con qualcosa di concreto.

gila89
19-10-2013, 15:09
@MItaly: puoi dirmi come faccio a creare un enum nella sitassi del c++11? So che rispetto alle versioni precedenti è cambiata (e presumo che tu ti riferisca a questa sintassi)
@YuYevon: hai centrato il problema in pieno

Se serve ecco il codice:


/*La finestra la costruisco nel costruttore della classe mywindow, lì c'è un pulsante che una volta cliccato mi permette di accedere al metodo clickedSlot(), è proprio in questo metodo che mi trovo alle prese con il problema che ho detto prima. Non metto il costruttore perché non c'entra nulla con il problema*/
void mywindow::clickedSlot()
{
QDialog *w = new QDialog(this);
w->setModal(true);
QRadioButton *A = new QRadioButton("A",w), *B = new QRadioButton("B",w);
QRadioButton *C = new QRadioButton("C",w), *D = new QRadioButton("D",w);
QRadioButton *E = new QRadioButton("E",w), *F = new QRadioButton("F",w);
QPushButton *vai = new QPushButton("Vai!",w);

B->move(0,20);
C->move(0,40);
D->move(0,60);
E->move(0,80);
F->move(0,100);
vai->move(300,200);

QObject::connect(/*Usare questo metodo in qualche modo*/);
w->setFixedSize(400,250);
w->move(QApplication::desktop()->screen()->rect().center() - w->rect().center());w->show();
}

void mywindow::actionSlot()
{
//Azioni da eseguire a seconda del QRadioButton che è stato selezionato
}

lovesemiramide
19-10-2013, 17:34
Il C++11 ha aggiunto una nuovo tipo di enum(strongly typed enum), ma ha mantenuto anche quella classica del C. Per maggiori informazioni guarda la documentazione online(link sotto). In questo caso penso possa bastare anche il vecchio tipo di enum.

Per quanto riguarda connect basta guardare la documentazione online(link sotto).
Nel tuo caso connect sarà una cosa del genere:


connect(vai,SIGNAL(clicked()),this,SLOT(actionSlot ()));



In actionSlot controllerai quale radio button è stato selezionato con qualcosa tipo:


void mywindow::actionSlot()
{
if( a->isChecked() ) { /*codice */ }

else if( b->isChecked() ) { /*altro codice */ }

//etc...
}


Links:
C++11 enum: http://en.cppreference.com/w/cpp/language/enum
QObject::connect: http://qt-project.org/doc/qt-5.0/qtcore/qobject.html#connect-3

gila89
19-10-2013, 17:48
Ho capito. Va bene se l'enum lo definisco così?


enum azioni{
PrimaAzione,
SecondaAzione,
TerzaAzione,
//etc. etc.
};

YuYevon
19-10-2013, 17:50
In actionSlot controllerai quale radio button è stato selezionato con qualcosa tipo:


void mywindow::actionSlot()
{
if( a->isChecked() ) { /*codice */ }

else if( b->isChecked() ) { /*altro codice */ }

//etc...
}



in realtà non può farlo perché i radiobuttons A, B etc. sono dichiarati e costruiti localmente al costruttore della finestra, pertanto non referenziabili dallo slot.
Si può risolvere in maniera quick 'n' dirty dichiarando tutti quei widgets come campi della classe stessa (nell'header file relativo) per poi costruirli nel costruttore come è fatto ora, in questo modo saranno referenziabili anche nello slot (che appartiene alla stessa classe).
Un modo più raffinato e strutturato per affrontare la cosa consiste nel creare una classe con una form associata: la form può essere disegnata con il QtDesigner e all'interno della classe i widgets possono essere referenziati con il namespace ui (rimando alla documentazione per dettagli).

gila89
19-10-2013, 18:09
Grazie ai vostri suggerimenti ho risolto :)
Grazie mille a tutti!!!!!!

Loading