No fim do módulo 10 e agora no começo deste módulo começamos a programar outra vez em QT;
Para isso duas novas ferramentas foram-nos apresentadas:
o QT Creator e o QT Designer (QT Creator Review)
Com este programa foi muito mais facil programar nesta plataforma... mas agora ao que interessa.
Fizemos vários tipos de programas como Dialogs:
Um “dialog” é construído utilizando um conjunto de widgets onde estabelecemos ligações (SIGNALS/SLOTS) entre eles. Para criar estes Dialogs precisamos de saber o básico de Herança (Explicado no post anterior) e de classes. Depois desta introduçao vamos começar o programa. O que eu fiz foi um widget que nos mostra as matrículas portuguesas:
O resultado final será este:

Agora o programa:
IdAutomovelDialog.cpp
#include <QtGui>
#include "IdDoAutomovelDialog.h"
IdDoAutomovelDialog::IdDoAutomovelDialog(QWidget *parent):QDialog(parent){
//Label
label = new QLabel("&Matrícula:");
//Line Edit
lineEdit = new QLineEdit;
//Buddyes
label->setBuddy(lineEdit);
//Spacer
horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
//OK Button
okButton = new QPushButton("Ok");
okButton->setEnabled(false);
//CANCEL Button
cancelButton = new QPushButton("Cancel");
cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
//Validar a matrícula introduzida ( http://pt.wikipedia.org/wiki/Matr%C3%ADculas_autom%C3%B3veis_em_Portugal )
listaMatriculasValidas = new QStringList;
listaMatriculasValidas->append("[A-Za-z]{2,2}[-][0-9]{2,2}[-][0-9]{2,2}");
listaMatriculasValidas->append("[0-9]{2,2}[-][0-9]{2,2}[-][A-Za-z]{2,2}"); //or
listaMatriculasValidas->operator <<("[0-9]{2,2}[-][A-Za-z]{2,2}[-][0-9]{2,2}");
QRegExp regExp(listaMatriculasValidas->join("|"));
lineEdit->setValidator(new QRegExpValidator(regExp, this));
//Definir acções
connect(lineEdit, SIGNAL(textChanged(const QString &)),
this, SLOT(on_lineEdit_textChanged()));
connect(okButton, SIGNAL(clicked()),
this, SLOT(accept()));
connect(cancelButton, SIGNAL(clicked()),
this, SLOT(close()));
//layout Dialog
horizontalLayout = new QHBoxLayout;
horizontalLayout_2 = new QHBoxLayout;
verticalLayout = new QVBoxLayout;
horizontalLayout->addWidget(label);
horizontalLayout->addWidget(lineEdit);
horizontalLayout_2->addItem(horizontalSpacer);
horizontalLayout_2->addWidget(okButton);
horizontalLayout_2->addWidget(cancelButton);
verticalLayout->addLayout(horizontalLayout);
verticalLayout->addLayout(horizontalLayout_2);
setWindowTitle("Matrícula");
setLayout(verticalLayout);
//Tab order
QWidget::setTabOrder(lineEdit, okButton);
QWidget::setTabOrder(okButton, cancelButton);
}
void IdDoAutomovelDialog::on_lineEdit_textChanged(){
okButton->setEnabled(lineEdit->hasAcceptableInput());
}
IdAutomovelDialog.h
#ifndef IDDOAUTOMOVELDIALOG_H
#define IDDOAUTOMOVELDIALOG_H
#include <QDialog>
class QLabel;
class QLineEdit;
class QSpacerItem;
class QPushButton;
class QHBoxLayout;
class QVBoxLayout;
class QString;
class QRegExp;
class IdDoAutomovelDialog : public QDialog
{
Q_OBJECT
public:
IdDoAutomovelDialog(QWidget *parent = 0);
private slots:
void on_lineEdit_textChanged();
private:
QLabel *label;
QLineEdit *lineEdit;
QSpacerItem *horizontalSpacer;
QPushButton *okButton;
QPushButton *cancelButton;
QStringList *listaMatriculasValidas;
QVBoxLayout *verticalLayout;
QHBoxLayout *horizontalLayout;
QHBoxLayout *horizontalLayout_2;
};
#endif // IDDOAUTOMOVELDIALOG_H
main.cpp
#include <QApplication>
#include "IdDoAutomovelDialog.h"
int main(int argc, char *argv[]){
QApplication app(argc, argv);
IdDoAutomovelDialog *dialog = new IdDoAutomovelDialog;
dialog->show();
return app.exec();
}
Isto feito neste programa foi mesmo o mais facil; O mais dificil vem a seguir; Inda em QT mas agora falando de streaming;
Streaming é basicamente troca de dados através de 2 novas funçoes de QT:
-QTextStream: para manipular dados no formato de texto.
-QDataStream: Para manipular dados no formato binário.
O primeiro a ser falado foi o QTextStream talvez por ser o mais facil; Isto permite trocar dados em apenas formato de texto.
Aqui um pequeno programa de exemplo:
dialog.h
#define DIALOG_H
#include <QtGui/QDialog>
#include <QMessageBox>
#include <QTextStream>
#include <QFile>
namespace Ui
{
class DialogClass;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void processar();
private:
Ui::DialogClass *ui;
QFile original;
QFile copia;
QString line, new_line;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent), ui(new Ui::DialogClass)
{
ui->setupUi(this);
connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
connect(ui->okButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(ui->goButton, SIGNAL(clicked()), this, SLOT(processar()));
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::processar(){
QMessageBox msgBox;
msgBox.setModal(true);
if(ui->original->text().isEmpty() || ui->copia->text().isEmpty() ||
ui->palavra->text().isEmpty() || ui->novapalavra->text().isEmpty()){
msgBox.setText("É obrigatório o preenchimento de todos os campos!");
msgBox.exec();
}else{
original.setFileName(ui->original->text());
copia.setFileName(ui->copia->text());
if (original.open(QFile::ReadOnly)) {
copia.open(QFile::WriteOnly);
QTextStream in(&original);
QTextStream out(&copia);
out.setCodec("UTF-8");
in.setCodec("UTF-8");
do {
line = in.readLine();
new_line = line;
new_line.replace(ui->palavra->text(), ui->novapalavra->text());
out << new_line << endl;
} while (!line.isNull());
original.close();
copia.close();
msgBox.setText("Sucesso!");
msgBox.exec();;
}else{
msgBox.setText("Erro ao abrir o ficheiro: " + ui->original->text());
msgBox.exec();;
}
}
}
Como o modo grafico deste programa é gerado pelo QTDesigner eu ponho aqui um link para download do projecto completo que contém além disto um .ui e um main.cpp.
Link para Download
Agora ainda mais difícil começamos a falar do QDataStream:
QDataStream permite a troca de datagramas como neste programa:

Este programa contém dois ficheiros um que recebe e um que envia dados no caso um receiver e um sender;
Agora o código; Como no exemplo anterior este código também é gerado pelo QTDesigner e Contém ainda um resource file com imagens do programa;
Deixo o link com o programa completo cujo download pode ser feito clicando aqui
RECEIVER
receiver.cpp
#include "receiver.h"
#include "ui_receiver.h"
receiver::receiver(QWidget *parent)
: QWidget(parent), ui(new Ui::receiverClass)
{
ui->setupUi(this);
udpSocket = new QUdpSocket(this);
udpSocket->bind(45454);
connect(udpSocket, SIGNAL(readyRead()),
this, SLOT(datagramreceiver()));
}
receiver::~receiver()
{
delete ui;
}
void receiver::datagramreceiver(){
QByteArray datagram;
do {
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
} while (udpSocket->hasPendingDatagrams());
int m;
bool n;
QDataStream in(&datagram, QIODevice::ReadOnly);
in.setVersion(QDataStream::Qt_4_1);
in >> m >> n; //for more data in >> m >> n >> o >> p >> ...;
if(m == ui->lineEdit->text().toInt()){
if(n)
ui->pushButton->setIcon(QIcon(":/imagens/open"));
else
ui->pushButton->setIcon(QIcon(":/imagens/close"));
}
}
receiver.h
#ifndef RECEIVER_H
#define RECEIVER_H
#include <QtGui/QWidget>
#include <QUdpSocket>
#include <QDataStream>
#include <QRegExp>
namespace Ui
{
class receiverClass;
}
class receiver : public QWidget
{
Q_OBJECT
public:
receiver(QWidget *parent = 0);
~receiver();
private slots:
void datagramreceiver();
private:
Ui::receiverClass *ui;
QUdpSocket *udpSocket;
};
#endif // RECEIVER_H
SENDER
sender.cpp
#include "sender.h"
#include "ui_sender.h"
sender::sender(QWidget *parent)
: QWidget(parent), ui(new Ui::senderClass)
{
ui->setupUi(this);
cancela[0] = ui->push1;
cancela[1] = ui->push2;
cancela[2] = ui->push3;
cancela[3] = ui->push4;
cancela[4] = ui->push5;
cancela[5] = ui->push6;
cancela[6] = ui->push7;
cancela[7] = ui->push8;
cancela[8] = ui->push9;
cancela[9] = ui->push10;
QSignalMapper *signalMapper = new QSignalMapper(this);
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(mudacancela(int)));
for(int i = 0; i < 10; i++){
signalMapper->setMapping(cancela[i], i);
connect(cancela[i], SIGNAL(clicked()), signalMapper, SLOT(map()));
estado[i]=true;
}
udpSocket = new QUdpSocket(this);
}
sender::~sender()
{
delete ui;
}
void sender::mudacancela(int m){
//bool n=false;
estado[m] = !estado[m];
if(estado[m])
cancela[m]->setIcon(QIcon(":/imagens/open"));
else
cancela[m]->setIcon(QIcon(":/imagens/close"));
QByteArray datagram;
QDataStream out(&datagram, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_1);
out << m << estado[m]; //for more data out << m << n << o << p << ...;
udpSocket->writeDatagram(datagram, QHostAddress::LocalHost, 45454);
}
sender.h
#ifndef SENDER_H
#define SENDER_H
#include <QtGui/QWidget>
#include <QSignalMapper>
#include <QUdpSocket>
#include <QPushButton>
namespace Ui
{
class senderClass;
}
class sender : public QWidget
{
Q_OBJECT
public:
sender(QWidget *parent = 0);
~sender();
private slots:
void mudacancela(int m);
private:
Ui::senderClass *ui;
QPushButton *cancela[10];
QUdpSocket *udpSocket;
bool estado[10];
};
#endif // SENDER_H
Para vermos isto a funcionar é só abrir os dois programas e trabalhar no sender; Ao carregar numa cancela para abri-la por exemplo no receiver a cancela abre também.
0 comentários:
Enviar um comentário