2009-12-14 7 views
0

J'ai un éditeur avec beaucoup de miniatures d'images. Je voudrais un double-clic sur une image pour afficher l'image en pleine résolution en utilisant une boîte de dialogue modale non décorée. Idéalement, ceci serait animé, pour montrer l'image zoomant en pleine résolution sur le centre de l'écran, alors n'importe quel clic ferait disparaître l'image, soit en zoomant vers l'arrière, soit en disparaissant.Effet Swing animé pour afficher une image en pleine résolution

Je ne suis pas concerné par l'établissement d'un comportement exact, je veux juste quelque chose de lisse. J'ai trouvé beaucoup d'exemples de JavaScript pour cela, mais est-ce qu'il y a quelque chose de construit pour Swing?

+1

Cela semble être un bon candidat pour un composant générique réutilisable. Est-ce que quelqu'un est au courant d'un? –

+0

Ce n'est pas vraiment une réponse à votre question, mais pour un excellent article sur la mise à l'échelle de l'image en général, je recommande l'article de Chris Campbell "The Perils of Image.getScaledInstance" (http://today.java.net/pub/a /today/2007/04/03/perils-of-image-getscaledinstance.html) – Ash

+0

Vous pouvez également consulter l'application d'animation open source "Project Onyx" (http://www.pushing-pixels.org/? p = 1231). Le troisième film de démo ressemble à ce que vous cherchez – Ash

Répondre

1

Ce morceau de code fait plus ou moins le truc ... Il y a encore un problème dans la façon dont je suis la mise en l'emplacement de la boîte de dialogue ...

Hope it helps.

import java.awt.BorderLayout; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.geom.AffineTransform; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.lang.reflect.InvocationTargetException; 

import javax.imageio.ImageIO; 
import javax.swing.JButton; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class OpenImageZooming { 

private static final int NB_STEPS = 30; 

private static final long OPENING_TOTAL_DURATION = 3000; 

public static void main(String[] args) { 
    OpenImageZooming me = new OpenImageZooming(); 
    me.openImage(args[0]); 
} 

private JFrame frame; 
private JDialog dialog; 
private JPanelZooming panelZooming; 

private void openImage(final String imagePath) { 
    SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
    frame = new JFrame(); 
    frame.setTitle("Open image with zoom"); 
    JPanel p = new JPanel(new BorderLayout()); 
    p.add(new JLabel("click on button to display image"), BorderLayout.CENTER); 
    JButton button = new JButton("Display!"); 
    frame.setContentPane(p); 
    button.addActionListener(new ActionListener() { 

    public void actionPerformed(ActionEvent e) { 
     Thread t = new Thread() { 

     @Override 
     public void run() { 
     displayImaggeWithProgressiveZoom(imagePath); 
     } 

     }; 
     t.start(); 

    } 

    }); 
    p.add(button, BorderLayout.SOUTH); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setSize(300, 100); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 
    } 
    }); 
} 

protected void displayImaggeWithProgressiveZoom(String imagePath) { 
    try { 
    final BufferedImage image = ImageIO.read(new File(imagePath)); 

    for (int i = 0; i < NB_STEPS; i++) { 
    displayDialog(i, NB_STEPS, image); 

    Thread.sleep(OPENING_TOTAL_DURATION/NB_STEPS); 
    } 

    } catch (Exception e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 

} 

private void displayDialog(final int i, final int nbSteps, final BufferedImage image) { 

    try { 
    SwingUtilities.invokeAndWait(new Runnable() { 
    public void run() { 
    if (dialog == null) { 
     dialog = new JDialog(frame); 
     dialog.setUndecorated(true); 
     dialog.setModal(false); 
     panelZooming = new JPanelZooming(image); 
     dialog.setContentPane(panelZooming); 
     dialog.setSize(0, 0); 
     dialog.setLocationRelativeTo(frame); 
     dialog.setVisible(true); 

    } 
    int w = (i + 1) * image.getWidth()/nbSteps; 
    int h = (i + 1) * image.getHeight()/nbSteps; 

    panelZooming.setScale((double) (i + 1)/nbSteps); 
    dialog.setSize(w, h); 
    dialog.setLocationRelativeTo(null); 
    } 
    }); 
    } catch (InterruptedException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } catch (InvocationTargetException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 

} 

@SuppressWarnings("serial") 
public static class JPanelZooming extends JPanel { 

    private BufferedImage image; 

    private double scale = 1.0d; 

    public JPanelZooming(BufferedImage image) { 
    this.image = image; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2 = (Graphics2D) g; 
    AffineTransform at = g2.getTransform(); 
    AffineTransform oldTransform = (AffineTransform) at.clone(); 
    at.scale(scale, scale); 
    g2.setTransform(at); 
    g2.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null); 
    g2.setTransform(oldTransform); 

    } 

    public void setScale(double scale) { 
    this.scale = scale; 
    } 

} 
} 
+0

Merci pour le code Laurent. L'animation de la boîte de dialogue est assez agitée et disparaît et réapparaît entre les animations (sous OS X). J'ai essayé d'utiliser le framework d'animation, et c'est un peu mieux, mais toujours saccadé. Peut-être que les résultats seraient mieux en utilisant la vitre et un composant au lieu d'un dialogue? –

+0

Donc, pour clarifier, comment puis-je dessiner un composant personnalisé sur la fenêtre complète? Ai-je besoin d'un glassPane transparent sur le JRootPane? Cela ne semble pas remplir toute la fenêtre, seulement le cadre supérieur. –

+0

Ou devrais-je utiliser un JDialog transparent non décoré qui occupe toute la fenêtre? J'ai déjà vu cette technique utilisée auparavant, et cela semble être un hack. Parce que le dialogue ne peut pas être complètement transparent, il semble. –

0

Vous pouvez créer un contrôle personnalisé qui affiche l'image à l'échelle souhaitée.

1) Créer un BufferedImage à partir du fichier d'image que vous désirez à l'aide ImageIO.read(file) (vous pouvez également créer à partir d'un InputStream)

2) Étendre la JComponent ou classe Canvas et surcharger la fonction de peinture pour dessiner l'image animée en utilisant Graphics.DrawImage() et définissez la largeur et la hauteur en fonction de la durée d'ouverture de la fenêtre. Définissez une minuterie ou utilisez un autre thread pour que le composant se redessine à plusieurs reprises, quelle que soit la durée de lecture de l'animation.

Je n'ai pas beaucoup fait avec les boîtes de dialogue modales personnalisées (je les trouve surtout agaçantes), mais vous pouvez utiliser un JDialog et votre composant.

+1

La peinture personnalisée est faite en substituant la méthode paintComponent() PAS la méthode paint(). – camickr

+0

Euh ... J'ai toujours utilisé de la peinture, et ça marche bien. Il y a aussi update(), ou vous pouvez simplement appeler getGraphics() et dessiner sur un composant sans même le surcharger. - Il y a beaucoup de façons de tirer sur les composants. Cela ne fait pas tellement de différence. - Si vous lisez la documentation de JComponent.paint(), elle appelle en fait paintComponent(), donc à moins d'avoir des éléments enfants, il n'y a pas de raison de surcharger paintComponent(), plutôt que paint() –

+0

Paint fait beaucoup plus que simplement appelez paintComponent, notamment en définissant des régions de plan, en appliquant un gestionnaire de repaint (si le composant en utilise un) et en peignant également la bordure. – Ash

Questions connexes