如何在外观变化时动态更改图标? [英] How to change dynamically the icons when the look and feel change?

查看:133
本文介绍了如何在外观变化时动态更改图标?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发具有两个主题的外观。

I'm developing a look-and-feel with two themes.

问题是:


  • 我希望能够在两者之间动态切换两个主题(这意味着在启动后更改主题)。

  • 但主题有两组不同的图标(实际上是不同颜色的相同图标)。

我不知道如何动态更改整个应用程序中的图标。

I don't know how to change dynamically the icons in the entire application.

一个解决方案将图标和图标ID注册到每个组件上以在两种图标之间切换,但这似乎是一个非常重的解决方案!

One solution would be to register each component with an icon and the icon ID on an icon manager to switch between the two kinds of icons, but it seems a very heavy solution!

推荐答案

可能有很多不同的方法(我不能说哪一个是最好的):

There might be a lot of different approaches (and i cannot say which one is the best):


  1. 基于javax.swing.Icon创建自己的图标类,并根据当前安装的L& F

  2. 在installUI方法中绘制一个实际图标,因为它在组件调用时被调用UI已安装或重新安装d(例如,更改L& F时)

  3. 创建自己的组件或处理图标绘制的UI

  4. 覆盖使用此类图标的组件并替换图标检索方法

  1. Create your own icon class based on javax.swing.Icon and paint there an actual icon based on currently installed L&F
  2. Setup component icons inside the installUI method since it is called when component UI is installed OR reinstalled (for example when L&F is changed)
  3. Create your own components or their UIs that handles icon painting
  4. Override components which uses such icons and replace icon retrieval methods

可能会有更多,但首先想到的是......

There might be more, but those are first that comes to mind...

这是第一个解决方案工作示例:

Here is the 1st solution working example:

import com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel;

import javax.swing.*;
import javax.swing.plaf.metal.MetalLookAndFeel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * @see http://stackoverflow.com/a/12301173/909085
 */

public class LafIcon implements Icon
{
    private Map<String, Icon> lafIcons;

    public LafIcon ()
    {
        super ();
        lafIcons = new HashMap<String, Icon> ();
    }

    public void addIcon ( String laf, Icon icon )
    {
        lafIcons.put ( laf, icon );
    }

    private String getLaf ()
    {
        return UIManager.getLookAndFeel ().getClass ().getCanonicalName ();
    }

    private Icon getCurrentIcon ()
    {
        return lafIcons.get ( getLaf () );
    }

    public void paintIcon ( Component c, Graphics g, int x, int y )
    {
        Icon icon = getCurrentIcon ();
        if ( icon != null )
        {
            icon.paintIcon ( c, g, x, y );
        }
    }

    public int getIconWidth ()
    {
        Icon icon = getCurrentIcon ();
        return icon != null ? icon.getIconWidth () : 0;
    }

    public int getIconHeight ()
    {
        Icon icon = getCurrentIcon ();
        return icon != null ? icon.getIconHeight () : 0;
    }

    public static void main ( String[] args )
    {
        installMetalLookAndFeel ();

        JFrame frame = new JFrame ();
        frame.setLayout ( new FlowLayout ( FlowLayout.CENTER, 5, 5 ) );

        frame.add ( new JButton ( "Test button", createIcon () ) );

        String[] laf = { "Metal Look and Feel", "Nimbus Look and Feel" };
        final JComboBox lafType = new JComboBox ( laf );
        lafType.addActionListener ( new ActionListener ()
        {
            public void actionPerformed ( ActionEvent e )
            {
                if ( lafType.getSelectedIndex () == 0 )
                {
                    installMetalLookAndFeel ();
                }
                else
                {
                    installNimbusLookAndFeel ();
                }
            }
        } );
        frame.add ( lafType );

        frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
        frame.pack ();
        frame.setLocationRelativeTo ( null );
        frame.setVisible ( true );
    }

    private static LafIcon createIcon ()
    {
        LafIcon icon = new LafIcon ();    
        try
        {
            icon.addIcon ( MetalLookAndFeel.class.getCanonicalName (), new ImageIcon (
                    new URL ("http://cdn3.iconfinder.com/data/icons/fatcow/32x32_0020/application_form.png") ) );
            icon.addIcon ( NimbusLookAndFeel.class.getCanonicalName (), new ImageIcon (
                    new URL ("http://cdn3.iconfinder.com/data/icons/fatcow/32x32_0040/application_view_gallery.png") ) );
        }
        catch ( MalformedURLException e )
        {
            e.printStackTrace ();
        }    
        return icon;
    }

    private static void installMetalLookAndFeel ()
    {
        installLookAndFeel ( MetalLookAndFeel.class.getCanonicalName () );
    }

    private static void installNimbusLookAndFeel ()
    {
        installLookAndFeel ( NimbusLookAndFeel.class.getCanonicalName () );
    }

    private static void installLookAndFeel ( String name )
    {
        try
        {
            UIManager.setLookAndFeel ( name );

            Window[] windows = Window.getWindows ();
            if ( windows.length > 0 )
            {
                for ( Window window : windows )
                {
                    SwingUtilities.updateComponentTreeUI ( window );
                    window.pack ();
                }
            }
        }
        catch ( ClassNotFoundException e )
        {
            e.printStackTrace ();
        }
        catch ( InstantiationException e )
        {
            e.printStackTrace ();
        }
        catch ( IllegalAccessException e )
        {
            e.printStackTrace ();
        }
        catch ( UnsupportedLookAndFeelException e )
        {
            e.printStackTrace ();
        }
    }
}

实际上,你可以看到,代码的大部分都是示例。您可以修改图标代码以提供其他图标添加/设置/删除方法,使图标更容易创建。

Actually, as you can see, most part of the code is the example. You can modify the icon code to provide additional icons add/set/remove methods to make the icon much more simple to create.

此外,您无需收听L& F使用这种方式进行更改,因为在组件UI更改时,它将重新绘制并重新验证,以便再次调用图标大小和绘制方法,并为更新的L& F提供新图标。

Also you don't need to listen to L&F changes using this way, since on component UI change it will be repainted and revalidated so the icon size and paint methods will get called again and will provide the new icon for updated L&F.

这篇关于如何在外观变化时动态更改图标?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆