使用Swing的JList組件實現可滑動的圖片列表、好友列表

先放效果圖吧,代碼是從程序裏抽出來的,沒有特意的做效果,挺醜的湊合着看吧。前面是思路,不想看思路的,可以直接跳到後面看源碼(有3個類哦)。

 

一、實現JList每一項以圖片的形式展示並附帶滾輪思路:

1.需要【JScrollPane】對象,將JList放置在JScrollPane上,而不是普通的JPane中。

    JScrollPane scrollPane = new JScrollPane(list);
    panel_1.add(scrollPane, BorderLayout.CENTER);

2.需要【JList】對象,JList對象中設置模型

    JList<File> list = new JList<File>();

3.需要【DefaultListCellRenderer】接口

(1)JList並不會顯示圖片,那麼我們就重寫JList的渲染器ListCellRenderer。可是ListCellRenderer是一個接口,在這裏我們選擇自定義一個DefaultListCellRenderer類,從API中,我們看到DefaultListCellRenderer繼承了JLabel,這意味着我們可以使用這個類的對象,在繪製的時候直接設置JLabel標籤的圖標。而不用再去創建很多JLabel對象。

    public class ImageCellRender extends DefaultListCellRenderer {
        private static final long serialVersionUID = 1L;
    }

(2)真正控制如何繪製JList的是getListCellRendererComponent(參數列表)方法,所以我們在自定義類ImageCellRender 中需要重寫getListCellRendererComponent(參數列表)方法,在重寫裏面的具體代碼之前,我們先分析一下這個方法的參數列表:

    JList<? extends Object> list:正在繪製的JList 
    Object value:由list.getModel().getElementAt(index)返回的值 
    int index:單元格索引 
    boolean isSelected:如果選擇了指定的單元格,則爲true 
    cellHsaFocus:如果指定的單元格擁有焦點,則爲true
  public class ImageCellRender extends DefaultListCellRenderer {
        private static final long serialVersionUID = 1L;
        public Component getListCellRendererComponent(JList<? extends Object> list,
		    	Object value, int index, boolean isSelected, boolean cellHasFocus){
        }
    }   

(3)分析:在這個方法中我們需要做什麼?

    要setIcon(圖標);我們需要一個ImageIcon對象
    setIcon(ImageIcon imageIcon);

    要ImageIcon對象,我們需要圖片路徑
    ImageIcon icon = new ImageIcon(String imagePath);

    要圖片的路徑,我們可以通過getListCellRendererComponent()方法傳入圖片文件
    String imagePath = xxxx.....

(4)從上面的分析中,我們知道我們需要一個【File】類型的對象,這個對象的路徑是文件夾中的某一個圖片。所以在這個方法中我們需要傳入的Value值爲File類型的對象。而這個File對象全部存放於JList中,所以我們可以給JList定義一個泛型JList<File>。 解釋前面第2.點,爲什麼是JList需要加泛型<File>

4.需要【ListMode】對象

(1)重寫好渲染器ImageCellRender之後,我們將開始往JList中存放元素。如果使用list.add()方法去添加元素,不利於我們對JList進行操作,JList爲我們提供了一個list.setModel(ListModel listModel)方法。下面我們來看一下ListModel這個類。

(2)打開API我們會發現ListModel是一個接口,從名字來看實現子類中和ListModel相關的類有:AbstractListModel和DefaultListModel。點開DefaultListModel類後發現,DefaultListModel繼承了AbstractListModel,而且具有很多對元素操作的方法。所以我們新建一個類,繼承DefaultListModel,並對一些方法進行重寫

    public class ImageListModel extends DefaultListModel<File> {
        private static final long serialVersionUID = 1L;
        private List<File> imageFile = new ArrayList<File>();
    	public void addElement(File file){
    		this.imageFile.add(file);
    	}
    	public int getSize(){
	    	return imageFile.size();
	    }
	    public File getElementAt(int index){
    		return imageFile.get(index);
    	}
    }

(3)創建一個imageFile集合對象,由於model中存放的都是File類型的對象,所以將List集合定義泛型爲<File>,addElement(File file),每addElement元素就存進List集合中。getSize()返回List.size(),getElementAt(int index),返回集合中對應下標的元素。

5.需要【File】對象​​

(1)所有準備工作都做好了,那麼我們現在需要創建File對象了。創建一個文件夾new File("文件路徑"),從這個文件夾下獲得文件夾中的全部文件,存進File[]數組中。使用foreach循環遍歷files數組添加進listModel模型中。

    File[] files = new File("head").listFiles();
    for(File file : files){
        listModel.addElement(file);
    }

(2)注意:我的"head"中 放的全是jpg文件,如果路徑下還有別的格式的文件(.txt .exe等)需要篩選!不然會報錯!

    File[] files = new File("head").listFiles(new FileFilter(){
        public boolean accept(File file){
            return file.getName().endsWith("jpg");
        }
    });

二、代碼

(1)JListDemo extends JFrame

package JListAndImage;

import java.awt.BorderLayout;
import java.io.File;
import java.io.FileFilter;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;

public class JListDemo extends JFrame{
	
	private static final long serialVersionUID = 1L;

	public JListDemo(){
		JList<File> list = new JList<File>();
		ImageListModel listModel = new ImageListModel();		
		/**
		 * 這裏使用了一個匿名內部內,來過濾文件格式
		 * files.list()是獲取該目錄下的所有文件   
		 * files.listFiles()是獲取該目錄下所有文件和目錄的絕對路徑 
		 * 我們在獲取的時候可以傳入一個【FileFilter】過濾器
		 * 用到一個匿名內部類,accept則是過濾方法,file.name得到這個文件的名字.endsWith("jpg")
		 * 在rootpath路徑下篩選出jpg格式的文件存入files集合中
		 * 
		 */
		File[] files = new File("head").listFiles(new FileFilter(){
				public boolean accept(File file){
					return file.getName().endsWith("jpg");
				}
		});
		for(File file : files){
			listModel.addElement(file);
		}
		list.setModel(listModel);
		//設置JList的渲染器爲我們自己構建的渲染器
		list.setCellRenderer(new ImageCellRender());
		//setVisibleRowCount設置顯示的行數,但是如果設置了面板的高度 這個會不起效果
		//list.setVisibleRowCount(4);

		//將JList放在滾動面板上
		JScrollPane scrollPane = new JScrollPane(list);
		getContentPane().add(scrollPane, BorderLayout.CENTER);	
		getContentPane().add(new JLabel("帶圖片的Jlist"), BorderLayout.NORTH);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(900, 350, 50, 300);
		
	}
	public static void main(String[] args) {
		new JListDemo().setVisible(true);
	}
}

(2)ImageCellRender extends DefaultListCellRenderer 

package JListAndImage;

import java.awt.Color;
import java.awt.Component;
import java.awt.Image;
import java.io.File;

import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JList;
import javax.swing.SwingConstants;

/**
 * DefaultListCellRenderer是Swing JList的渲染器
 * ImageCellRender繼承DefaultListCellRender,DefaultListCellRender繼承於JLabel,所以只要將圖片賦給JLabel就可以更改顯示樣式
 * @author Silly
 *
 */
public class ImageCellRender extends DefaultListCellRenderer {
	private static final long serialVersionUID = 1L;
	
	/**
	 * 重寫【ListCellRenderer】的getListCellRendererComponent()方法
	 * JList<? extends Object> list:表示JList中ListModel中存放的對象可以是任何引用類型(從JList的源碼得知這個泛型是控制ListModel中對象類型的)
	 * Object value:由list.getModel().getElementAt(index)返回的值,也就是當前正在繪製的對象
	 * index:當前選擇的單元格下標
	 * isSelected:單元格被選擇的狀態(這個被選擇是發生在選擇單元格改變時,如果選了A再選A返回是false,如果選了A選B再選A才爲true)
	 * cellHasFocus:和isSelected的效果一樣 不過沒有用到這個參數 不知道有什麼作用
	 */
	@Override
	public Component getListCellRendererComponent(JList<? extends Object> list,
			Object value, int index, boolean isSelected, boolean cellHasFocus){
		//instanceof 判斷其左邊對象是否爲其右邊類的實例
		if(value instanceof File){
			File imageFile = (File) value;
			try{
				//拿到當前文件的URI再拿到URL
				ImageIcon icon = new ImageIcon(imageFile.toURI().toURL());
				//設置圖標大小
				icon.setImage(icon.getImage().getScaledInstance(50, 50, Image.SCALE_DEFAULT));
				setIcon(icon);
				//a.這裏可以用html來控制字體的顏色
				String text1 = "<html><body color=\"red\">"+imageFile.getName()+"</body></html>";
				//b.也可以通過設置前景色來改變字體顏色
				setForeground(Color.blue);
				String text2 = imageFile.getName();
				setText(text2);
				//設置背景色
				setBackground(Color.white);
				//設置文本的水平和垂直位置:比如(右上)
				setVerticalTextPosition(SwingConstants.TOP);
				setHorizontalTextPosition(SwingConstants.RIGHT);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		if(isSelected){
			if(index == 0){
				System.out.println("第一個被選擇了,注意鼠標按下算一次,鼠標鬆開算一次,只有選擇發生改變時纔會觸發,重複點擊無效果");
			}
		}
		if(cellHasFocus){
			System.out.println("???");
		}
		return this;
	}
}

(3)ImageListModel extends DefaultListModel

package JListAndImage;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractListModel;

/**
 * 【swing中JList控件使用】
 * 每一項以 圖片+文字(文字在圖片的下面)的形式顯示並且在水平方向排序
 * 
 * 實現這個功能的重點在以下幾個方面:
 * (1)需要改變JList的cellRender來支持對圖片的顯示,默認的cellRender只會顯示文本字符串
 * (2)設置JList的每一項的顯示方向(文字和圖片的排列關係)
 * (3)設置每一項選中後的背景
 * 
 * @author Silly
 */

/**
 * 1.創建一個ImageListModel,繼承【AbstractListModel】,設置爲JList的列表模型
 * @author Silly
 *
 */
public class ImageListModel extends AbstractListModel<File> {
	private static final long serialVersionUID = 1L;
	private List<File> imageFile = new ArrayList<File>();
	
	public void addElement(File file){
		this.imageFile.add(file);
	}
	public int getSize(){
		return imageFile.size();
	}
	public File getElementAt(int index){
		return imageFile.get(index);
	}
}

Over啦~ 初學Swing整理了下思路 希望跟我一樣的初學者能看懂

客官~有緣再見
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章