PDA

View Full Version : Problem with signals & slots



Palmik
16th January 2009, 19:39
Hi... I am writing program which consist from two exactly same parts, so I decided to make one object and then use it twice :)


sifrator.cpp

#include <iostream>
#include <QtGui>
#include <QLocale>
#include <QFile>
#include <QByteArray>
#include <QChar>

#include "sifrator.h"

using namespace std;

EncrypterBody::EncrypterBody(QWidget *parent)
: QWidget(parent)
{

int LABEL_STYLE = QFrame::Sunken | QFrame::Panel;

// Zadavani klicu
QLineEdit *keyPublic = new QLineEdit();
keyPublic->setMinimumWidth(TEXT_W);
keyPublic->setMaximumWidth(TEXT_W);
keyPublic->setMaxLength(50);
keyPublic->setText(trUtf8("Veřejný klÃ*č"));

// Name Label souboru
openFileName = new QLabel;
openFileName->setFrameStyle(LABEL_STYLE);
openFileName->setText(trUtf8("Cesta k otevřenému souboru"));

// Textarea
text = new QTextEdit();
text->setText(trUtf8("Text"));
text->canPaste();
text->setTabStopWidth(500);
text->setMinimumSize(TEXT_W - BUTT_W - 5, TEXT_H);
text->setMaximumSize(TEXT_W - BUTT_W - 5, TEXT_H);

// Buttónky
buttonTranslate = new QPushButton(trUtf8("Přeložit"));
buttonTranslate->setMinimumSize(BUTT_W, BUTT_H);
buttonTranslate->setMaximumSize(BUTT_W, BUTT_H);
connect(buttonTranslate, SIGNAL(clicked()), this, SLOT(textEncryp()));

QPushButton *buttonSave = new QPushButton(trUtf8("Uložit"));
buttonSave->setMinimumSize(BUTT_W, BUTT_H);
buttonSave->setMaximumSize(BUTT_W, BUTT_H);
connect(buttonSave, SIGNAL(clicked()), this, SLOT(saveFile()));

QPushButton *buttonOpen = new QPushButton(trUtf8("NačÃ*st"));
buttonOpen->setMinimumSize(BUTT_W, BUTT_H);
buttonOpen->setMaximumSize(BUTT_W, BUTT_H);
connect(buttonOpen, SIGNAL(clicked()), this, SLOT(openFile()));

// UspořádánÃ* layoutu
QGridLayout *texts_buttons = new QGridLayout;
texts_buttons->addWidget(openFileName, 0, 0);
texts_buttons->addWidget(text, 1, 0, 4, 1);
texts_buttons->addWidget(buttonTranslate, 1, 1);
texts_buttons->addWidget(buttonSave, 2, 1);
texts_buttons->addWidget(buttonOpen, 3, 1);
texts_buttons->setRowMinimumHeight(4, TEXT_H - (3 * BUTT_H + 8));

QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(keyPublic);
layout->addLayout(texts_buttons);
layout->setSizeConstraint(QLayout::SetFixedSize);
setLayout(layout);

}

////////////
// FUNKCE //
////////////

void EncrypterBody::openFile()
{
QFileDialog::Options options;
QString selectedFilter;

QString fileName = QFileDialog::getOpenFileName(this, trUtf8("Vyber textový soubor"), openFileName->text(), trUtf8("Textové soubory (*.txt)"));

if (!fileName.isEmpty())
{
if (fileName != openFileName->text())
{
openFileName->setText(fileName);
}

readFile();
}
}

void EncrypterBody::readFile()
{
text->clear();

QFile file(openFileName->text());
file.open(QIODevice::ReadOnly | QIODevice::Text);

while (!file.atEnd())
{
QString line = QString::fromUtf8(file.readLine());
text->append(line);
}

file.close();
}

void EncrypterBody::saveFile()
{
QString fileName = QFileDialog::getSaveFileName(this, trUtf8("Vyber textový soubor"), openFileName->text(), trUtf8("Textové soubory (*.txt)"));

openFileName->setText(fileName);

QFile file(fileName);
file.open(QIODevice::WriteOnly | QIODevice::Text);

QTextStream out(&file);
out << text->toPlainText();

file.close();
}

QString EncrypterBody::textEncryption()
{
//some unimportant code for encrypting which returns some QString
return textEncrypted;
}

void EncrypterBody::setText(QString string)
{
text->setText(string);
}

/*void EncrypterBody::clickedTranslation(QString string)
{
if (buttonTranslate->clicked())
{
emit clickedTranslation;
}
}*/

sifrator.h

#ifndef SIFRATOR_H
#define SIFRATOR_H

#include <QWidget>
#include <QString>

const int PISMO_V = 12;
const int BUTT_H = 25;
const int BUTT_W = 70;
const int TEXT_H = 200;
const int TEXT_W = 550;

QT_BEGIN_NAMESPACE
class QLabel;
class QTextEdit;
class QPushButton;
QT_END_NAMESPACE

class EncrypterBody : public QWidget
{
Q_OBJECT

public:
EncrypterBody(QWidget *parent = 0);
//
QString textEncryption();

public slots:
void setText(QString string);

/*signals:
void clickedTranslation(QString string);*/

private slots:
void openFile();
//
void readFile();
//
void saveFile();

private:
QTextEdit *text;
//
QLabel *openFileName;
//
QPushButton *buttonTranslate;
};

#endif


main.cpp

#include <QApplication>

#include "sifrator.h"

int main(int argc, char *argv[])
{
QApplication sifrator(argc, argv);

EncrypterBody partEncryption;
EncrypterBody partDecryption;

/*QString string = partEncryption.textEncryption();
QObject::connect(&partEncryption, SIGNAL(clickedTrasnlate(QString)), &partDecryption, SLOT(setText(QString)));*/


partEncryption.show();
partDecryption.show();

return sifrator.exec();
}

So what I am tring to do is, when I click buttonTranslation in object partEncryption I want text in text (QTextEdit) in partDecription to be set to partEncryption.textEncryption() which returns string.
Thanks in advance for any advice. :)

Petr

nifei
17th January 2009, 07:20
So when buttonTranslation is clicked, SIGNAL(clickedTrasnlate(QString)) need to be emitted, I think u could add



: : textEncryp()
{
.....
emit clickedTranslate(textEncrypted);// if this is the right string you want to pass
return something;
}

in SLOT(textEncryp())

BTW, you might miss the slot key word before textEncryp(), maybe you want to write:



private slots:
QString textEncryp();


Then when the button is clicked, signal clickedTranslate( QString) will be emitted and connect this signal to any slot you want to response;

Palmik
17th January 2009, 10:01
Thank you very much, now I feel, that this is the right way. But still it does not work :/
Dunno why, maybe and hopefully it is just a silly typo.

sifrator.h


#ifndef SIFRATOR_H
#define SIFRATOR_H

#include <QWidget>
#include <QString>

const int PISMO_V = 12;
const int BUTT_H = 25;
const int BUTT_W = 70;
const int TEXT_H = 200;
const int TEXT_W = 550;

QT_BEGIN_NAMESPACE
class QLabel;
class QTextEdit;
class QPushButton;
QT_END_NAMESPACE

class EncrypterBody : public QWidget
{
Q_OBJECT

public:
EncrypterBody(QWidget *parent = 0);

public slots:
void setText(QString string);

signals:
void clickedTranslate(QString string);

private slots:
void openFile();
//
void readFile();
//
void saveFile();
//
void textEncryption();

private:
QTextEdit *text;
//
QLabel *openFileName;
//
QPushButton *buttonTranslate;
};

#endif


sifrator.cpp


#include <iostream>
#include <QtGui>
#include <QLocale>
#include <QFile>
#include <QByteArray>
#include <QChar>

#include "sifrator.h"

using namespace std;

EncrypterBody::EncrypterBody(QWidget *parent)
: QWidget(parent)
{

int LABEL_STYLE = QFrame::Sunken | QFrame::Panel;

// Zadavani klicu
QLineEdit *keyPublic = new QLineEdit();
keyPublic->setMinimumWidth(TEXT_W);
keyPublic->setMaximumWidth(TEXT_W);
keyPublic->setMaxLength(50);
keyPublic->setText(trUtf8("Veřejný klÃ*č"));

// Name Label souboru
openFileName = new QLabel;
openFileName->setFrameStyle(LABEL_STYLE);
openFileName->setText(trUtf8("Cesta k otevřenému souboru"));

// Textarea
text = new QTextEdit();
text->setText(trUtf8("Text"));
text->canPaste();
text->setTabStopWidth(500);
text->setMinimumSize(TEXT_W - BUTT_W - 5, TEXT_H);
text->setMaximumSize(TEXT_W - BUTT_W - 5, TEXT_H);

// Buttónky
buttonTranslate = new QPushButton(trUtf8("Přeložit"));
buttonTranslate->setMinimumSize(BUTT_W, BUTT_H);
buttonTranslate->setMaximumSize(BUTT_W, BUTT_H);
connect(buttonTranslate, SIGNAL(clicked()), this, SLOT(textEncryption()));

QPushButton *buttonSave = new QPushButton(trUtf8("Uložit"));
buttonSave->setMinimumSize(BUTT_W, BUTT_H);
buttonSave->setMaximumSize(BUTT_W, BUTT_H);
connect(buttonSave, SIGNAL(clicked()), this, SLOT(saveFile()));

QPushButton *buttonOpen = new QPushButton(trUtf8("NačÃ*st"));
buttonOpen->setMinimumSize(BUTT_W, BUTT_H);
buttonOpen->setMaximumSize(BUTT_W, BUTT_H);
connect(buttonOpen, SIGNAL(clicked()), this, SLOT(openFile()));

// UspořádánÃ* layoutu
QGridLayout *texts_buttons = new QGridLayout;
texts_buttons->addWidget(openFileName, 0, 0);
texts_buttons->addWidget(text, 1, 0, 4, 1);
texts_buttons->addWidget(buttonTranslate, 1, 1);
texts_buttons->addWidget(buttonSave, 2, 1);
texts_buttons->addWidget(buttonOpen, 3, 1);
texts_buttons->setRowMinimumHeight(4, TEXT_H - (3 * BUTT_H + 8));

QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(keyPublic);
layout->addLayout(texts_buttons);
layout->setSizeConstraint(QLayout::SetFixedSize);
setLayout(layout);

}

////////////
// FUNKCE //
////////////

// Načte jméno souboru do text()u QLabelu
void EncrypterBody::openFile()
{
QFileDialog::Options options;
QString selectedFilter;

QString fileName = QFileDialog::getOpenFileName(this, trUtf8("Vyber textový soubor"), openFileName->text(), trUtf8("Textové soubory (*.txt)"));

if (!fileName.isEmpty())
{
if (fileName != openFileName->text())
{
openFileName->setText(fileName);
}

readFile();
}
}

void EncrypterBody::readFile()
{
text->clear();

QFile file(openFileName->text());
file.open(QIODevice::ReadOnly | QIODevice::Text);

while (!file.atEnd())
{
QString line = QString::fromUtf8(file.readLine());
text->append(line);
}

file.close();
}

void EncrypterBody::saveFile()
{
QString fileName = QFileDialog::getSaveFileName(this, trUtf8("Vyber textový soubor"), openFileName->text(), trUtf8("Textové soubory (*.txt)"));

openFileName->setText(fileName);

QFile file(fileName);
file.open(QIODevice::WriteOnly | QIODevice::Text);

QTextStream out(&file);
out << text->toPlainText();

file.close();
}

//clicked() SIGNAL is connected to this SLOT which is emmiting another SIGNAL
void EncrypterBody::textEncryption()
{
QString textNormal = text->toPlainText();
textNormal = textNormal.simplified();

QString textEncrypted;
QTextStream out(&textEncrypted);

for (int o = 0; o < textNormal.size(); o++)
{
QChar cChar = textNormal.data()[o];
short cNumber = cChar.unicode();

for (int i = 1; i < 3; i++)
{
if (cNumber < pow(10, i))
{
textEncrypted.append('0');
}
}
out << cNumber;
}
emit clickedTranslate(textEncrypted);
}

void EncrypterBody::setText(QString string)
{
text->setText(string);
}


main.cpp


#include <QApplication>

#include "sifrator.h"

int main(int argc, char *argv[])
{
QApplication sifrator(argc, argv);


// Here I created two instances of Encrypter body
EncrypterBody partEncryption;
EncrypterBody partDecryption;

// Here I am trying to achieve this: When I click buttonTranslate in partEncryption part I want change text in text (QTextEdit) in partDecription instance, however this does not seem to work.
QObject::connect(&partEncryption, SIGNAL(clickedTrasnlate(QString)), &partDecryption, SLOT(setText(QString)));


partEncryption.show();
partDecryption.show();

return sifrator.exec();
}

Palmik
17th January 2009, 18:07
When I added CONFIG+=console to *.pro file a then recompiled it and runned the output was:
Object::connect: No such signal EncrypterBody::clickedTrasnlate(QString)

It made me just more confused than I was :P
Edit: I found it.... the problem was of course typo :D I misspelled "clickedTranslate" in main
Now it is working as intended :)

However the application makes 2 windows (2 objects of one class) How should I moddify the layout to make it appear in one window? Can you direct to some documentation connected with this topic?

rexi
17th January 2009, 23:45
However the application makes 2 windows (2 objects of one class) How should I moddify the layout to make it appear in one window? Can you direct to some documentation connected with this topic?

No wonder, you're creating two QWidgets and showing both in your main.cpp. Just create a QDialog or QMainWindow with an appropriate layout, add those widgets to the layout and show the dialog/mainwindow. See Layout Management (http://doc.trolltech.com/4.4/layout.html) for how to work with layouts.