Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.
Getting Started on the Commandline/pt: Difference between revisions
No edit summary |
m (Wieland moved page GettingStartedPortuguese to Getting Started on the Commandline/pt: Portuguese) |
||
(6 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{Cleanup | reason=Auto-imported from ExpressionEngine.}} | |||
= Iniciando o desenvolvimento com Qt = | = Iniciando o desenvolvimento com Qt = | ||
Line 11: | Line 12: | ||
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 [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] e [http://doc.qt.nokia.com/4.7/qtextedit.html QTextEdit], 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 [http://doc.qt.nokia.com/4.7/qapplication.htm QApplication]. 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 [http://doc.qt.nokia.com/4.7/qtextedit.html QTextEdit]. 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 [http://doc.trolltech.com/4.7/qwidget.html#show 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 38: | ||
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 -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. | |||
=== Aprenda mais === | |||
|'''Sobre'''|'''Onde'''| | |||
|Widgets e geometria de janelas|[http://doc.qt.nokia.com/4.7/application-windows.html| Janelas e Diálogos] | |||
|Eventos e manipulação de eventos|[http://doc.qt.nokia.com/4.7/eventsandfilters.html| O Sistema de eventos] | |||
== 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 [http://doc.qt.nokia.com/4.7/qtgui.html QtGui], 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". | |||
[http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit quit()] é o ''slot'' de QApplication que finaliza a aplicação.[http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked clicked()] é o sinal emitido por [http://doc.qt.nokia.com/4.7/qpushbutton.html QPushButton] quando este for pressionado. O método estático [http://doc.qt.nokia.com/4.7/qobject.html#connect QObject::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 [http://doc.qt.nokia.com/4.7/qvboxlayout.html QVBoxLayout]. 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. [http://doc.qt.nokia.com/4.7/qvboxlayout.html QVBoxLayout], 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. | |||
=== Aprenda Mais === | |||
|'''Sobre'''|'''Onde'''| | |||
|Sinais e slots|[http://doc.qt.nokia.com/4.7/signalsandslots.html| Slots e Sinais] | |||
|Layouts|[http://doc.qt.nokia.com/4.7/layout.html Gerenciamento de Layout], [http://doc.qt.nokia.com/4.7/widgets-and-layouts.html widgets e Layouts], [http://doc.qt.nokia.com/4.7/examples-layouts.html| exemplos de layouts] | |||
|Os widgets do Qt|[http://doc.qt.nokia.com/4.7/gallery.html Galeria de Widgets], [http://doc.qt.nokia.com/4.7/examples-widgets.html| exemplos] | |||
== 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 [http://doc.qt.nokia.com/4.7/qwidget.html QWidget] 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 [http://doc.qt.nokia.com/4.7/qobject.html QObjects] (textEdit e quitButton). Como regra: sempre devemos alocar os [http://doc.qt.nokia.com/4.7/qobject.html QObjects] na ''heap'' e nunca copiá-los. | ||
Usamos a função | Usamos a função [http://doc.qt.nokia.com/4.7/qobject.html#tr 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 150: | ||
|- | |- | ||
|tr() e i18n | |tr() e i18n | ||
| | |[http://doc.qt.nokia.com/4.7/linguist-manual.html Manual do Qt Linguist], [http://doc.qt.nokia.com/4.7/i18n-source-translation.html Escrevendo código fonte para tradução], [http://doc.qt.nokia.com/4.7/linguist-hellotr.html Example Olá tr()], [http://doc.qt.nokia.com/4.7/internationalization.html Internationalização com Qt] | ||
|- | |- | ||
| | |[http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects QObjects] e o modelo do Qt Object (Isto é essencial para entender Qt) | ||
| | |[http://doc.qt.nokia.com/4.7/object.html Modelo de Objeto] | ||
|- | |- | ||
|qmake e o systema de construção do Qt | |qmake e o systema de construção do Qt | ||
| | |[http://doc.qt.nokia.com/4.7/qmake-manual.html Manual qmake] | ||
|} | |} | ||
== 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> | |||
== Usando o QMainWindow == | |||
Várias aplicações serão beneficiadas ao usar a [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow], que possui seu próprio layout no qual pode-se adicionar uma barra de menu, ''dock widgets'', barra de ferramentas e barra de status. [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow] 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&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; | textEdit = new QTextEdit; | ||
setCentralWidget(textEdit); | |||
setWindowTitle(tr( | setWindowTitle(tr("Notepad")); | ||
}</code> | |||
[http://doc.qt.nokia.com/4.7/qaction.html QActions] 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 [http://doc.qt.nokia.com/4.7/qicon.html ícones] 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 243: | ||
|- | |- | ||
|Main windows e suas classes | |Main windows e suas classes | ||
| | |[http://doc.qt.nokia.com/4.7/mainwindow.html Aplicação comMain Window], [http://doc.qt.nokia.com/4.7/examples-mainwindow.html Exemplos da Main Window] | ||
|- | |- | ||
|Aplicações MDI | |Aplicações MDI | ||
| | |[http://doc.qt.nokia.com/4.7/qmdiarea.html QMdiArea], [http://doc.qt.nokia.com/4.7/mainwindows-mdi.html Exemplo MDI] | ||
|} | |} | ||
Line 144: | Line 257: | ||
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 [http://doc.qt.nokia.com/4.7/qfiledialog.html QFileDialog], 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 [http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName 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 [http://doc.qt.nokia.com/4.7/qiodevice.html#open 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 [http://doc.qt.nokia.com/4.7/qmessagebox.html QMessageBox] para mostar um diálogo com uma mensagem de erro (veja a descrição da classe [http://doc.qt.nokia.com/4.7/qmessagebox.html QMessageBox] para maiores detalhes). | |||
Ler os dados do arquivo é trivial usando o método [http://doc.qt.nokia.com/4.7/qiodevice.html#readAll readAll()] que retorna todos os dados do arquivo em um [http://doc.qt.nokia.com/4.7/qbytearray.html QByteArray]. [http://doc.qt.nokia.com/4.7/qbytearray.html#constData constData()] retorna todos os dados em um array como um const char''', que pode ser usado para gerar uma [http://doc.qt.nokia.com/4.7/qstring.html QString]. O conteúdo pode ser mostrado na caixa de edição de texto. Então o método [http://doc.qt.nokia.com/4.7/qiodevice.html#closeé 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 [http://doc.qt.nokia.com/4.7/qtextstream.html QTextStream] que recebe um objeto tipo QFile. O stream de text pode escrever QStrings diretamente no arquivo enquanto [http://doc.qt.nokia.com/4.7/qfile.html QFile] somente aceita dado puro (char''') com o método [http://doc.qt.nokia.com/4.7/qiodevice.html#write write()] do [http://doc.qt.nokia.com/4.7/qiodevice.html QIODevice]. | |||
=== Aprenda Mais === | === Aprenda Mais === | ||
Line 163: | Line 304: | ||
|- | |- | ||
|Arquivos e dispositivos de entrada e saída | |Arquivos e dispositivos de entrada e saída | ||
| | |[http://doc.qt.nokia.com/4.7/qfile.html QFile], [http://doc.qt.nokia.com/4.7/qiodevice.html QIODevice] | ||
|} | |} |
Latest revision as of 17:52, 24 March 2016
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine. Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean. |
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 e QTextEdit, 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. 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. 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() 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.
Aprenda mais
|Sobre|Onde| |Widgets e geometria de janelas|Janelas e Diálogos |Eventos e manipulação de eventos|O Sistema de eventos
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, 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() é o slot de QApplication que finaliza a aplicação.clicked() é o sinal emitido por QPushButton quando este for pressionado. O método estático QObject::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. 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, 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.
Aprenda Mais
|Sobre|Onde| |Sinais e slots|Slots e Sinais |Layouts|Gerenciamento de Layout, widgets e Layouts, exemplos de layouts |Os widgets do Qt|Galeria de Widgets, exemplos
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 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 (textEdit e quitButton). Como regra: sempre devemos alocar os QObjects na heap e nunca copiá-los.
Usamos a função 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, Escrevendo código fonte para tradução, Example Olá tr(), Internationalização com Qt |
QObjects e o modelo do Qt Object (Isto é essencial para entender Qt) | Modelo de Objeto |
qmake e o systema de construção do Qt | Manual qmake |
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
Usando o QMainWindow
Várias aplicações serão beneficiadas ao usar a QMainWindow, 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 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&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 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 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, Exemplos da Main Window |
Aplicações MDI | QMdiArea, Exemplo MDI |
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, 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() 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(), 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 para mostar um diálogo com uma mensagem de erro (veja a descrição da classe QMessageBox para maiores detalhes).
Ler os dados do arquivo é trivial usando o método readAll() que retorna todos os dados do arquivo em um QByteArray. constData() retorna todos os dados em um array como um const char, que pode ser usado para gerar uma QString. O conteúdo pode ser mostrado na caixa de edição de texto. Então o método 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 que recebe um objeto tipo QFile. O stream de text pode escrever QStrings diretamente no arquivo enquanto QFile somente aceita dado puro (char) com o método write() do QIODevice.
Aprenda Mais
Sobre | Onde |
Arquivos e dispositivos de entrada e saída | QFile, QIODevice |