Artigos‎ > ‎Qt‎ > ‎

QAction

Criar uma interface gráfica para o usuário que seja bem organizada e intuitiva, normalmente envolve criar menus, barras de ferramentas e barra de status. Para tornar essa tarefa mais simples, existe no Qt a classe QAction. Essa classe nos permite criar ações na qual podemos: conectar Slots, incluir o texto da ação, ícone, atalho de teclado, texto de ajuda, etc. Dessa forma fica muito fácil sincronizar menus e barras de ferramentas, pois a mesma ação tanto no menu quanto na barra de ferramentas estarão conectadas a um mesmo objeto QAction.

Como primeiro exemplo, vamos criar um programinha simples que abre e imprime um documento de texto.


 
 

Este é o arquivo de cabeçalho mainwindow.h:

 


#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QtGui>

class MainWindow : public QMainWindow

{

    Q_OBJECT

public:

    MainWindow(QWidget *parent = 0);

    ~MainWindow();

private slots:

    void open();

    void print();

    void textChanged();

private:

    QTextEdit *textEdit;

    QAction *openAct;

    QAction *printAct;

    QAction *exitAct;

    QMenu *fileMenu;

    QToolBar *fileTBar;

};

#endif // MAINWINDOW_H


 

No arquivo de cabeçalho declaramos:

A função open() para abrir um arquivo;

A função print() para imprimir o arquivo;

A função textChanged() para verificar alteração no texto;

Um objeto QTextEdit no qual vamos visualizar o arquivo de texto aberto;

Três objetos QAction que serão as ações para abrir, imprimir e fechar o programa;

Um QMenu que será o menu [Arquivo];

Um QToolBar que será nossa barra de ferramentas “Arquivo”.


Vamos ao construtor de mainwindow.ccp.


 

MainWindow::MainWindow(QWidget *parent)

    : QMainWindow(parent)

{

    textEdit = new QTextEdit;

    setCentralWidget(textEdit);

    connect(textEdit, SIGNAL(textChanged()), this, SLOT(textChanged()));

    openAct = new QAction(QIcon(":/images/open.png"), tr("&Abrir"), this);

    openAct->setShortcut(QKeySequence::New);

    openAct->setStatusTip(tr("Abre um arquivo"));

    connect(openAct, SIGNAL(triggered()), this, SLOT(open()));

    printAct = new QAction(QIcon(":/images/print.png"), tr("&Imprimir"), this);

    printAct->setShortcut(QKeySequence::Print);

    printAct->setStatusTip(tr("Imprime o arquivo aberto"));

    printAct->setEnabled(false);

    connect(printAct, SIGNAL(triggered()), this, SLOT(print()));

    exitAct = new QAction(QIcon(":/images/exit.png"), tr("&Sair"), this);

    exitAct->setShortcut(QKeySequence::Close);

    exitAct->setStatusTip(tr("Sair do programa"));

    connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

    fileMenu = menuBar()->addMenu(tr("&Arquivo"));

    fileMenu->addAction(openAct);

    fileMenu->addAction(printAct);

    fileMenu->addAction(exitAct);

    fileTBar = addToolBar(tr("Arquivo"));

    fileTBar->addAction(openAct);

    fileTBar->addAction(printAct);

    statusBar()->show();

}



Primeiro criamos um QTextEdit e o definimos como Widget central da classe QMainWindow. Conectamos o sinal textChanged() a um slot criado com o mesmo nome, o qual vai servir para desabilitar o botão imprimir.

Criamos os objetos QAction passando logo no construtos o ícone e o texto. Os atalhos para cada ação foram definidos com setShortcut usando como argumentos o padrão de atalhos definidos no Qt. Isso é interessante pois, a depender do sistema, o padrão de atalhos pode ser diferente. Por exemplo: No Windows o atalho padrão para sair da aplicação é Ctrl+F4 e no Linux normalmente se usa Ctrl+W. Da forma que criamos os atalhos usando o padrão da biblioteca do Qt, se compilarmos no Windows, atalho para sair será Ctrl+F4 e compilando no Linux será Ctrl+W.

Embora seja conveniente usar os atalhos padrões sempre que possível, também podemos criar nossos atalhos como quisermos. No atalho de printAct poderíamos definir o atalho dessa forma:

 


    printAct->setShortcut(QKeySequence("Ctrl+P"));

 

ou

 

    printAct->setShortcut(Qt::CTRL + Qt::Key_P);


 

Depois de criar os atalhos, definimos o texto que será exibido na barra de status com a função setStatusTip e finalmente conectamos algum sinal da ação com algum slot.

 

Após criarmos as ações, podemos criar o menu e a barra de ferramentas, adicionando a eles as ações criadas.

 

Por fim, exibimos a barra de status.

 

Em alguns sistemas, por padrão os ícones não são visíveis no menu. Se quisermos que sempre sejam exibidos os ícones no menu, temos que setar como true a propriedade setIconVisibleInMenu do QAction.

 
 

A implementação das funções open() e print() foram omitidas para poupar espaço, mas o código fonte completo está em anexo no fim desta página.

 

Podemos adicionar um menu a um QAction, permitindo assim criar um submenu para uma ação.

Vamos pegar nosso exemplo anterior, criar um menu de arquivos recentes, e adicionar esse menu a uma QAction. Essa ação vai permitir abrir um arquivo ou mostrar um menu de arquivos recentes.




Primeiro vamos organizar melhor melhor nosso exemplo, criando as funções createActions(), createMenus(), createToolBars() e createStatusBar() para o código do construtor não ficar muito grande.

 

Em createActions() vamos criar um QAction  openAndRecentAct e dez  recentFileAct para serrem adicionados ao menu.


 

  openAndRecentAct = new QAction(QIcon(":/images/open.png"), tr("Abrir"), this);

 openAndRecentAct->setStatusTip(tr("Abre um arquivo"));

 connect(openAndRecentAct, SIGNAL(triggered()), this, SLOT(open()));

  for (int x = 0; x < 10; x++)

  {

    recentFileAct[x] = new QAction(this);

    recentFileAct[x]->setVisible(false);

    connect( recentFileAct[x], SIGNAL(triggered()), this, SLOT(openRecentFile()));

  }


 

Em createMenus(), criamos um QMenu  recentFilesMenu que será um submenu de fileMenu. Depois adicionamos as ações criadas ao menu recentFilesMenu e chamamos a função updateRecentFileActions() para atualizar o menu de arquivos recentes.

 


  recentFilesMenu = fileMenu->addMenu(tr("Abrir &recente"));

        for (int x = 0; x < 10; x++)

                recentFilesMenu->addAction(recentFileAct[x]);

  updateRecentFileActions();

 


Como o QMenu  recentFilesMenu já foi criado, podemos adicionar ele no QAction  openAndRecentAct. Depois adicionamos a ação na barra de ferramentas.

 


  openAndRecentAct->setMenu(recentFilesMenu);

  fileTBar->addAction(openAndRecentAct


 

Por último vamos adicionar a este exemplo, opções de alinhamento do parágrafo.


 
 

Para isso, vamos utilizar a opção Checkable do QAction e um QActionGroup. 
Criamos um slot alignChange() que faz um casting dinâmico de QAction e depois, seta o alinhamento do parágrafo conforme o valor retornado por data(), referente ao QAction recebido.
 


void MainWindow::alignChange()
{
   QAction *clickedAct = qobject_cast<QAction *>(sender());
   textEdit->setAlignment(Qt::Alignment(clickedAct->data().toInt()));
}

 


A função data() retorna um Qvariant, que é atribuído pala função setData().

Isso nos permite adicionar uma marca ou uma informação adicional ao objeto QAction.
 
Em createActions() criamos as ações, definindo setCheckable(true) para a ação ter um comportamento booleano, atribuímos o alinhamento referente a cada QAction usando setData() e depois conectamos seus sinais ao slot alignChange().
 


    leftAlignAct = new QAction(QIcon(":/images/left.png"),"Esquerda", this);
    leftAlignAct->setStatusTip(tr("Alinha o parágrafo à esquerda"));
    leftAlignAct->setData(Qt::AlignLeft);
    leftAlignAct->setCheckable(true);
    leftAlignAct->setChecked(true);
    connect(leftAlignAct, SIGNAL(triggered()), this, SLOT(alignChange()));
 
    rightAlignAct = new QAction(QIcon(":/images/right.png"), "Direita", this);
    rightAlignAct->setStatusTip(tr("Alinha o parágrafo à direita"));
    rightAlignAct->setData(Qt::AlignRight);
    rightAlignAct->setCheckable(true);
    connect(rightAlignAct, SIGNAL(triggered()), this, SLOT(alignChange()));
 
    centerAlignAct = new QAction(QIcon(":/images/center.png"), "Centralizado", this);
    centerAlignAct->setStatusTip(tr("Centralizar o parágrafo"));
    centerAlignAct->setData(Qt::AlignCenter);
    centerAlignAct->setCheckable(true);
    connect(centerAlignAct, SIGNAL(triggered()), this, SLOT(alignChange()));
 
    justifyAlignAct = new QAction(QIcon(":/images/justify.png"), "Justificado", this);
    justifyAlignAct->setStatusTip(tr("Justificar o parágrafo"));
    justifyAlignAct->setData(Qt::AlignJustify);
    justifyAlignAct->setCheckable(true);
    connect(justifyAlignAct, SIGNAL(triggered()), this, SLOT(alignChange()));

 


Poderíamos ter usado setProperty  em vez de setData para definir o alinhamento em cada QAction. A propriedade property é definida em QObject e por isso está presente em praticamente todos os objetos o Qt.

Para usarmos property, temos que indicar um nome que serve como uma identidade para uma propriedade. Isso permite que criemos várias propriedades para um objeto.

Se tivéssemos usado property no nosso exemplo, o alinhamento referente a cada QAction seria setado assim:


    leftAlignAct->setProperty("Alinhamento", Qt::AlignLeft);

e lido assim:

    textEdit->setAlignment(Qt::Alignment(clickedAct->property("Alinhamento").toInt()));


Com QActionGroup *alignActGroup definido em nosso arquivo de cabeçalho, criamos o grupo alignActGroup  e adicionamos as ações de alinhamento a ele.

 
    alignActGroup = new QActionGroup(this);
    alignActGroup->addAction(leftAlignAct);
    alignActGroup->addAction(centerAlignAct);
    alignActGroup->addAction(rightAlignAct);
    alignActGroup->addAction(justifyAlignAct);

 


Quando adicionamos QActions que estão definidos com Checkable = true em um  QActionGroup, eles se comportam como um grupo de opções que somente uma pode estar com Checked = true. Isto é: Só podemos selecionar uma opção do grupo.

Em createMenus(), criamos o menu “Formatar”, adicionando as ações de  alignActGroup.
 


    formatMenu = menuBar()->addMenu(tr("&Formatar"));
    formatMenu->addActions(alignActGroup->actions());

 


Em createToolBars(), adicionamos a barra de ferramentas “Formatar” e  também adicionamos  alignActGroup.
 


    formatTBar = addToolBar(tr("Formatar"));
    formatTBar->addActions(alignActGroup->actions());


 
Por último, vamos adicionar um componente QFontComboBox a nossa barra de ferramentas.
Com QFontComboBox *fontComboBox definido em nosso arquivo de cabeçalho, adicionamos ele na nossa barra de ferramentas “Formatar”:
 


  formatTBar->addWidget(fontComboBox); 





Chagamos ao fim deste artigo. Foram omitidas várias partes do código para simplificar a teoria e mantermos o foco no objeto QAction.

O código fonte completo deste exemplo está em anexo logo abaixo.

 

Até a próxima!

ċ
Exemplo01.zip
(16k)
Rafael Fassi,
15 de fev de 2011 20:07
Comments