Как да завъртя икона в Java с JLabel?

+4 гласа
153 прегледа
попитан 2016 април 25 от Nikola.Nikolov. (3,100 точки)
Здравейте,имам проблем със завъртането на изображение в JLabel. Взех този код от StackOverflow,

и се опитвам да го променя малко като вместо да завъртам изображението в Tab, да го завъртя в JLabel.

public class ProgressTabbedPane {  

public static void main(String[] args) {

    EventQueue.invokeLater(new Runnable() {

        @Override

        public void run() {

            JFrame frame = new JFrame("RotatingIcon");  

            JTabbedPane tabbedPane = new JTabbedPane();

            JLabel lable = new JLabel();

            tabbedPane.addTab("Searching", new RotatingIcon(new ImageIcon("disk.png"), tabbedPane, 10), new JLabel( /*new ImageIcon( "resources/images/rotatingIcon.gif" )*/));                

            frame.getContentPane().add(tabbedPane);                 

            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            //frame.setUndecorated(true);

            frame.pack();

            frame.setLocationRelativeTo(null);

            frame.setVisible(true);

        }

    });

}

private static class RotatingIcon implements Icon {

    private final Icon delegateIcon;

    private double angleInDegrees = 90;

    final private Timer rotatingTimer;

    private RotatingIcon(Icon icon, final JComponent component, int vrotating) {

        delegateIcon = icon;

        rotatingTimer = new Timer(vrotating, new ActionListener() {

            @Override

            public void actionPerformed(ActionEvent e) {

                angleInDegrees = angleInDegrees + 1;

                if (angleInDegrees == 360) {

                    angleInDegrees = 0;

                }

                component.repaint();

            }

        });

        rotatingTimer.setRepeats(false);

        rotatingTimer.start();

    }

    @Override

    public void paintIcon(Component c, Graphics g, int x, int y) {

        rotatingTimer.stop();

        Graphics2D g2 = (Graphics2D) g.create();

        int cWidth = delegateIcon.getIconWidth() / 2;

        int cHeight = delegateIcon.getIconHeight() / 2;

        Rectangle r = new Rectangle(x, y, delegateIcon.getIconWidth(), delegateIcon.getIconHeight());

        g2.setClip(r);

        AffineTransform original = g2.getTransform();

        AffineTransform at = new AffineTransform();

        at.concatenate(original);

        at.rotate(Math.toRadians(angleInDegrees), x + cWidth, y + cHeight);

        g2.setTransform(at);

        delegateIcon.paintIcon(c, g2, x, y);

        g2.setTransform(original);

        rotatingTimer.start();

    }

    @Override

    public int getIconWidth() {

        return delegateIcon.getIconWidth();

    }

    @Override

    public int getIconHeight() {

        return delegateIcon.getIconHeight();

    }

}

  

}

Това работи, изображението се върти. Но като го променя в това :

public class ProgressTabbedPane {  

public static void main(String[] args) {

    EventQueue.invokeLater(new Runnable() {

        @Override

        public void run() {

            JFrame frame = new JFrame("RotatingIcon");  

            JTabbedPane tabbedPane = new JTabbedPane();

            JLabel lable = new JLabel();

            lable.setIcon(new RotatingIcon(new ImageIcon(disk.png"), tabbedPane, 10));                 

            frame.getContentPane().add(lable);

            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            //frame.setUndecorated(true);

            frame.pack();

            frame.setLocationRelativeTo(null);

            frame.setVisible(true);

        }

    });

}

private static class RotatingIcon implements Icon {

    private final Icon delegateIcon;

    private double angleInDegrees = 90;

    final private Timer rotatingTimer;

    private RotatingIcon(Icon icon, final JComponent component, int vrotating) {

        delegateIcon = icon;

        rotatingTimer = new Timer(vrotating, new ActionListener() {

            @Override

            public void actionPerformed(ActionEvent e) {

                angleInDegrees = angleInDegrees + 1;

                if (angleInDegrees == 360) {

                    angleInDegrees = 0;

                }

                component.repaint();

            }

        });

        rotatingTimer.setRepeats(false);

        rotatingTimer.start();

    }

    @Override

    public void paintIcon(Component c, Graphics g, int x, int y) {

        rotatingTimer.stop();

        Graphics2D g2 = (Graphics2D) g.create();

        int cWidth = delegateIcon.getIconWidth() / 2;

        int cHeight = delegateIcon.getIconHeight() / 2;

        Rectangle r = new Rectangle(x, y, delegateIcon.getIconWidth(), delegateIcon.getIconHeight());

        g2.setClip(r);

        AffineTransform original = g2.getTransform();

        AffineTransform at = new AffineTransform();

        at.concatenate(original);

        at.rotate(Math.toRadians(angleInDegrees), x + cWidth, y + cHeight);

        g2.setTransform(at);

        delegateIcon.paintIcon(c, g2, x, y);

        g2.setTransform(original);

        rotatingTimer.start();

    }

    @Override

    public int getIconWidth() {

        return delegateIcon.getIconWidth();

    }

    @Override

    public int getIconHeight() {

        return delegateIcon.getIconHeight();

    }

}

спира да работи. Извинявам се предварително ако е тъп въпросът, но не намирам отговор.

Благодаря предварително

1 отговор

0 гласа
отговорени 2016 април 26 от Daniel Ivanov (11,160 точки)

Метод за рисуване по принцип трябва да се използва само за рисуване. Не трябва да спира или да пуска таймер.Tрябва да забравиш за вкарването на таймер в метода за рисуване и след това да сложиш таймер, който да повтаря, така че продължителните event-и да се генерират.

За алтернативен подход – виж анимираната икона:

https://tips4java.wordpress.com/2009/06/21/animated-icon/

Анимираната икона Animated Icon ще съдържа списък с икони, последователни базирани на таймер. Когато таймера удари => следващата икона ще се изобрази. Можеш да конфигурираш анимацията да бъде или продължителна или да избереш колко цикъла да изобразява всяка икона.

Забележка: този начин би трябвало да е по-ефикасно, понеже просто я рисува наново,а не целия компонент.

Ако не ти харесва идеята да правиш всички тези икони за анимацията, можеш да ползваш Завъртяната икона :

https://tips4java.wordpress.com/2009/04/06/rotated-icon/

С тоя клас RotatedIcon  можеш да си настроиш градусите на ротация на иконата. След това таймерът се отделя изцяло от класа. След това като мине таймера можеш да дигнеш градусите на ротация.

Ето ти пример с AnimatedIcon:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SSCCE extends JPanel
{
    public SSCCE()
    {
        setLayout( new BorderLayout() );
        JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.add("1", new JPanel());
        tabbedPane.add("2", new JPanel());
        add(tabbedPane);
        AnimatedIcon icon = new AnimatedIcon(tabbedPane, 250, 3);
        ImageIcon duke = new ImageIcon( "copy16.gif" );
        icon.addIcon( duke );
        for (int angle = 30; angle < 360; angle += 30)
        {
            icon.addIcon( new RotatedIcon(duke, angle) );
        }
        tabbedPane.setIconAt(0, icon);
        icon.start();
    }
коментиран 2016 април 26 от Daniel Ivanov (11,160 точки)
private static void createAndShowGUI()

    {

        JFrame frame = new JFrame("SSCCE");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(new SSCCE());

        frame.setLocationByPlatform( true );

        frame.pack();

        frame.setVisible( true );

    }


    public static void main(String[] args)

    {

        EventQueue.invokeLater( () -> createAndShowGUI() );

/*

        EventQueue.invokeLater(new Runnable()

        {

            public void run()

            {

                createAndShowGUI();

            }

        });

*/

    }

}
...