Comment changer l'horloge d'une horloge analogique en utilisant BufferedImage en Java


J'essaie de modifier un code java qui implémente une horloge analogique à l'aide de BufferedImage. Je veux que le visage de l'horloge soit changé dynamiquement lorsqu'un utilisateur clique sur un bouton qui fait défiler un tableau préchargé avec les emplacements des images. Pour l'instant, mes tentatives ont échoué. J'ai deux classes; La première classe crée et affiche l'analogique, et la deuxième classe tente de changer la face de l'horloge analogique en utilisant un mutateur (setAnalogClockFace()) et un accesseur (getAnalogClockFace()). Ce qui suit est le code de la première classe tel que trouvé sur ici , avec des modifications mineures:

package panels;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.util.*;

public class Clock extends JPanel{
/**
 * 
 */
private static final long serialVersionUID = 1L;
private int hours = 0;
private int minutes = 0;
private int seconds = 0;
private int millis = 0;
private static final int spacing = 10;
private static final float threePi = (float)(3.0 * Math.PI);
private static final float radPerSecMin = (float)(Math.PI/30.0);
private int size; //height and width of clockface
private int centerX;//X coord of middle of clock
private int centerY;//Y coord of middle of clock
private BufferedImage clockImage;
private BufferedImage imageToUse;
private javax.swing.Timer t;

public Clock(){
    this.setPreferredSize(new Dimension(203,203));
    this.setBackground(getBackground());
    this.setForeground(Color.darkGray);

    t = new javax.swing.Timer(1000, new ActionListener(){
        public void actionPerformed(ActionEvent ae){
            update();
        }
    });
}

public void update(){
    this.repaint();
}

public void start(){
    t.start();
}

public void stop(){
    t.stop();
}

public void paintComponent(Graphics g){
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                                RenderingHints.VALUE_ANTIALIAS_ON);

    int w = getWidth();
    int h = getHeight();
    size = ((w < h) ? w : h) - 2 * spacing;

    centerX = size/2 + spacing;
    centerY = size/2 + spacing;

    setClockFace(new AnalogClockTimer().getAnalogClockFace());
    clockImage = getClockFace();

    if (clockImage == null | clockImage.getWidth() != w | clockImage.getHeight() != h){
        clockImage = (BufferedImage)(this.createImage(w,h));
        Graphics2D gc = clockImage.createGraphics();
        gc.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                                RenderingHints.VALUE_ANTIALIAS_ON);

        drawClockFace(gc);
    }


    Calendar now = Calendar.getInstance();
    hours = now.get(Calendar.HOUR);
    minutes = now.get(Calendar.MINUTE);
    seconds = now.get(Calendar.SECOND);
    millis = now.get(Calendar.MILLISECOND);

    g2d.drawImage(clockImage, null, 0, 0);
    drawClockHands(g);
}

private void drawClockHands(Graphics g){
    int secondRadius = size/2;
    int minuteRadius = secondRadius * 3/4;
    int hourRadius = secondRadius/2;

    float fseconds = seconds + (float)millis/1000;
    float secondAngle = threePi - (radPerSecMin * fseconds);

    drawRadius(g, centerX, centerY, secondAngle, 0, secondRadius);

    float fminutes = (float)(minutes + fseconds/60.0);
    float minuteAngle = threePi - (radPerSecMin * fminutes);

    drawRadius(g, centerX, centerY, minuteAngle, 0 , minuteRadius);

    float fhours = (float)(hours + fminutes/60.0);
    float hourAngle = threePi - (5 * radPerSecMin * fhours);

    drawRadius(g, centerX, centerY, hourAngle, 0 ,hourRadius);
}

private void drawClockFace(Graphics g){
    //g.setColor(Color.lightGray);
    g.fillOval(spacing, spacing, size, size);
    //g.setColor(new Color(168,168,168));
    g.drawOval(spacing, spacing, size, size);

    for(int sec = 0; sec < 60; sec++){
        int tickStart;

        if(sec%5 == 0){
            tickStart = size/2-10;
        }else{
            tickStart = size/2-5;
        }

        drawRadius(g, centerX, centerY, radPerSecMin * sec, tickStart, size/2);
    }
}

private void drawRadius(Graphics g, int x, int y, double angle,
        int minRadius, int maxRadius){
    float sine = (float)Math.sin(angle);
    float cosine = (float)Math.cos(angle);

    int dxmin = (int)(minRadius * sine);
    int dymin = (int)(minRadius * cosine);

    int dxmax = (int)(maxRadius * sine);
    int dymax = (int)(maxRadius * cosine);

    g.drawLine(x+dxmin, y+dymin, x+dxmax,y+dymax);
}

public void setClockFace(BufferedImage img){
    if(img != null){
        imageToUse = img;
    }else{
        try{
            imageToUse =  
ImageIO.read(getClass().getClassLoader().getResource("http://imgur.com/T8x0I29"));
        }catch(IOException io){
            io.printStackTrace();
        }
    }

}

public BufferedImage getClockFace(){
    return imageToUse;
}

}

La deuxième classe qui tente de régler le cadran de l'horloge est:

package panels;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import panels.Clock;


public class AnalogClockTimer extends javax.swing.JPanel implements ActionListener,  
MouseListener {
private Clock clock;
/**
 * 
 */
private static final long serialVersionUID = 1L;
private JButton prevBtn;
private JTextField clockFaceCount;
private JButton nextBtn;
private JPanel buttonedPanel,leftPanel,rightPanel;
private BufferedImage image;

String[] clockFace;
int arrayPointer = 1;


/**
* Auto-generated main method to display this 
* JPanel inside a new JFrame.
*/
public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.getContentPane().add(new AnalogClockTimer());
    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
}

public AnalogClockTimer() {
    super();
    initGUI();
}

private void initGUI() {
    try {
        BorderLayout thisLayout = new BorderLayout();
        this.setLayout(thisLayout);
        this.setPreferredSize(new java.awt.Dimension(283, 233));
        this.setBackground(getBackground());

        {
            clock = new Clock();
            add(clock,BorderLayout.CENTER);
            clock.start();
            clock.setSize(203, 203);
        }
        {
            buttonedPanel = new JPanel();
            FlowLayout buttonedPanelLayout = new FlowLayout();
            buttonedPanel.setLayout(buttonedPanelLayout);
            this.add(buttonedPanel, BorderLayout.SOUTH);
            buttonedPanel.setPreferredSize(new java.awt.Dimension(283, 30));
            {
                prevBtn = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_left_rest.png")));
                prevBtn.setPreferredSize(new java.awt.Dimension(20, 19));
                prevBtn.setBackground(getBackground());
                prevBtn.setBorderPainted(false);
                prevBtn.setEnabled(false);
                prevBtn.addMouseListener(this);
                prevBtn.addActionListener(this);
                buttonedPanel.add(prevBtn);
            }
            {
                nextBtn = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_right_rest.png")));
                nextBtn.setPreferredSize(new java.awt.Dimension(20, 19));
                nextBtn.setBackground(getBackground());
                nextBtn.setBorderPainted(false);
                nextBtn.addMouseListener(this);
                nextBtn.addActionListener(this);
            }
            {
                clockFaceCount = new JTextField();
                clockFaceCount.setPreferredSize(new java.awt.Dimension(50, 19));
                clockFaceCount.setBackground(getBackground());
                clockFaceCount.setBorder(null);
                clockFaceCount.setHorizontalAlignment(SwingConstants.CENTER);
                clockFaceCount.setEditable(false);
                buttonedPanel.add(clockFaceCount);

                buttonedPanel.add(nextBtn);
            }
            {
                clockFace = new String[]{"http://imgur.com/079QSdJ","http://imgur.com/vQ7tZjI",
                        "http://imgur.com/T8x0I29"};

                for(int i = 1; i <= clockFace.length; i++){

                    if(i == 1){
                        nextBtn.setEnabled(true);
                        prevBtn.setEnabled(false);
                    }
                    clockFaceCount.setText(arrayPointer+" of "+clockFace.length);
                }
            }
            {
                leftPanel = new JPanel();
                leftPanel.setPreferredSize(new Dimension(40, getHeight()));
                add(leftPanel,BorderLayout.WEST);
            }
            {
                rightPanel = new JPanel();
                rightPanel.setPreferredSize(new Dimension(40,getHeight()));
                add(rightPanel,BorderLayout.EAST);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void mouseClicked(MouseEvent me) {
    if(me.getSource() == prevBtn)
        prevBtn.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_left_pressed.png")));
    else
        nextBtn.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_right_pressed.png")));
}

@Override
public void mouseEntered(MouseEvent me) {
    if(me.getSource()==prevBtn)
        prevBtn.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_left_hover.png")));
    else
        nextBtn.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_right_hover.png")));
}

@Override
public void mouseExited(MouseEvent me) {
    if(me.getSource() == prevBtn)
        prevBtn.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_left_rest.png")));
    else
        nextBtn.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_right_rest.png")));

}

@Override
public void mousePressed(MouseEvent me) {
    if(me.getSource() == prevBtn){
        prevBtn.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_left_pressed.png")));
    }else{
        nextBtn.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_right_pressed.png")));
    }
}

@Override
public void mouseReleased(MouseEvent me) {
    if(me.getSource() == prevBtn)
        prevBtn.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_left_hover.png")));
    else
        nextBtn.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/settings_right_hover.png")));

}

@Override
public void actionPerformed(ActionEvent ae) {
    if(ae.getSource() == nextBtn){
        {
            if(arrayPointer < clockFace.length){
                ++arrayPointer;
                prevBtn.setEnabled(true);

                if(arrayPointer == clockFace.length)
                    nextBtn.setEnabled(false);
            }

            clockFaceCount.setText(arrayPointer + " of " + clockFace.length);
            setAnalogClockFace(arrayPointer);
        }
    }else if(ae.getSource() == prevBtn){
        {
            if(arrayPointer > 1){
                --arrayPointer;
                nextBtn.setEnabled(true);

                if(arrayPointer == 1){
                    clockFaceCount.setText(arrayPointer+" of "+clockFace.length);
                    prevBtn.setEnabled(false);
                }
            }
            clockFaceCount.setText(arrayPointer + " of "+clockFace.length);
            setAnalogClockFace(arrayPointer);
        }
    }

}

private void setAnalogClockFace(int pointerPosition) {
    try{
        image = ImageIO.read(getClass().getClassLoader().getResource(clockFace[pointerPosition]));
    }catch(IOException io){
        io.printStackTrace();
    }
}

public BufferedImage getAnalogClockFace(){
    return image;
}

}

Je travaille là-dessus depuis des jours, quelqu'un peut-il m'aider à comprendre ce qui ne va pas bien? Toute aide serait grandement appréciée.

Voici un MCVE utilisant un JLabel pour obtenir le même résultat:

package panels;

import java.awt.Dimension;

import javax.swing.ImageIcon;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;

import java.awt.event.*;
import java.awt.BorderLayout;

@SuppressWarnings({"serial"})
public class ClockPanel extends javax.swing.JPanel implements ActionListener {
private JLabel clockImageLabel;
private JPanel buttonsPanel;
private JButton next,prev;
private JTextField displayCount;

String[] imageFaces;
int pointer = 1;
/**
* Auto-generated main method to display this 
* JPanel inside a new JFrame.
*/
public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.getContentPane().add(new ClockPanel());
    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
}

public ClockPanel() {
    super();
    initGUI();
}

private void initGUI() {
    try {
        setPreferredSize(new Dimension(203, 237));
        BorderLayout panelLayout = new BorderLayout();
        setLayout(panelLayout);

        {
            clockImageLabel = new JLabel();
            clockImageLabel.setPreferredSize(new Dimension(203,203));
            clockImageLabel.setHorizontalAlignment(SwingConstants.CENTER);
            clockImageLabel.setVerticalAlignment(SwingConstants.CENTER);
            add(clockImageLabel,BorderLayout.NORTH);
        }
        {
            buttonsPanel = new JPanel();

            {
                next = new JButton(">");
                next.addActionListener(this);
            }
            {
                prev = new JButton("<");
                prev.addActionListener(this);

                displayCount = new JTextField();
                displayCount.setBorder(null);
                displayCount.setEditable(false);
                displayCount.setBackground(getBackground());
                displayCount.setHorizontalAlignment(SwingConstants.CENTER);
                buttonsPanel.add(prev);
                buttonsPanel.add(displayCount);
                displayCount.setPreferredSize(new java.awt.Dimension(45, 23));
                buttonsPanel.add(next);

                add(buttonsPanel,BorderLayout.SOUTH);
            }
            {
                imageFaces = new String[]{"http://imgur.com/T8x0I29",
                        "http://imgur.com/079QSdJ","http://imgur.com/vQ7tZjI"
                };

                for(int i = 1; i < imageFaces.length; i++){
                    if(i == 1){
                        next.setEnabled(true);
                        prev.setEnabled(false);
                    }
                    displayCount.setText(pointer+" of "+imageFaces.length);
                    setLabelImage(pointer);
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void setLabelImage(int pointerPosition){
    clockImageLabel.setIcon(new ImageIcon(getClass().getClassLoader().getResource(imageFaces[pointerPosition])));
    this.repaint();
}

@Override
public void actionPerformed(ActionEvent ae) {
    if(ae.getSource() == next){
            if(pointer < imageFaces.length){
                ++pointer;
                prev.setEnabled(true);

                if(pointer == imageFaces.length)next.setEnabled(false);

                displayCount.setText(pointer+" of "+imageFaces.length);
                setLabelImage(pointer);
            }
    }else if(ae.getSource() == prev){
        if(pointer > 1){
            --pointer;
            next.setEnabled(true);

            if(pointer == 1)prev.setEnabled(false);

            displayCount.setText(pointer+" of "+imageFaces.length);
            setLabelImage(pointer);
        }
    }
}

}

Voici 1/2 images pour le code: HandlessAnalogClock 1 HandlessAnalogClock 2 HandlessAnalogClock 3

Author: aknessy, 2014-11-03

2 answers

Ce MCVE retournera avec succès entre deux des trois images, mais a toujours des problèmes avec ArrayIndexOutOfBoundsException.

Cette dernière partie est 'Piles non incluses' (à gauche comme un exercice pour l'utilisateur de corriger).

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.net.URL;

@SuppressWarnings({"serial"})
public class ClockPanel extends JPanel implements ActionListener {

    private JLabel clockImageLabel;
    private JPanel buttonsPanel;
    private JButton next, prev;
    private JTextField displayCount;

    BufferedImage[] images;
    int pointer = 1;

    /**
     * Auto-generated main method to display this JPanel inside a new JFrame.
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.getContentPane().add(new ClockPanel());
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);
    }

    public ClockPanel() {
        super();
        initGUI();
    }

    private void initGUI() {
        try {
            setPreferredSize(new Dimension(203, 237));
            BorderLayout panelLayout = new BorderLayout();
            setLayout(panelLayout);

            clockImageLabel = new JLabel();
            clockImageLabel.setPreferredSize(new Dimension(203, 203));
            clockImageLabel.setHorizontalAlignment(SwingConstants.CENTER);
            clockImageLabel.setVerticalAlignment(SwingConstants.CENTER);
            add(clockImageLabel, BorderLayout.NORTH);

            buttonsPanel = new JPanel();

            next = new JButton(">");
            next.addActionListener(this);

            prev = new JButton("<");
            prev.addActionListener(this);

            displayCount = new JTextField();
            displayCount.setBorder(null);
            displayCount.setEditable(false);
            displayCount.setBackground(getBackground());
            displayCount.setHorizontalAlignment(SwingConstants.CENTER);
            buttonsPanel.add(prev);
            buttonsPanel.add(displayCount);
            displayCount.setPreferredSize(new java.awt.Dimension(45, 23));
            buttonsPanel.add(next);

            add(buttonsPanel, BorderLayout.SOUTH);

            String[] imageFaces = new String[]{
                "http://i.imgur.com/T8x0I29.png",
                "http://i.imgur.com/079QSdJ.png",
                "http://i.imgur.com/vQ7tZjI.png"
            };
            images = new BufferedImage[imageFaces.length];
            for (int ii=0; ii<imageFaces.length; ii++) {
                System.out.println("loading image: " + ii);
                images[ii] = ImageIO.read(new URL(imageFaces[ii]));
                System.out.println("loaded image: " + images[ii]);
            }
            setLabelImage(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setLabelImage(int pointerPosition) {
        System.out.println("setLabelImage: " + pointerPosition);
        clockImageLabel.setIcon(new ImageIcon(images[pointerPosition]));
        this.repaint();
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        if (ae.getSource() == next) {
            if (pointer < images.length) {
                ++pointer;
                prev.setEnabled(true);

                if (pointer == images.length) {
                    next.setEnabled(false);
                }

                displayCount.setText(pointer + " of " + images.length);
                setLabelImage(pointer);
            }
        } else if (ae.getSource() == prev) {
            if (pointer > 1) {
                --pointer;
                next.setEnabled(true);

                if (pointer == 1) {
                    prev.setEnabled(false);
                }

                displayCount.setText(pointer + " of " + images.length);
                setLabelImage(pointer);
            }
        }
    }
}
 3
Author: Andrew Thompson, 2014-11-07 01:32:50

Expansion sur @Andrew's exemple, envisager d'organiser pour l'index de l'image courante à wrap-around, comme indiqué dans l'exemple cité ici.

private int pointer = 0;
...
private void initGUI() {
    ...
    setLabelImage(pointer);
    ...
}

private void setLabelImage(int pointerPosition) {
    System.out.println("setLabelImage: " + pointerPosition);
    clockImageLabel.setIcon(new ImageIcon(images[pointerPosition]));
    displayCount.setText((pointerPosition + 1) + " of " + images.length);
    this.repaint();
}

@Override
public void actionPerformed(ActionEvent ae) {
    if (ae.getSource() == next) {
        pointer++;
        if (pointer >= images.length) {
            pointer = 0;
        }
    } else if (ae.getSource() == prev) {
        pointer--;
        if (pointer < 0) {
            pointer = images.length - 1;
        }
    }
    setLabelImage(pointer);
}

Comme exercice, essayez de prendre en compte l'instanciation répétée de ImageIcon dans setLabelImage() en créant un List<ImageIcon> dans initGUI().

 3
Author: trashgod, 2017-05-23 11:49:39