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

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
[toc align_right="yes" depth="4"]
[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><br />#include &lt;QApplication&amp;gt;<br />#include &lt;QTextEdit&amp;gt;
<code>
#include <QApplication>
#include <QTextEdit>


int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);
int main(int argv, char **args)
{
QApplication app(argv, args);


QTextEdit textEdit;<br /> textEdit.show();<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br /></code>
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 &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/4.7/qapplication.html e &quot;QTextEdit&amp;quot;: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.
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 &quot;QApplication&amp;quot;: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.
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 &quot;QTextEdit&amp;quot;: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.
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 &quot;show()&quot;:http://doc.trolltech.com/4.7/qwidget.html#show deve ser chamado para fazer o widget visível.
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<br />qmake<br />make</code>
<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 <s>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.
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.
<br />h3. Aprenda mais
 
<br />|'''Sobre'''|'''Onde'''|<br />|Widgets e geometria de janelas|&quot;Janelas e Diálogos&amp;quot;:http://doc.qt.nokia.com/4.7/application-windows.html|<br />|Eventos e manipulação de eventos|&quot;O Sistema de eventos&amp;quot;:http://doc.qt.nokia.com/4.7/eventsandfilters.html|
h3. Aprenda mais
<br />h2. Adicionando um botão de saída
 
<br />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).
|'''Sobre'''|'''Onde'''|
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|Editor de texto com botão para fechar]]
|Widgets e geometria de janelas|"Janelas e Diálogos":http://doc.qt.nokia.com/4.7/application-windows.html|
<br />Vamos analizar o código linha a linha:
|Eventos e manipulação de eventos|"O Sistema de eventos":http://doc.qt.nokia.com/4.7/eventsandfilters.html|
<br /><code>#include &lt;QtGui&amp;gt;
 
<br />int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);
h2. Adicionando um botão de saída
<br /> QTextEdit textEdit;<br /> QPushButton quitButton(&quot;Sair&amp;quot;);
 
<br /> QObject::connect(&amp;quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
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).
<br /> QVBoxLayout layout;<br /> layout.addWidget(&amp;textEdit);<br /> layout.addWidget(&amp;quitButton);
 
<br /> QWidget window;<br /> window.setLayout(&amp;layout);
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|Editor de texto com botão para fechar]]
<br /> window.show();
 
<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}</code>
Vamos analizar o código linha a linha:
<br />A linha 1 inclui &quot;QtGui&amp;quot;:http://doc.qt.nokia.com/4.7/qtgui.html, que contém todas as classes de elementos gráficos Qt.
 
<br />A Linha 10 usa o mecanismo de sinais e slots (''signals &amp; 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 &quot;conectar o slot no sinal e emitir o sinal&amp;quot;.
<code>#include <QtGui>
<br />&quot;quit()&quot;:http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit é o ''slot'' de QApplication que finaliza a aplicação.&quot; clicked()&quot;:http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked é o sinal emitido por &quot;QPushButton&amp;quot;:http://doc.qt.nokia.com/4.7/qpushbutton.html quando este for pressionado. O método estático &quot;QObject::connect() &quot;: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.
 
<br />A linha 12 cria um &quot;QVBoxLayout&amp;quot;: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. &quot;QVBoxLayout&amp;quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html, por exemplo, posiciona os filhos verticalmente.
int main(int argv, char **args)
<br />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.
{
<br />h3. Aprenda Mais
QApplication app(argv, args);
<br />|'''Sobre'''|'''Onde'''|<br />|Sinais e slots|&quot;Slots e Sinais&amp;quot;:http://doc.qt.nokia.com/4.7/signalsandslots.html|<br />|Layouts|&quot;Gerenciamento de Layout&amp;quot;:http://doc.qt.nokia.com/4.7/layout.html, &quot;widgets e Layouts&amp;quot;:http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, &quot;exemplos de layouts&amp;quot;:http://doc.qt.nokia.com/4.7/examples-layouts.html|<br />|Os widgets do Qt|&quot;Galeria de Widgets&amp;quot;:http://doc.qt.nokia.com/4.7/gallery.html, &quot;exemplos&amp;quot;:http://doc.qt.nokia.com/4.7/examples-widgets.html|
 
<br />h2. Herdando de QWidget
QTextEdit textEdit;
<br />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 &quot;QWidget&amp;quot;:http://doc.qt.nokia.com/4.7/qwidget.html e adicionamos um slot que foi conectado ao botão '''Sair'''.
QPushButton quitButton("Sair");
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs3.png|Herdando de QWidget]]
 
<br />O código:<br /><code>class Notepad : public QWidget<br />{<br /> Q_OBJECT
QObject::connect(&amp;quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
<br />public:<br /> Notepad();
 
<br />private slots:<br /> void quit();
QVBoxLayout layout;
<br />private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br />};</code>
layout.addWidget(&amp;textEdit);
<br />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.
layout.addWidget(&amp;quitButton);
<br />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)
 
<br />Ao invés de iniciarmos a interface gráfica e conectarmos o slot dentro da função main(), agora usamos o contrutor do ''Notepad''.
QWidget window;
<br /><code>Notepad::Notepad()<br />{<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr(&quot;Quit&amp;quot;));
window.setLayout(&amp;layout);
<br /> connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));
 
<br /> QVBoxLayout *layout = new QVBoxLayout;<br /> layout</s>&gt;addWidget(textEdit);<br /> layout-&gt;addWidget(quitButton);
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 &amp; 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(&quot;Notepad&amp;quot;));<br />}<br /></code>
setWindowTitle(tr("Notepad"));
}
</code>


Como podemos ver na definição da classe, usamos ponteiros para os nossos &quot;QObjects&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html (textEdit e quitButton). Como regra: sempre devemos alocar os &quot;QObjects&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html na ''heap'' e nunca copiá-los.
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 &quot;tr()&quot;: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'''.
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
|&quot;Manual do Qt Linguist&amp;quot;:http://doc.qt.nokia.com/4.7/linguist-manual.html, &quot;Escrevendo código fonte para tradução&amp;quot;:http://doc.qt.nokia.com/4.7/i18n-source-translation.html, &quot;Example Olá tr()&quot;:http://doc.qt.nokia.com/4.7/linguist-hellotr.html, &quot;Internationalização com Qt&amp;quot;:http://doc.qt.nokia.com/4.7/internationalization.html
|"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
|-
|-
|&quot;QObjects&amp;quot;:http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects e o modelo do Qt Object (Isto é essencial para entender Qt)
|"QObjects":http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects e o modelo do Qt Object (Isto é essencial para entender Qt)
|&quot;Modelo de Objeto&amp;quot;:http://doc.qt.nokia.com/4.7/object.html
|"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
|&quot;Manual qmake&amp;quot;:http://doc.qt.nokia.com/4.7/qmake-manual.html
|"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 <s>project do qmake.
Para este exemplo escreveremos nosso próprio arquivo .pro ao invés de usarmos a opção -project do qmake.
<br /><code>HEADERS = notepad.h<br />SOURCES = notepad.cpp main.cpp<br /></code>
 
<br />Para compilar o programa siga os seguintes passos:
<code>HEADERS = notepad.h
<br /><code>qmake<br />make</code>
SOURCES = notepad.cpp main.cpp
<br />h2. Usando o QMainWindow
</code>
<br />Várias aplicações serão beneficiadas ao usar a &quot;QMainWindow&amp;quot;: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. &quot;QMainWindow&amp;quot;: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.
 
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|Usando QMainWindow]]
Para compilar o programa siga os seguintes passos:
<br />Vamos à nova definição da classe Notepad.
 
<br /><code>#include &lt;QtGui&amp;gt;
<code>qmake
<br />class Notepad : public QMainWindow<br />{<br /> Q_OBJECT  
make</code>
<br />public:<br /> Notepad();
 
<br />private slots:<br /> void open();<br /> void save();<br /> void quit();
h2. Usando o QMainWindow
<br />private:<br /> QTextEdit *textEdit;
 
<br /> QAction *openAction;<br /> QAction *saveAction;<br /> QAction *exitAction;
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.
<br /> QMenu *fileMenu;<br />};<br /></code>
 
<br />Incluímos mais dois slots que podem salvar e abrir um documento. Iremos implementá-los na próxima sessão.
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|Usando QMainWindow]]
<br />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.
 
<br />Como antes, usamos o costrutor do Notepad para iniciar a interface gráfica.
Vamos à nova definição da classe Notepad.
<br /><code>Notepad::Notepad()<br />{<br /> saveAction = new QAction(tr(&quot;&amp;Open&amp;quot;), this);<br /> saveAction = new QAction(tr(&quot;&amp;Save&amp;quot;), this);<br /> exitAction = new QAction(tr(&quot;E&amp;amp;xit&amp;quot;), this);
 
<br /> connect(openAction, SIGNAL (triggered()), this, SLOT (open()));<br /> connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));<br /> connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
<code>#include <QtGui>
<br /> fileMenu = menuBar()</s>&gt;addMenu(tr(&quot;&amp;File&amp;quot;));<br /> fileMenu-&gt;addAction(openAction);<br /> fileMenu-&gt;addAction(saveAction);<br /> fileMenu-&gt;addSeparator();<br /> fileMenu-&gt;addAction(exitAction);
 
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("&amp;Open"), this);
saveAction = new QAction(tr("&amp;Save"), this);
exitAction = new QAction(tr("E&amp;amp;xit"), this);


textEdit = new QTextEdit;<br /> setCentralWidget(textEdit);
connect(openAction, SIGNAL (triggered()), this, SLOT (open()));
connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));
connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));


setWindowTitle(tr(&quot;Notepad&amp;quot;));<br />}</code>
fileMenu = menuBar()->addMenu(tr("&amp;File"));
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);


&quot;QActions&amp;quot;: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 &quot;ícones&amp;quot;:http://doc.qt.nokia.com/4.7/qicon.html nos QActions.
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
|&quot;Aplicação comMain Window&amp;quot;:http://doc.qt.nokia.com/4.7/mainwindow.html, &quot;Exemplos da Main Window&amp;quot;:http://doc.qt.nokia.com/4.7/examples-mainwindow.html
|"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
|&quot;QMdiArea&amp;quot;:http://doc.qt.nokia.com/4.7/qmdiarea.html, &quot;Exemplo MDI&amp;quot;:http://doc.qt.nokia.com/4.7/mainwindows-mdi.html
|"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(&quot;Open File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp '''.h)&quot;));
<code>QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
<br />if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr(&quot;Error&amp;quot;),<br /> tr(&quot;Could not open file&amp;quot;));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit-&gt;setPlainText(contents);<br /> file.close();<br />}</code>
tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)"));
<br />O primeiro passo é perguntar ao usuário pelo nome do arquivo que deseja abrir. Qt vem com o &quot;QFileDialog&amp;quot;: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 &quot;getOpenFileName()&quot;: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.
 
<br />Se nós tivermos um nome de arquivo então tentaremos abrí-lo uando o método &quot;open()&quot;: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 &quot;QMessageBox&amp;quot;: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 &quot;QMessageBox&amp;quot;:http://doc.qt.nokia.com/4.7/qmessagebox.html para maiores detalhes).
if (fileName != "") {
<br />Ler os dados do arquivo é trivial usando o método &quot;readAll()&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#readAll que retorna todos os dados do arquivo em um &quot;QByteArray&amp;quot;:http://doc.qt.nokia.com/4.7/qbytearray.html. &quot;constData()&quot;: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 &quot;QString&amp;quot;: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 &quot;close() &quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#closeé invocado para retornar o descritor de arquivo para o sistema operacional.
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(&quot;Save File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp '''.h)&quot;));  
<code>QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "",
<br />if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&amp;file);<br /> stream &lt;&lt; textEdit-&gt;toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br />}</code>
tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)"));  
<br />Quando escrevemos o conteúdo da caixa de edição de texto no arquivo usamos a classe &quot;QTextStream&amp;quot;: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 &quot;QFile&amp;quot;:http://doc.qt.nokia.com/4.7/qfile.html somente aceita dado puro (char''') com o método &quot;write()&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#write do &quot;QIODevice&amp;quot;:http://doc.qt.nokia.com/4.7/qiodevice.html.
 
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
// error message
} else {
QTextStream stream(&amp;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
|&quot;QFile&amp;quot;:http://doc.qt.nokia.com/4.7/qfile.html, &quot;QIODevice&amp;quot;:http://doc.qt.nokia.com/4.7/qiodevice.html
|"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(&amp;quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));

 QVBoxLayout layout;
 layout.addWidget(&amp;textEdit);
 layout.addWidget(&amp;quitButton);

 QWidget window;
 window.setLayout(&amp;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.

p=. Herdando de QWidget

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.

p=. Usando QMainWindow

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("&amp;Open"), this);
 saveAction = new QAction(tr("&amp;Save"), this);
 exitAction = new QAction(tr("E&amp;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("&amp;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(&amp;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