Getting Started on the Commandline/pt: Difference between revisions
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
[toc align_right= | [toc align_right="yes" depth="4"] | ||
= Iniciando o desenvolvimento com Qt = | = Iniciando o desenvolvimento com Qt = | ||
Line 11: | Line 11: | ||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|http://doc.qt.nokia.com/4.7/images/gs1.png]] | p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|http://doc.qt.nokia.com/4.7/images/gs1.png]] | ||
<code> | <code> | ||
#include <QApplication> | |||
#include <QTextEdit> | |||
int main(int argv, char **args) | int main(int argv, char **args) | ||
{ | |||
QApplication app(argv, args); | |||
QTextEdit textEdit; | QTextEdit textEdit; | ||
textEdit.show(); | |||
return app.exec(); | |||
} | |||
</code> | |||
Vamos caminhar pelo código linha por linha. Nas primeiras duas linhas nós incluimos os headers | Vamos caminhar pelo código linha por linha. Nas primeiras duas linhas nós incluimos os headers "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html e "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html, que são as duas classes que usaremos neste exemplo. Todas as classes possuem um aquivo de header com seu nome. | ||
A linha 6 cria um objeto | A linha 6 cria um objeto "QApplication":http://doc.qt.nokia.com/4.7/qapplication.htm. Este objeto gerencia os recursos da aplicação e é necessário para rodar qualquer programa Qt que possua uma interface gráfica. O uso de ''argv'' e ''argc'' também é necessário porque o framework Qt aceita alguns argumentos da linha de comando. | ||
Linha 8 cria um objeto | Linha 8 cria um objeto "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html. Uma caixa de texto é um elemento visual em uma interface gráfica. Em Qt, estes elementos são chamados de ''widgets''. Exemplo de outros widgets são as barras de rolagem (''scroll bars''), ''labels'', e ''radio buttons''. Um ''widget'' também pode ser um recipiente para outros ''widgets''; Uma janela de diálogo, ou a janela principal, por exemplo. | ||
A linha 9 mostra a caixa de texto dentro do seu próprio ''frame''. Como ''widgets'' funcionam também como recipientes, é possível mostar um ''widget'' simples na sua própria janela. ''Widgets'' não são visíveis por padrão, portanto o método | A linha 9 mostra a caixa de texto dentro do seu próprio ''frame''. Como ''widgets'' funcionam também como recipientes, é possível mostar um ''widget'' simples na sua própria janela. ''Widgets'' não são visíveis por padrão, portanto o método "show()":http://doc.trolltech.com/4.7/qwidget.html#show deve ser chamado para fazer o widget visível. | ||
A linha 11 faz com que a QApplication entre em seu ''loop'' de eventos. Quando uma aplicação Qt está rodando, os eventos são gerados e enviados para os widgets da aplicação. Exemplo de eventos são os clicks do mouse e entradas de teclado. Quando você digita algo dentro de uma caixa de texto, esta recebe os eventos de teclado e responde desenhando o texto digitado. | A linha 11 faz com que a QApplication entre em seu ''loop'' de eventos. Quando uma aplicação Qt está rodando, os eventos são gerados e enviados para os widgets da aplicação. Exemplo de eventos são os clicks do mouse e entradas de teclado. Quando você digita algo dentro de uma caixa de texto, esta recebe os eventos de teclado e responde desenhando o texto digitado. | ||
Line 29: | Line 37: | ||
Para rodar a aplicação: Abra um terminal e entre no diretório onde está seu .cpp. Para compilar a aplicação execute os seguintes passos: | Para rodar a aplicação: Abra um terminal e entre no diretório onde está seu .cpp. Para compilar a aplicação execute os seguintes passos: | ||
<code>qmake -project | <code>qmake -project | ||
qmake | |||
make</code> | |||
Isso deverá gerar um executável no diretório '''part1''' (note que no windows você deve usar nmake ao invés de make. O executável também será gerado em *part1*/debug ou *part1*/release). qmake é a ferramenta Qt para construção do ambiente de compilação da sua aplicação, e depende de um arquivo de configuração (.pro) para funcionar. Este arquivo pode ser gerado com o argumento | Isso deverá gerar um executável no diretório '''part1''' (note que no windows você deve usar nmake ao invés de make. O executável também será gerado em *part1*/debug ou *part1*/release). qmake é a ferramenta Qt para construção do ambiente de compilação da sua aplicação, e depende de um arquivo de configuração (.pro) para funcionar. Este arquivo pode ser gerado com o argumento -project. Dado esse arquivo, qmake produz um Makefile que será utilizado para compilar o programa pra você. Futuramente veremos como construir nossos próprios arquivos .pro. | ||
h3. Aprenda mais | |||
|'''Sobre'''|'''Onde'''| | |||
|Widgets e geometria de janelas|"Janelas e Diálogos":http://doc.qt.nokia.com/4.7/application-windows.html| | |||
|Eventos e manipulação de eventos|"O Sistema de eventos":http://doc.qt.nokia.com/4.7/eventsandfilters.html| | |||
h2. Adicionando um botão de saída | |||
Em uma aplicação real você normalmente precisaria de mais de um único widget. Então introduziremos um QPushButton abaixo da caixa de edição de texto. O botão irá fechar o bloco de notas quando pressionado (ex.: quando houver um click com o mouse). | |||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|Editor de texto com botão para fechar]] | |||
Vamos analizar o código linha a linha: | |||
<code>#include <QtGui> | |||
int main(int argv, char **args) | |||
{ | |||
QApplication app(argv, args); | |||
QTextEdit textEdit; | |||
QPushButton quitButton("Sair"); | |||
QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit())); | |||
QVBoxLayout layout; | |||
layout.addWidget(&textEdit); | |||
layout.addWidget(&quitButton); | |||
QWidget window; | |||
window.setLayout(&layout); | |||
window.show(); | |||
return app.exec(); | |||
}</code> | |||
A linha 1 inclui "QtGui":http://doc.qt.nokia.com/4.7/qtgui.html, que contém todas as classes de elementos gráficos Qt. | |||
A Linha 10 usa o mecanismo de sinais e slots (''signals & slots'') para fechar a aplicação quando o botão '''Sair''' for pressionado. Um slot é um método que pode ser invocado em tempo de execução usando seu nome (como uma string literal). Um sinal é uma função que, quando chamada, irá invocar os slots registrados nela ela; Nós chamamos isso de "conectar o slot no sinal e emitir o sinal". | |||
"quit()":http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit é o ''slot'' de QApplication que finaliza a aplicação." clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked é o sinal emitido por "QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html quando este for pressionado. O método estático "QObject::connect() ":http://doc.qt.nokia.com/4.7/qobject.html#connect é responsável por conectar o slot ao sinal. SIGNAL () e SLOT() são duas macros que retornam as assinaturas dos sinais e slots, respectivamente. Nós também precisamos passar os ponteiros para os objetos que devem receber e enviar o sinal. | |||
A linha 12 cria um "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html. Como mencionado, widgets podem conter outros widgets. É possível definir os limites (posição e tamanho) dos widgets filhos diretamente, mas é mais fácil usar um ''layout''. Um layout gerencia os limites dos widgets filhos. "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html, por exemplo, posiciona os filhos verticalmente. | |||
As linhas 13 e 14 adicionam a caixa de texto e o botão ao layout. Na linha 17 definimos o layout em um widget. | |||
h3. Aprenda Mais | |||
|'''Sobre'''|'''Onde'''| | |||
|Sinais e slots|"Slots e Sinais":http://doc.qt.nokia.com/4.7/signalsandslots.html| | |||
|Layouts|"Gerenciamento de Layout":http://doc.qt.nokia.com/4.7/layout.html, "widgets e Layouts":http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "exemplos de layouts":http://doc.qt.nokia.com/4.7/examples-layouts.html| | |||
|Os widgets do Qt|"Galeria de Widgets":http://doc.qt.nokia.com/4.7/gallery.html, "exemplos":http://doc.qt.nokia.com/4.7/examples-widgets.html| | |||
h2. Herdando de QWidget | |||
Quando o usuário desejar sair da aplicação, pode ser necessário mostrar um diálogo perguntando se ele realmente quer sair. Neste exemplo, nós especializamos "QWidget":http://doc.qt.nokia.com/4.7/qwidget.html e adicionamos um slot que foi conectado ao botão '''Sair'''. | |||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs3.png|Herdando de QWidget]] | |||
O código: | |||
<code>class Notepad : public QWidget | |||
{ | |||
Q_OBJECT | |||
public: | |||
Notepad(); | |||
private slots: | |||
void quit(); | |||
private: | |||
QTextEdit *textEdit; | |||
QPushButton *quitButton; | |||
};</code> | |||
A macro Q_OBJECT deve ser colocada no início da definição da classe, e essa ser uma especialização de QObject (QWidget herda de QObject). O QObject adiciona algumas habilidades a uma classe C++ padrão. Notavelmente, o nome da classe e dos slots podem ser requisitados em tempo de execução. Também é possível consultar um tipo de parâmetro do slot e invocá-lo. | |||
A linha 9 declara o slot '''quit()'''. Isso é fácil usando a macro '''slots'''. O slot quit() agora pode ser conectado aos sinais que possuem uma assinatura equivalente (no caso, qualquer sinal que não receba parâmetros) | |||
Ao invés de iniciarmos a interface gráfica e conectarmos o slot dentro da função main(), agora usamos o contrutor do ''Notepad''. | |||
<code>Notepad::Notepad() | |||
{ | |||
textEdit = new QTextEdit; | |||
quitButton = new QPushButton(tr("Quit")); | |||
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit())); | |||
QVBoxLayout *layout = new QVBoxLayout; | |||
layout->addWidget(textEdit); | |||
layout->addWidget(quitButton); | |||
setLayout(layout); | setLayout(layout); | ||
setWindowTitle(tr( | setWindowTitle(tr("Notepad")); | ||
} | |||
</code> | |||
Como podemos ver na definição da classe, usamos ponteiros para os nossos | Como podemos ver na definição da classe, usamos ponteiros para os nossos "QObjects":http://doc.qt.nokia.com/4.7/qobject.html (textEdit e quitButton). Como regra: sempre devemos alocar os "QObjects":http://doc.qt.nokia.com/4.7/qobject.html na ''heap'' e nunca copiá-los. | ||
Usamos a função | Usamos a função "tr()":http://doc.qt.nokia.com/4.7/qobject.html#tr em torno de nossas strings visíveis ao usuário. Esta função é necessária quando queremos distribuir nossa aplicação em mais de um idioma (por exemplo: inglês e alemão). Não vamos entrar em detalhes aqui, mas você pode seguir o link Qt Linguist na tabela '''Aprenda Mais'''. | ||
=== Aprenda Mais === | === Aprenda Mais === | ||
Line 82: | Line 153: | ||
|- | |- | ||
|tr() e i18n | |tr() e i18n | ||
| | |"Manual do Qt Linguist":http://doc.qt.nokia.com/4.7/linguist-manual.html, "Escrevendo código fonte para tradução":http://doc.qt.nokia.com/4.7/i18n-source-translation.html, "Example Olá tr()":http://doc.qt.nokia.com/4.7/linguist-hellotr.html, "Internationalização com Qt":http://doc.qt.nokia.com/4.7/internationalization.html | ||
|- | |- | ||
| | |"QObjects":http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects e o modelo do Qt Object (Isto é essencial para entender Qt) | ||
| | |"Modelo de Objeto":http://doc.qt.nokia.com/4.7/object.html | ||
|- | |- | ||
|qmake e o systema de construção do Qt | |qmake e o systema de construção do Qt | ||
| | |"Manual qmake":http://doc.qt.nokia.com/4.7/qmake-manual.html | ||
|} | |} | ||
== Criando um arquivo .pro == | == Criando um arquivo .pro == | ||
Para este exemplo escreveremos nosso próprio arquivo .pro ao invés de usarmos a opção | Para este exemplo escreveremos nosso próprio arquivo .pro ao invés de usarmos a opção -project do qmake. | ||
<code>HEADERS = notepad.h | |||
SOURCES = notepad.cpp main.cpp | |||
</code> | |||
Para compilar o programa siga os seguintes passos: | |||
<code>qmake | |||
make</code> | |||
h2. Usando o QMainWindow | |||
Várias aplicações serão beneficiadas ao usar a "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, que possui seu próprio layout no qual pode-se adicionar uma barra de menu, ''dock widgets'', barra de ferramentas e barra de status. "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html possui também uma área central que pode ser ocupada por qualquer tipo de widget. No nosso caso, colocaremos lá nossa caixa de edição de texto. | |||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|Usando QMainWindow]] | |||
Vamos à nova definição da classe Notepad. | |||
<code>#include <QtGui> | |||
class Notepad : public QMainWindow | |||
{ | |||
Q_OBJECT | |||
public: | |||
Notepad(); | |||
private slots: | |||
void open(); | |||
void save(); | |||
void quit(); | |||
private: | |||
QTextEdit *textEdit; | |||
QAction *openAction; | |||
QAction *saveAction; | |||
QAction *exitAction; | |||
QMenu *fileMenu; | |||
}; | |||
</code> | |||
Incluímos mais dois slots que podem salvar e abrir um documento. Iremos implementá-los na próxima sessão. | |||
Em uma janela principal (''main window'') o mesmo slot costuma ser invocado por vários widgets. Exemplos disso são os ítens de menu e os botões em uma barra de ferramentas. Para facilitar, Qt provê o QAction, que pode ser passado para vários widgets e ser conectado aos slots. Por exemplo, QMenu e QToolBar podem criar ítens de menu através dos mesmos QActions. Iremos ver como isso funciona mais a frente. | |||
Como antes, usamos o costrutor do Notepad para iniciar a interface gráfica. | |||
<code>Notepad::Notepad() | |||
{ | |||
saveAction = new QAction(tr("&Open"), this); | |||
saveAction = new QAction(tr("&Save"), this); | |||
exitAction = new QAction(tr("E&amp;xit"), this); | |||
connect(openAction, SIGNAL (triggered()), this, SLOT (open())); | |||
connect(saveAction, SIGNAL (triggered()), this, SLOT (save())); | |||
connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit())); | |||
fileMenu = menuBar()->addMenu(tr("&File")); | |||
fileMenu->addAction(openAction); | |||
fileMenu->addAction(saveAction); | |||
fileMenu->addSeparator(); | |||
fileMenu->addAction(exitAction); | |||
textEdit = new QTextEdit; | |||
setCentralWidget(textEdit); | |||
setWindowTitle(tr("Notepad")); | |||
}</code> | |||
"QActions":http://doc.qt.nokia.com/4.7/qaction.html são criadas com o texto que deve aparecer nos widgets em que forem adicionadas (no nosso caso, o menu). Se nós também quisermos adicioná-los à barra de ferramentas poderemos utilizar "ícones":http://doc.qt.nokia.com/4.7/qicon.html nos QActions. | |||
Quando um ítem do menu for pressionado, o ítem irá ativar a ação e o respectivo slot será invocado. | Quando um ítem do menu for pressionado, o ítem irá ativar a ação e o respectivo slot será invocado. | ||
Line 130: | Line 247: | ||
|- | |- | ||
|Main windows e suas classes | |Main windows e suas classes | ||
| | |"Aplicação comMain Window":http://doc.qt.nokia.com/4.7/mainwindow.html, "Exemplos da Main Window":http://doc.qt.nokia.com/4.7/examples-mainwindow.html | ||
|- | |- | ||
|Aplicações MDI | |Aplicações MDI | ||
| | |"QMdiArea":http://doc.qt.nokia.com/4.7/qmdiarea.html, "Exemplo MDI":http://doc.qt.nokia.com/4.7/mainwindows-mdi.html | ||
|} | |} | ||
Line 144: | Line 261: | ||
Vamos começar com o slot open(): | Vamos começar com o slot open(): | ||
<code>QString fileName = QFileDialog::getOpenFileName(this, tr( | <code>QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", | ||
tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)")); | |||
if (fileName != "") { | |||
QFile file(fileName); | |||
if (!file.open(QIODevice::ReadOnly)) { | |||
QMessageBox::critical(this, tr("Error"), | |||
tr("Could not open file")); | |||
return; | |||
} | |||
QString contents = file.readAll().constData(); | |||
textEdit->setPlainText(contents); | |||
file.close(); | |||
}</code> | |||
O primeiro passo é perguntar ao usuário pelo nome do arquivo que deseja abrir. Qt vem com o "QFileDialog":http://doc.qt.nokia.com/4.7/qfiledialog.html, que é um diálogo onde o usuário pode selecionar um arquivo. A imagem acima mostra o diálogo no Kubuntu. O método estático "getOpenFileName()":http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName mostra um diálogo de arquivo modal, e não retorna até que o usuário seleciona um arquivo. Ele retorna o caminho para o arquivo selecionado, ou uma string vazia caso o usuário cancele o diálogo. | |||
Se nós tivermos um nome de arquivo então tentaremos abrí-lo uando o método "open()":http://doc.qt.nokia.com/4.7/qiodevice.html#open, que retorna True se o arquivo pode ser aberto. Não iremos tratar gerenciamento de erro neste artigo, para isso você pode seguir os links da seção Aprenda Mais. Se o arquivo não pode ser aberto, usaremos uma "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html para mostar um diálogo com uma mensagem de erro (veja a descrição da classe "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html para maiores detalhes). | |||
Ler os dados do arquivo é trivial usando o método "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll que retorna todos os dados do arquivo em um "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html. "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData retorna todos os dados em um array como um const char''', que pode ser usado para gerar uma "QString":http://doc.qt.nokia.com/4.7/qstring.html. O conteúdo pode ser mostrado na caixa de edição de texto. Então o método "close() ":http://doc.qt.nokia.com/4.7/qiodevice.html#closeé invocado para retornar o descritor de arquivo para o sistema operacional. | |||
Agora, vejamos o método save(): | Agora, vejamos o método save(): | ||
<code>QString fileName = QFileDialog::getSaveFileName(this, tr( | <code>QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", | ||
tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)")); | |||
if (fileName != "") { | |||
QFile file(fileName); | |||
if (!file.open(QIODevice::WriteOnly)) { | |||
// error message | |||
} else { | |||
QTextStream stream(&file); | |||
stream << textEdit->toPlainText(); | |||
stream.flush(); | |||
file.close(); | |||
} | |||
}</code> | |||
Quando escrevemos o conteúdo da caixa de edição de texto no arquivo usamos a classe "QTextStream":http://doc.qt.nokia.com/4.7/qtextstream.html que recebe um objeto tipo QFile. O stream de text pode escrever QStrings diretamente no arquivo enquanto "QFile":http://doc.qt.nokia.com/4.7/qfile.html somente aceita dado puro (char''') com o método "write()":http://doc.qt.nokia.com/4.7/qiodevice.html#write do "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html. | |||
=== Aprenda Mais === | === Aprenda Mais === | ||
Line 163: | Line 308: | ||
|- | |- | ||
|Arquivos e dispositivos de entrada e saída | |Arquivos e dispositivos de entrada e saída | ||
| | |"QFile":http://doc.qt.nokia.com/4.7/qfile.html, "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html | ||
|} | |} |
Revision as of 10:27, 25 February 2015
[toc align_right="yes" depth="4"]
Iniciando o desenvolvimento com Qt
Bem vindo ao mundo Qt — o framework multiplataforma. Neste guia introdutório você irá aprender o básico de Qt implementado um bloco de notas simples. Após a leitura deste guia você deverá estar preparado para aprofundar-se no ambiente e na documentação da API, além de saber localizar toda a documentação que você precisa para as aplicações que estiver desenvolvendo.
Olá Notepad
Neste primeiro exemplo criaremos e mostraremos simplesmente uma caixa de texto em uma janela do desktop. É a aplicação gráfica mais simples possível.
p=. http://doc.qt.nokia.com/4.7/images/gs1.png
#include <QApplication>
#include <QTextEdit>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
textEdit.show();
return app.exec();
}
Vamos caminhar pelo código linha por linha. Nas primeiras duas linhas nós incluimos os headers "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html e "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html, que são as duas classes que usaremos neste exemplo. Todas as classes possuem um aquivo de header com seu nome.
A linha 6 cria um objeto "QApplication":http://doc.qt.nokia.com/4.7/qapplication.htm. Este objeto gerencia os recursos da aplicação e é necessário para rodar qualquer programa Qt que possua uma interface gráfica. O uso de argv e argc também é necessário porque o framework Qt aceita alguns argumentos da linha de comando.
Linha 8 cria um objeto "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html. Uma caixa de texto é um elemento visual em uma interface gráfica. Em Qt, estes elementos são chamados de widgets. Exemplo de outros widgets são as barras de rolagem (scroll bars), labels, e radio buttons. Um widget também pode ser um recipiente para outros widgets; Uma janela de diálogo, ou a janela principal, por exemplo.
A linha 9 mostra a caixa de texto dentro do seu próprio frame. Como widgets funcionam também como recipientes, é possível mostar um widget simples na sua própria janela. Widgets não são visíveis por padrão, portanto o método "show()":http://doc.trolltech.com/4.7/qwidget.html#show deve ser chamado para fazer o widget visível.
A linha 11 faz com que a QApplication entre em seu loop de eventos. Quando uma aplicação Qt está rodando, os eventos são gerados e enviados para os widgets da aplicação. Exemplo de eventos são os clicks do mouse e entradas de teclado. Quando você digita algo dentro de uma caixa de texto, esta recebe os eventos de teclado e responde desenhando o texto digitado.
Para rodar a aplicação: Abra um terminal e entre no diretório onde está seu .cpp. Para compilar a aplicação execute os seguintes passos:
qmake -project
qmake
make
Isso deverá gerar um executável no diretório part1 (note que no windows você deve usar nmake ao invés de make. O executável também será gerado em *part1*/debug ou *part1*/release). qmake é a ferramenta Qt para construção do ambiente de compilação da sua aplicação, e depende de um arquivo de configuração (.pro) para funcionar. Este arquivo pode ser gerado com o argumento -project. Dado esse arquivo, qmake produz um Makefile que será utilizado para compilar o programa pra você. Futuramente veremos como construir nossos próprios arquivos .pro.
h3. Aprenda mais
|Sobre|Onde| |Widgets e geometria de janelas|"Janelas e Diálogos":http://doc.qt.nokia.com/4.7/application-windows.html%7C |Eventos e manipulação de eventos|"O Sistema de eventos":http://doc.qt.nokia.com/4.7/eventsandfilters.html%7C
h2. Adicionando um botão de saída
Em uma aplicação real você normalmente precisaria de mais de um único widget. Então introduziremos um QPushButton abaixo da caixa de edição de texto. O botão irá fechar o bloco de notas quando pressionado (ex.: quando houver um click com o mouse).
p=. Editor de texto com botão para fechar
Vamos analizar o código linha a linha:
#include <QtGui>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
QPushButton quitButton("Sair");
QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
QVBoxLayout layout;
layout.addWidget(&textEdit);
layout.addWidget(&quitButton);
QWidget window;
window.setLayout(&layout);
window.show();
return app.exec();
}
A linha 1 inclui "QtGui":http://doc.qt.nokia.com/4.7/qtgui.html, que contém todas as classes de elementos gráficos Qt.
A Linha 10 usa o mecanismo de sinais e slots (signals & slots) para fechar a aplicação quando o botão Sair for pressionado. Um slot é um método que pode ser invocado em tempo de execução usando seu nome (como uma string literal). Um sinal é uma função que, quando chamada, irá invocar os slots registrados nela ela; Nós chamamos isso de "conectar o slot no sinal e emitir o sinal".
"quit()":http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit é o slot de QApplication que finaliza a aplicação." clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked é o sinal emitido por "QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html quando este for pressionado. O método estático "QObject::connect() ":http://doc.qt.nokia.com/4.7/qobject.html#connect é responsável por conectar o slot ao sinal. SIGNAL () e SLOT() são duas macros que retornam as assinaturas dos sinais e slots, respectivamente. Nós também precisamos passar os ponteiros para os objetos que devem receber e enviar o sinal.
A linha 12 cria um "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html. Como mencionado, widgets podem conter outros widgets. É possível definir os limites (posição e tamanho) dos widgets filhos diretamente, mas é mais fácil usar um layout. Um layout gerencia os limites dos widgets filhos. "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html, por exemplo, posiciona os filhos verticalmente.
As linhas 13 e 14 adicionam a caixa de texto e o botão ao layout. Na linha 17 definimos o layout em um widget.
h3. Aprenda Mais
|Sobre|Onde| |Sinais e slots|"Slots e Sinais":http://doc.qt.nokia.com/4.7/signalsandslots.html%7C |Layouts|"Gerenciamento de Layout":http://doc.qt.nokia.com/4.7/layout.html, "widgets e Layouts":http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "exemplos de layouts":http://doc.qt.nokia.com/4.7/examples-layouts.html%7C |Os widgets do Qt|"Galeria de Widgets":http://doc.qt.nokia.com/4.7/gallery.html, "exemplos":http://doc.qt.nokia.com/4.7/examples-widgets.html%7C
h2. Herdando de QWidget
Quando o usuário desejar sair da aplicação, pode ser necessário mostrar um diálogo perguntando se ele realmente quer sair. Neste exemplo, nós especializamos "QWidget":http://doc.qt.nokia.com/4.7/qwidget.html e adicionamos um slot que foi conectado ao botão Sair.
O código:
class Notepad : public QWidget
{
Q_OBJECT
public:
Notepad();
private slots:
void quit();
private:
QTextEdit *textEdit;
QPushButton *quitButton;
};
A macro Q_OBJECT deve ser colocada no início da definição da classe, e essa ser uma especialização de QObject (QWidget herda de QObject). O QObject adiciona algumas habilidades a uma classe C++ padrão. Notavelmente, o nome da classe e dos slots podem ser requisitados em tempo de execução. Também é possível consultar um tipo de parâmetro do slot e invocá-lo.
A linha 9 declara o slot quit(). Isso é fácil usando a macro slots. O slot quit() agora pode ser conectado aos sinais que possuem uma assinatura equivalente (no caso, qualquer sinal que não receba parâmetros)
Ao invés de iniciarmos a interface gráfica e conectarmos o slot dentro da função main(), agora usamos o contrutor do Notepad.
Notepad::Notepad()
{
textEdit = new QTextEdit;
quitButton = new QPushButton(tr("Quit"));
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(textEdit);
layout->addWidget(quitButton);
setLayout(layout);
setWindowTitle(tr("Notepad"));
}
Como podemos ver na definição da classe, usamos ponteiros para os nossos "QObjects":http://doc.qt.nokia.com/4.7/qobject.html (textEdit e quitButton). Como regra: sempre devemos alocar os "QObjects":http://doc.qt.nokia.com/4.7/qobject.html na heap e nunca copiá-los.
Usamos a função "tr()":http://doc.qt.nokia.com/4.7/qobject.html#tr em torno de nossas strings visíveis ao usuário. Esta função é necessária quando queremos distribuir nossa aplicação em mais de um idioma (por exemplo: inglês e alemão). Não vamos entrar em detalhes aqui, mas você pode seguir o link Qt Linguist na tabela Aprenda Mais.
Aprenda Mais
Sobre | Onde |
tr() e i18n | "Manual do Qt Linguist":http://doc.qt.nokia.com/4.7/linguist-manual.html, "Escrevendo código fonte para tradução":http://doc.qt.nokia.com/4.7/i18n-source-translation.html, "Example Olá tr()":http://doc.qt.nokia.com/4.7/linguist-hellotr.html, "Internationalização com Qt":http://doc.qt.nokia.com/4.7/internationalization.html |
"QObjects":http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects e o modelo do Qt Object (Isto é essencial para entender Qt) | "Modelo de Objeto":http://doc.qt.nokia.com/4.7/object.html |
qmake e o systema de construção do Qt | "Manual qmake":http://doc.qt.nokia.com/4.7/qmake-manual.html |
Criando um arquivo .pro
Para este exemplo escreveremos nosso próprio arquivo .pro ao invés de usarmos a opção -project do qmake.
HEADERS = notepad.h
SOURCES = notepad.cpp main.cpp
Para compilar o programa siga os seguintes passos:
qmake
make
h2. Usando o QMainWindow
Várias aplicações serão beneficiadas ao usar a "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, que possui seu próprio layout no qual pode-se adicionar uma barra de menu, dock widgets, barra de ferramentas e barra de status. "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html possui também uma área central que pode ser ocupada por qualquer tipo de widget. No nosso caso, colocaremos lá nossa caixa de edição de texto.
Vamos à nova definição da classe Notepad.
#include <QtGui>
class Notepad : public QMainWindow
{
Q_OBJECT
public:
Notepad();
private slots:
void open();
void save();
void quit();
private:
QTextEdit *textEdit;
QAction *openAction;
QAction *saveAction;
QAction *exitAction;
QMenu *fileMenu;
};
Incluímos mais dois slots que podem salvar e abrir um documento. Iremos implementá-los na próxima sessão.
Em uma janela principal (main window) o mesmo slot costuma ser invocado por vários widgets. Exemplos disso são os ítens de menu e os botões em uma barra de ferramentas. Para facilitar, Qt provê o QAction, que pode ser passado para vários widgets e ser conectado aos slots. Por exemplo, QMenu e QToolBar podem criar ítens de menu através dos mesmos QActions. Iremos ver como isso funciona mais a frente.
Como antes, usamos o costrutor do Notepad para iniciar a interface gráfica.
Notepad::Notepad()
{
saveAction = new QAction(tr("&Open"), this);
saveAction = new QAction(tr("&Save"), this);
exitAction = new QAction(tr("E&amp;xit"), this);
connect(openAction, SIGNAL (triggered()), this, SLOT (open()));
connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));
connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);
textEdit = new QTextEdit;
setCentralWidget(textEdit);
setWindowTitle(tr("Notepad"));
}
"QActions":http://doc.qt.nokia.com/4.7/qaction.html são criadas com o texto que deve aparecer nos widgets em que forem adicionadas (no nosso caso, o menu). Se nós também quisermos adicioná-los à barra de ferramentas poderemos utilizar "ícones":http://doc.qt.nokia.com/4.7/qicon.html nos QActions.
Quando um ítem do menu for pressionado, o ítem irá ativar a ação e o respectivo slot será invocado.
Aprenda Mais
Sobre | Onde |
Main windows e suas classes | "Aplicação comMain Window":http://doc.qt.nokia.com/4.7/mainwindow.html, "Exemplos da Main Window":http://doc.qt.nokia.com/4.7/examples-mainwindow.html |
Aplicações MDI | "QMdiArea":http://doc.qt.nokia.com/4.7/qmdiarea.html, "Exemplo MDI":http://doc.qt.nokia.com/4.7/mainwindows-mdi.html |
Salvando e Abrindo
Neste exemplo iremos implementar a funcionalidade de abrir e salvar, implementando os slots open() e save() que foram adicionados no exemplo anterior.
p=. Abrir e salvar
Vamos começar com o slot open():
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(this, tr("Error"),
tr("Could not open file"));
return;
}
QString contents = file.readAll().constData();
textEdit->setPlainText(contents);
file.close();
}
O primeiro passo é perguntar ao usuário pelo nome do arquivo que deseja abrir. Qt vem com o "QFileDialog":http://doc.qt.nokia.com/4.7/qfiledialog.html, que é um diálogo onde o usuário pode selecionar um arquivo. A imagem acima mostra o diálogo no Kubuntu. O método estático "getOpenFileName()":http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName mostra um diálogo de arquivo modal, e não retorna até que o usuário seleciona um arquivo. Ele retorna o caminho para o arquivo selecionado, ou uma string vazia caso o usuário cancele o diálogo.
Se nós tivermos um nome de arquivo então tentaremos abrí-lo uando o método "open()":http://doc.qt.nokia.com/4.7/qiodevice.html#open, que retorna True se o arquivo pode ser aberto. Não iremos tratar gerenciamento de erro neste artigo, para isso você pode seguir os links da seção Aprenda Mais. Se o arquivo não pode ser aberto, usaremos uma "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html para mostar um diálogo com uma mensagem de erro (veja a descrição da classe "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html para maiores detalhes).
Ler os dados do arquivo é trivial usando o método "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll que retorna todos os dados do arquivo em um "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html. "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData retorna todos os dados em um array como um const char, que pode ser usado para gerar uma "QString":http://doc.qt.nokia.com/4.7/qstring.html. O conteúdo pode ser mostrado na caixa de edição de texto. Então o método "close() ":http://doc.qt.nokia.com/4.7/qiodevice.html#closeé invocado para retornar o descritor de arquivo para o sistema operacional.
Agora, vejamos o método save():
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "",
tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
// error message
} else {
QTextStream stream(&file);
stream << textEdit->toPlainText();
stream.flush();
file.close();
}
}
Quando escrevemos o conteúdo da caixa de edição de texto no arquivo usamos a classe "QTextStream":http://doc.qt.nokia.com/4.7/qtextstream.html que recebe um objeto tipo QFile. O stream de text pode escrever QStrings diretamente no arquivo enquanto "QFile":http://doc.qt.nokia.com/4.7/qfile.html somente aceita dado puro (char) com o método "write()":http://doc.qt.nokia.com/4.7/qiodevice.html#write do "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html.
Aprenda Mais
Sobre | Onde |
Arquivos e dispositivos de entrada e saída | "QFile":http://doc.qt.nokia.com/4.7/qfile.html, "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html |