Menu dinâmico

6 respostas
Bambatera

Galera, sei que já existem vários posts aki no forum englobanco este assunto, porém, nenhum me ajudou.

Tenho uma aplicação em Java Swing, a qual faz acesso a um banco de dados PostgreSQL por meio de JPA.

Toda a estrutura do banco de dados já está pronta, mas estou tendo dificuldades de montar a lógica pra criar os menus do sistema dinamicamente de forma que eu possa ter um menu principal na JMenuBar e vários itens em cascada independente de nível.

Tipo:

MENU A
    |-MENU 1
    |-MENU 2
          |-MENU B
          |-MENU C
                |-MENU 3
                |-MENU 4
                      |-MENU D
                            |-MENU 5

E assim por diante. Como posso fazer isso???

Desde já agradeço a ajuda de todos.

6 Respostas

E

Em vez de um JMenu não é melhor usar um JTree (se houver tantos níveis em cascata assim?)
(Não que um JTree seja mais fácil de usar, he he).

De qualquer maneira, eis um exemplo de algoritmos recursivos que os professores não ensinam - eles ficam com essa lengalenga de Fibonacci e fatorial, que é completamente inútil, e não ensinam como preencher uma árvore, ou como andar sobre uma árvore de diretórios, que são coisas do dia-a-dia e muito úteis.

Bambatera

Não pretendo usar um JTree, o JMenu é exatamente o que preciso!!! Só estou tendo dificuldades de criar o algoritmo, que poderia ser até um XML.

J

entanglement:
Em vez de um JMenu não é melhor usar um JTree (se houver tantos níveis em cascata assim?)
(Não que um JTree seja mais fácil de usar, he he).

De qualquer maneira, eis um exemplo de algoritmos recursivos que os professores não ensinam - eles ficam com essa lengalenga de Fibonacci e fatorial, que é completamente inútil, e não ensinam como preencher uma árvore, ou como andar sobre uma árvore de diretórios, que são coisas do dia-a-dia e muito úteis.

Estou curioso…Quais seriam esses algoritmos recursivos?

E

Johnny, experimente tentar listar uma árvore de diretórios, e me diga se não é mais simples listá-la recursivamente.

Acho que você não consegue imaginar um algoritmo que não seja recursivo nesse caso, já que a própria estrutura de dados é recursiva.

Matheus_terra

entanglement:
Johnny, experimente tentar listar uma árvore de diretórios, e me diga se não é mais simples listá-la recursivamente.

Acho que você não consegue imaginar um algoritmo que não seja recursivo nesse caso, já que a própria estrutura de dados é recursiva.

Manda o algoritmo ai que também to curioso

Bambatera

Galera, após pesquisar muito na web, e tentar decifrar outras linguagens de programação consegui realizar a façanha de criar um menu dinâmico, porém, ainda não testei com vários níveis, mas mesmo assim vou postar o código aqui para quem quiser testar e corrigir ficar a vontade para fazê-lo.

/**
     * Realiza a montagem da Barra de Menus do sistema baseando-se no conteúdo
     * do banco de dados.
     *
     * @param vNewList Lista de Objetos do tipo <tt>Menu</tt> contendo as
     * informações de menus do sistema armazenadas no banco de dados.<p> É o
     * conteúdo da tabela &lt;tt&gt;menu&lt;/tt&gt; no banco de dados.<p> NÃO É A CLASSE
     * &lt;tt&gt;java.awt.Menu&lt;/tt&gt;.
     * @return Objeto do tipo &lt;tt&gt;javax.swing.JMenuBar&lt;/tt&gt; contendo a barra de
     * menus montada.
     */
    public static JMenuBar criaBarraMenus(List&lt;Menu&gt; vNewList) {
        JMenuBar barraMenus = new JMenuBar();
        for (int i = 0; i &lt; vNewList.size(); i++) {
            Menu menu = vNewList.get(i);
            if (menu.getNrMenupai() == null) {
                barraMenus.add(criaMenu(vNewList, menu));
            }
        }
        barraMenus.setFont(new Font("Segoe UI", Font.PLAIN, 12));
        return barraMenus;
    }

    /**
     * Realiza a montagem dos ítens de Menu para serem adicionados à Barra de
     * Menus.
     *
     * @param vNewList Lista de Objetos do tipo &lt;tt&gt;Menu&lt;/tt&gt; contendo as
     * informações de menus do sistema armazenadas no banco de dados.<p> É o
     * conteúdo da tabela &lt;tt&gt;menu&lt;/tt&gt; no banco de dados.<p> NÃO É A CLASSE
     * &lt;tt&gt;java.awt.Menu&lt;/tt&gt;.
     * @return Objeto do Tipo &lt;tt&gt;javax.swing.JComponent&lt;/tt&gt; representando um
     * ítem a ser adicionado à Barra de Menus.
     */
    private static JComponent criaMenu(List&lt;Menu&gt; vlstMenus, Menu vNewMenu) {
        JComponent cmpMenu = null;
        if (vNewMenu.getNrMenupai() == null && !vNewMenu.getBlMenupopup()) {
            cmpMenu = new JMenu(vNewMenu.getDsTitulo());
            cmpMenu.setName(vNewMenu.getNmMenu());
            cmpMenu.setActionMap(null); //Não adicionei nenhuma ação ainda.
            if (possuiFilho(vNewMenu.getNrMenu(), vlstMenus)) {
                for (int i = 0; i &lt; vlstMenus.size(); i++) {
                    Menu itemMenu = vlstMenus.get(i);
                    if (itemMenu.getNrMenupai() != null) {
                        if (itemMenu.getNrMenupai().getNrMenu() == vNewMenu.getNrMenu()) {
                            cmpMenu.add(criaMenu(vlstMenus, itemMenu));
                        }
                    }
                }
            }
        } else if (vNewMenu.getNrMenupai() != null && !vNewMenu.getBlMenupopup()) {
            if (possuiFilho(vNewMenu.getNrMenu(), vlstMenus)) {
                for (int i = 0; i &lt; vlstMenus.size(); i++) {
                    Menu itemMenu = vlstMenus.get(i);
                    if (itemMenu.getNrMenupai() != null) {
                        cmpMenu = new JMenu(itemMenu.getDsTitulo());
                        cmpMenu.setName(itemMenu.getNmMenu());
                        cmpMenu.setActionMap(null); //Não adicionei nenhuma ação ainda.
                        if (itemMenu.getNrMenupai().getNrMenu() == vNewMenu.getNrMenu()) {
                            cmpMenu.add(criaMenu(vlstMenus, itemMenu));
                        }
                    }
                }
            } else {
                cmpMenu = new JMenuItem(vNewMenu.getDsTitulo());
                cmpMenu.setName(vNewMenu.getNmMenu());
                cmpMenu.setActionMap(null); //Não adicionei nenhuma ação ainda.
            }
        }
        return cmpMenu;
    }

    /**
     * Verifica a existência de um nível inferior para o ítem de Menu.
     *
     * @param idMenu ID do menu pai.
     * @param vlstMenus Lisa de Menus para realizar a pesquisa.
     * @return &lt;tt&gt;true&lt;/tt&gt; caso o ítem pesquisado possua um "filho",
     * &lt;tt&gt;false&lt;/tt&gt; caso contrário.
     */
    private static boolean possuiFilho(short idMenu, List&lt;Menu&gt; vlstMenus) {
        List&lt;Menu&gt; lstMenus = vlstMenus;
        for (int i = 0; i &lt; lstMenus.size(); i++) {
            Menu itemMenu = lstMenus.get(i);
            if (itemMenu.getNrMenupai() != null) {
                if (idMenu == itemMenu.getNrMenupai().getNrMenu()) {
                    return true;
                }
            }

        }
        return false;
    }

Esta é a estrutura da tabela no banco de dados.
Estou usando o PostgreSQL 9.2.

CREATE TABLE dbsghu.menu (
  nr_menu SMALLINT DEFAULT nextval('menu_nr_id_seq'::regclass) NOT NULL,
  nm_menu VARCHAR(30) NOT NULL,
  ds_titulo VARCHAR(30) NOT NULL,
  ds_menu VARCHAR(100),
  nr_menupai SMALLINT,
  nr_menuordem SMALLINT DEFAULT 0 NOT NULL,
  im_menuicone BYTEA,
  bl_menupopup BOOLEAN DEFAULT false NOT NULL,
  nr_teclaatalho SMALLINT DEFAULT 0 NOT NULL,
  bl_ocupado BOOLEAN DEFAULT false NOT NULL,
  CONSTRAINT pk_menu1 PRIMARY KEY(nr_menu),
  CONSTRAINT uk_menu1 UNIQUE(nm_menu),
  CONSTRAINT fk_menu1 FOREIGN KEY (nr_menupai)
    REFERENCES dbsghu.menu(nr_menu)
    ON DELETE SET NULL
    ON UPDATE CASCADE
    DEFERRABLE
    INITIALLY IMMEDIATE
) 
WITH (oids = false);

COMMENT ON TABLE dbsghu.menu
IS 'Tabela de cadastro dos menus do sistema. Utilizada para cadastrar os menus e seus itens para permitir ou negar seu acesso por meio dos perfis.';

COMMENT ON COLUMN dbsghu.menu.nr_teclaatalho
IS 'Código ASCII da tecla que será utilizada como atalho.';

CREATE INDEX idx_menu1 ON dbsghu.menu
  USING btree (nr_menupai NULLS FIRST, nr_menuordem, nr_menu);

Quem testar e fizer alguma correção, por favor, informe aqui para que possamos melhorar mais este código.

Agora só preciso saber como faço pra adicionar a ação ao clicar no botão do menu, sendo que não estou utilizando a classe JMenuItem mas sim a JComponent.
Alguém pode me ajudar?

Criado 19 de abril de 2013
Ultima resposta 25 de abr. de 2013
Respostas 6
Participantes 4