Arquivo

Posts Tagged ‘primefaces pictures’

JSF 2 – PRIMEFACES – P:GALLERIA – EXEMPLO DE GALERIA DE FOTOS

Olá pessoal,

Um componente muito interessante para exibição de imagens é o galleria do primefaces. Irei explicar neste post como podemos usar este componente para exibir as imagens enviadas ao servidor e armazenadas no banco de dados.

Para nosso exemplo utilizarei:

Netbeans 7.0.1
Primefaces 3.0M3
Commons-io 2.0.1
Commons-fileupload 1.2.2

Além disso iremos usar a seguinte base de dados:

Iremos armazenar eventos e as fotos dos eventos. Salvaremos o nome do evento e sua data e ainda a imagem, uma descrição, a ordem que ela aparecerá e o evento ao qual esta imagem pertence.

Nosso projeto consistirá de um sistema que cadastraremos o evento e depois poderemos inserir imagens utilizando o fileupload ou visualizar as imagens com o galleria.

Veja a estrutura do projeto no netbeans, inclusive com as libs usadas:



Criamos uma estrutura com pacotes para separar DAO, modelos, fábrica de conexões, os managedbeans, etc. Abaixo irei colocar o código e explicar cada classe. No noss projeto irei utilizar o componente p:fileupload para enviar e gravar e capturar as imagens para que sejam salvas no banco de dados. Como ja vimos em dois posts como configurar este componente, irei falar dele com menos detalhes, afinal, a ênfase deve ser dada ao uso do galleria.

Classe Evento.java

public class Evento {

    private Long id;
    private String nome;
    private Date data;
    private List<Foto> fotos = new ArrayList<Foto>();

    public Date getData() {
        return data;
    }

    public void setData(Date data) {
        this.data = data;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public List<Foto> getFotos() {
        return fotos;
    }

    public void setFotos(List<Foto> fotos) {
        this.fotos = fotos;
    }
}

Classe Foto.java


public class Foto {

    private Long id;
    private byte[] imagem;
    private int ordem;
    private String descricao;
    private Evento evento = new Evento();

    public Evento getEvento() {
        return evento;
    }

    public void setEvento(Evento evento) {
        this.evento = evento;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public byte[] getImagem() {
        return imagem;
    }

    public void setImagem(byte[] imagem) {
        this.imagem = imagem;
    }

    public int getOrdem() {
        return ordem;
    }

    public void setOrdem(int ordem) {
        this.ordem = ordem;
    }

    public String getDescricao() {
        return descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }
}

As duas classes acima representam as tabelas Eventos e Fotos respectivamente. Primeiramente iremos abordar a cricação da estrutura para cadastrarmos os eventos, enviarmos e armazenarmos as fotos no banco.

No envio das fotos utilizaremos o componente fileupload, como nosso foco é o componente galleria não irei dar muitos detalhes da configuração do fileupload, para isso visite nosso outro post https://benignosales.wordpress.com/2011/03/17/jsf-2-0-primefaces-2-2-fileupload-com-imagecropper/ . Nele você encontrará todas as informações necessárias para configurar o componente de envio de arquivos.

Com o fileupload configurado, iremos criar nosso managed bean @SessionScoped, ele deve ser deste tipo para funcionar com o componente de envio de arquivos. Abaixo vamos conferir o código do gerenciador, para uma melhor visualização suprimi os getters e setters das variáveis.


@ManagedBean
@SessionScoped
public class GaleriaBean {

    private List<Evento> eventos = new ArrayList<Evento>();
    private Evento evento = new Evento();
    private Evento eventoSelecionado = new Evento();
    private EventoDAO eventoDAO = new EventoDAO();
    private FotoDAO fotoDAO = new FotoDAO();
    private Foto foto = new Foto();
    private StreamedContent imagem = new DefaultStreamedContent();
    private List<Foto> fotos = new ArrayList<Foto>();

    /* getters e setters */

    public void setFoto(Foto foto) {
        this.foto = foto;
    }

    public void salvaEvento() {
        try {
            eventoDAO.salva(evento);
            evento = new Evento();
            eventos = eventoDAO.listaTodos();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Evento adicionado", "Evento adicionado"));
        } catch (SQLException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void salvaFotos() {
        try {
            fotoDAO.salva(foto);
            foto = new Foto();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Foto adicionada", "Foto adicionada"));
        } catch (SQLException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void enviaImagem(FileUploadEvent event) {
        try {
            imagem = new DefaultStreamedContent(event.getFile().getInputstream());
            foto.setEvento(eventoSelecionado);
            foto.setImagem(event.getFile().getContents());
        } catch (IOException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void criaArquivo(byte[] bytes, String arquivo) {
        FileOutputStream fos;
        try {
            fos = new FileOutputStream(arquivo);
            fos.write(bytes);
            fos.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void listaFotosEvento() {
        try {
            fotos = fotoDAO.buscaPorEvento(eventoSelecionado);
            for (Foto f : fotos) {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                ServletContext scontext = (ServletContext) facesContext.getExternalContext().getContext();
                String nomeArquivo = f.getId().toString() + ".jpg";
                String arquivo = scontext.getRealPath("/temp/" + nomeArquivo);
                criaArquivo(f.getImagem(), arquivo);
            }
        } catch (SQLException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public GaleriaBean() {
        try {
            eventos = eventoDAO.listaTodos();
        } catch (SQLException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Temos uma coleção do tipo Evento na qual iremos jogar todos os eventos cadastrados no banco para exibirmos em um datatable, dois objetos do tipo Evento um para o cadastro e outro para a visualização e envio de imagens, um objeto Foto e uma coleção Foto, bem como um objeto StreamedContent que serve para aualizarmos dinamicamente um p:graphicimage e temos os DAOs.

Outro ponto, não iremos colocar o código dos DAOs, pois você pode trabalhar com o que quiser para a camada de persistencia, no meu caso, usei jdbc puro sem nenhuma framework ORM. Caso alguem queira os DAOs basta postar um comentário que envio.

Nos métodos temos o salvaEvento para persistirmos os eventos no banco e temos o salvaFotos para guardarmos as imagens no banco de dados. Além disso, o enviaImagem que é o listener do componente fileupload, ou seja, sempre que enviarmos um arquivo o sistema chama este método para “tratarmos” o arquivos como quisermos. Aqui, preenchemos o objeto StreamedContent imagem para exibir a imagem enviada na tela e setamos o objeto foto para que possamos salvá-lo depois. Mais abaixo, temos o método criaArquivo que serve para criar o arquivo físico a partir de um array de bytes e um caminho específico e o método listaFotosEvento, com o qual criamos os arquivos a serem exibidos na galeria. O grande lance é justamente esse, os arquivos devem ser criados dinamicamente e jogados dentro de uma pasta para serem exibidos na tela, pois o graphicImage não suporta conteudos dinamicos em listas, como um datatable ou mesmo no galleria.

Com isso, passamos para a nossa view. Veja o código abaixo:

Obs.: Crie uma pasta dentro da pasta web para armazenar temporariamente as imagens. No nossa caso, criei a pasta temp.

    <h:head>
        <title>Exemplo Galleria - Benigno Sales</title>
    </h:head>
    <h:body style="background-color: #CCCCCC">
        <h:form prependId="false" enctype="multipart/form-data">
            <p:panel id="dadosEvento" header="Exemplo Galeria" style="width: 600px;">
                <p:growl/>
                <h:panelGrid columns="2">
                    <h:outputText value="Nome"/>
                    <p:inputText value="#{galeriaBean.evento.nome}" size="40"/>
                    <h:outputText value="Data"/>
                    <p:calendar value="#{galeriaBean.evento.data}"
                                timeZone="GMT-3"
                                navigator="true"
                                pattern="dd/MM/yyyy"
                                locale="pt_BR"/>
                    <p:commandButton value="Salvar" action="#{galeriaBean.salvaEvento()}" update="tabelaEventos dadosEvento"/>
                    <p:commandButton value="Limpar" onclick="form.reset()"/>
                    <p:ajaxStatus>
                        <f:facet name="start">
                            <h:outputText value="aguarde..."/>
                        </f:facet>
                        <f:facet name="complete">
                            <h:outputText value=""/>
                        </f:facet>
                    </p:ajaxStatus>
                </h:panelGrid>
            </p:panel>
            <p:dialog id="dialogFotos" position="top" widgetVar="dialogFotos" modal="true" minWidth="600" minHeight="500">
                <p:fileUpload fileUploadListener="#{galeriaBean.enviaImagem}"
                              update="imagemTmp"
                              cancelLabel="Cancelar"
                              fileLimit="100000"
                              fileLimitMessage="Imagem muito grande"
                              label="Selecionar"
                              invalidFileMessage="Tipo de imagem inválido"
                              invalidSizeMessage="Imagem muito grande"
                              uploadLabel="Enviar"
                              allowTypes="/(\.|\/)(jpe?g|png)$/">

                </p:fileUpload>
                <p:outputPanel id="dadosFoto">
                    <h:panelGrid>
                        <p:graphicImage cache="false" id="imagemTmp" value="#{galeriaBean.imagem}" height="300" style="margin: 0 auto;"/>
                        <h:outputText value="Descrição"/>
                        <p:inputText value="#{galeriaBean.foto.descricao}" size="49"/>
                        <h:outputText value="Ordem"/>
                        <p:inputMask mask="9" value="#{galeriaBean.foto.ordem}" size="5"/>
                    </h:panelGrid>
                </p:outputPanel>
                <p:commandButton value="Adicionar" action="#{galeriaBean.salvaFotos()}" update="dadosFoto dadosEvento"/>
            </p:dialog>
            <p:dialog id="dialogGaleria" widgetVar="dialogGaleria" modal="true" position="top"
                      minWidth="440" minHeight="500">
                <h:outputText value="Nenhuma imagem encontrada" rendered="#{galeriaBean.fotos.size()==0}"/>
                <p:galleria value="#{galeriaBean.fotos}"
                            var="galeria" effect="slide" effectSpeed="2000"
                            panelHeight="300" panelWidth="400"
                            frameHeight="50" frameWidth="50"
                            filmstripPosition="bottom" showOverlays="true">
                    <p:graphicImage value="/temp/#{galeria.id}.jpg" cache="false" width="400" height="300"
                                    title="#{galeria.descricao}" alt="#{galeria.descricao}"/>

                    <p:galleriaOverlay title="#{galeria.descricao}">
                    </p:galleriaOverlay>
                </p:galleria>
            </p:dialog>
            <p:dataTable id="tabelaEventos"
                         value="#{galeriaBean.eventos}" var="evento" style="width: 610px;"
                         emptyMessage="Nenhum evento cadastrado"
                         rows="6"
                         paginator="true"
                         paginatorPosition="bottom"
                         paginatorAlwaysVisible="false">
                <p:column headerText="Id">
                    <h:outputText value="#{evento.id}"/>
                </p:column>
                <p:column headerText="Evento">
                    <h:outputText value="#{evento.nome}"/>
                </p:column>
                <p:column headerText="Data">
                    <h:outputText value="#{evento.data}">
                        <f:convertDateTime pattern="dd/MM/yyyy"/>
                    </h:outputText>
                </p:column>
                <p:column>
                    <p:commandButton image="ui-icon-plus" title="Adicionar Imagem" oncomplete="dialogFotos.show();" update="dadosFoto">
                        <f:setPropertyActionListener target="#{galeriaBean.eventoSelecionado}" value="#{evento}"/>
                    </p:commandButton>
                    <p:commandButton image="ui-icon-search" title="Ver Imagens" action="#{galeriaBean.listaFotosEvento()}" update="dialogGaleria" oncomplete="dialogGaleria.show()">
                        <f:setPropertyActionListener target="#{galeriaBean.eventoSelecionado}" value="#{evento}"/>
                    </p:commandButton>
                </p:column>
            </p:dataTable>
        </h:form>
    </h:body>
</html>

É uma tela simples, mas que da um grande resultado. Uma área para o cadastro dos eventos e um dataTable para listar estes eventos. Em uma coluna do dataTable colocamos dois botões, um para exibirmos as imagens(fotos) e outro para enviarmos as fotos.

O Componente Galleria tem alguns atributos que gostaria de destacar, são eles:

 value  null  String  Coleção que possui os dados das imagens
 var  null  String  Variavel  que vai interagir com a coleção
 panelHeight/panelWidth  –  Integer  Largura e altura do painel
 frameHeight/frameWidth  –  Integer  Largura e altura das miniaturas

style

null

String

 Estilo

styleClass

null

String

 Classe de estilo

effect

fade

String

 Nome da animação

filmstripPosition  top  String  Posição das miniaturas
showOverlays  true  boolean  Exibição das legendas

Abaixo eu criei um vídeo com o projeto em execução:

Ah! O vídeo foi feito com testes no primefaces 2.2.1, nesta versão a galeria era meio feinha. Abaixo vou postar como ficou com a versão 3M3 do prime.

Bom, é isso pessoal. Dúvidas? postem aqui! Abraço a todos e compartilhem suas idéias.