ok,我承認動感這個詞用的有點過,還是先看效果
解釋一下,圖片中是沒有什麼動感的,其實效果是這樣
當選中item時,藍色的選中背景會從白色漸層到藍色,給人動感~
雖然這種動感沒有特別實際的用處,不過實現原理還是有點意思,來看看
1、先通過lookandfeel擷取選中和未選中的背景顏色,在轉換成rgb浮點數組float[3]
UIDefaults uid = UIManager.getLookAndFeel().getDefaults(); Color listForeground = uid.getColor ("List.foreground"); float[] foregroundComps = listForeground.getRGBColorComponents(null);
2、在valueChanged方法中,啟動thread做背景漸層效果;通過計時,每50ms進行一次repaint,總共執行500ms
public void run() { startTime = System.currentTimeMillis(); stopTime = startTime + ANIMATION_DURATION; while (System.currentTimeMillis() < stopTime) { colorizeSelections(); repaint(); //每間隔ANIMATION_REFRESH時間就repaint一次 try { Thread.sleep (ANIMATION_REFRESH); } catch (InterruptedException ie) {} } // one more, at 100% selected color colorizeSelections(); repaint(); }
3、repaint之前調用colorizeSelections方法設定背景前景顏色,而colorizeSelections方法是根據時間來計算背景顯示的百分比
這個計算其實就是把背景的rgb值取百分比
public void colorizeSelections() { // calculate % completion relative to start/stop times float elapsed = (float) (System.currentTimeMillis() - startTime); float completeness = Math.min ((elapsed/ANIMATION_DURATION), 1.0f); // System.out.println ("completeness = " + completeness); // calculate scaled color float colorizedForeComps[] = new float[3]; float colorizedBackComps[] = new float[3]; for (int i=0; i<3; i++) { colorizedForeComps[i] = foregroundComps[i] + (completeness * (foregroundSelectionComps[i] - foregroundComps[i])); colorizedBackComps[i] = backgroundComps[i] + (completeness * (backgroundSelectionComps[i] - backgroundComps[i])); }
這樣repaint之前就設定好了背景色,不斷repaint的話就產生動感漸層的效果了
上代碼:
import java.awt.*;import javax.swing.*;import javax.swing.event.*;import java.util.*;public class AnimatedJList extends JList implements ListSelectionListener { static java.util.Random rand = new java.util.Random(); static Color listForeground, listBackground, listSelectionForeground, listSelectionBackground; static float[] foregroundComps, backgroundComps, foregroundSelectionComps, backgroundSelectionComps; static { UIDefaults uid = UIManager.getLookAndFeel().getDefaults(); listForeground = uid.getColor ("List.foreground"); listBackground = uid.getColor ("List.background"); listSelectionForeground = uid.getColor ("List.selectionForeground"); listSelectionBackground = uid.getColor ("List.selectionBackground"); foregroundComps = listForeground.getRGBColorComponents(null); foregroundSelectionComps = listSelectionForeground.getRGBColorComponents(null); backgroundComps = listBackground.getRGBColorComponents(null); backgroundSelectionComps = listSelectionBackground.getRGBColorComponents(null); } public Color colorizedSelectionForeground, colorizedSelectionBackground; public static final int ANIMATION_DURATION = 500; public static final int ANIMATION_REFRESH = 50; public AnimatedJList() { super(); addListSelectionListener (this); setCellRenderer (new AnimatedCellRenderer()); } public void valueChanged (ListSelectionEvent lse) { if (! lse.getValueIsAdjusting()) { HashSet selections = new HashSet(); // System.out.println ("got last lse"); for (int i=0; i < getModel().getSize(); i++) { if (getSelectionModel().isSelectedIndex(i)) selections.add (new Integer(i)); } CellAnimator animator = new CellAnimator (selections.toArray()); animator.start(); } } public static void main (String[] args) { JList list = new AnimatedJList (); DefaultListModel defModel = new DefaultListModel(); list.setModel (defModel); String[] listItems = { "Chris", "Joshua", "Daniel", "Michael", "Don", "Kimi", "Kelly", "Keagan" }; Iterator it = Arrays.asList(listItems).iterator(); while (it.hasNext()) defModel.addElement (it.next()); // show list JScrollPane scroller = new JScrollPane (list, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); JFrame frame = new JFrame ("Checkbox JList"); frame.getContentPane().add (scroller); frame.pack(); frame.setVisible(true); } class CellAnimator extends Thread { Object[] selections; long startTime; long stopTime; public CellAnimator (Object[] s) { selections = s; } public void run() { startTime = System.currentTimeMillis(); stopTime = startTime + ANIMATION_DURATION; while (System.currentTimeMillis() < stopTime) { colorizeSelections(); repaint(); try { Thread.sleep (ANIMATION_REFRESH); } catch (InterruptedException ie) {} } // one more, at 100% selected color colorizeSelections(); repaint(); } public void colorizeSelections() { // calculate % completion relative to start/stop times float elapsed = (float) (System.currentTimeMillis() - startTime); float completeness = Math.min ((elapsed/ANIMATION_DURATION), 1.0f); // System.out.println ("completeness = " + completeness); // calculate scaled color float colorizedForeComps[] = new float[3]; float colorizedBackComps[] = new float[3]; for (int i=0; i<3; i++) { colorizedForeComps[i] = foregroundComps[i] + (completeness * (foregroundSelectionComps[i] - foregroundComps[i])); colorizedBackComps[i] = backgroundComps[i] + (completeness * (backgroundSelectionComps[i] - backgroundComps[i])); } colorizedSelectionForeground = new Color (colorizedForeComps[0], colorizedForeComps[1], colorizedForeComps[2]); colorizedSelectionBackground = new Color (colorizedBackComps[0], colorizedBackComps[1], colorizedBackComps[2]); // System.out.println ("fore = " +colorizedSelectionForeground); // System.out.println ("back = " +colorizedSelectionBackground); } } class AnimatedCellRenderer extends DefaultListCellRenderer { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) { Component returnMe = super.getListCellRendererComponent (list, value, index, isSelected, hasFocus); if (isSelected) { returnMe.setForeground (colorizedSelectionForeground); returnMe.setBackground (colorizedSelectionBackground); /* this might be necessary if you have more elaborate cells if (returnMe instanceof Container) { Component[] children = ((Container)returnMe).getComponents (); System.out.println (children.length + " children"); for (int i=0; (children != null ) && (i<children.length); i++) { children[i].setForeground (colorizedSelectionForeground); children[i].setBackground (colorizedSelectionBackground); } } */ if (returnMe instanceof JComponent) ((JComponent) returnMe).setOpaque(true); } return returnMe; } }}