0.前言
Java那本书基础篇看完了,写一个小东西作为结书练习。在这个案例中,会展示选择文件夹,递归地获得文件夹中图片,使用监听器响应键盘事件,改变图片大小并重新绘制画布。同时会把接口和类设计的一些知识点也涉及。
如果有空的话会把读入文件从而减少加载时间的那部分也写上(就和之前python的一样)。不过博主我啊是真的要阳了,所以估计不行啦。
图片浏览器键盘左键上一张,右键下一张,上键随机一张。


1.获取文件夹和文件夹中图片
Java提供了便利的文件读取类JFileChooser,我们设置它的获取模式为文件夹,再递归地获得文件夹中图片——事实上似乎有这么一个函数已经提供给我们了,但是我的java版本似乎不支持。
import javax.swing.*;
import java.io.File;
import java.util.Vector;
public class MyFileGetter {
public static void getAllFileNames(File file, Vector fileNames) {
//获得所有文件名,是不是和listdir一模一样
File[] files = file.listFiles();
for (File f : files) {
if (f.isDirectory()) {
getAllFileNames(f, fileNames);
}
else {
String path = f.getAbsolutePath();
//是图片的话
if(path.contains("jpg")||path.contains("png"))
fileNames.add(f.getAbsolutePath());
}
}
}
public static File getDirectory(){
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
//设置好打开所在文件夹
fileChooser.setCurrentDirectory(new File("D:/素材/P站图片"));
if(fileChooser.showOpenDialog(null)==JFileChooser.APPROVE_OPTION)
{
File file = fileChooser.getSelectedFile();
return file;
}
else{
System.out.println("No return");
return new File("D:/素材/P站图片/P站图片2021年/P站图片2021九月/P站图片20210906");
//为方便起见不抛出错误,返回一个默认的文件夹
}
}
}
2.显示图片:ImageShower类
我们继承Jpannel类来显示一张图片,核心函数是drawImage。
这里我们思考一下为什么要把被拉伸初始化设置为true,并且之后我们是怎么绕过这一点让图片保持原来的长宽比的:因为我们无法保证用户之后不对边框拉伸,如果不默认为true,就需要处理敞口拉伸的事件,这不是那么容易做到的。而且思考主从关系,是让窗口内的组件适应窗口还是让窗口适应组件,我认为还是组件适应窗口比较好。
至于之后我们更改图片以后,只需要简单的frame.setSize即可。
import javax.swing.*;
import java.awt.*;
public class ImageShower extends JPanel {
private Image image;
private boolean streched = true;
private int xCoordinate;
private int yCoordinate;
public ImageShower(){};
public ImageShower(Image image)
{
this.image=image;
}
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if(image!=null){
if(streched)
g.drawImage(image,xCoordinate,yCoordinate,getWidth(),getHeight(),this);
}
else
g.drawImage(image,xCoordinate,yCoordinate,this);
}
public Image getImage()
{
return image;
}
public void setImage(Image image) {
this.image = image;
repaint();
}
public boolean isStreched() {
return streched;
}
public void setStreched(boolean streched) {
this.streched = streched;
repaint();
}
public int getxCoordinate() {
return xCoordinate;
}
public void setxCoordinate(int x)
{
xCoordinate=x;
repaint();
}
public int getyCoordinate() {
return yCoordinate;
}
public void setyCoordinate(int y)
{
yCoordinate=y;
repaint();
}
}
3.TestImageDemo类:主函数入口
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Random;
import java.util.Vector;
public class TestImageViwer extends JFrame{
private Image image1;//image对象
private ImageIcon imageicon1;
private ImageShower imgShower;//用于显示图片
public int imgWidth;
public int imgHeight;
private double muliple;
private int currentPos = 0;
private Random r = new Random();
private Vector filenames = new Vector(30);
public TestImageViwer(Vector filenames){
this.filenames = filenames;
currentPos = -1;
setNewImage(1);
setLayout(new GridLayout(1,2,5,5));
imgShower = new ImageShower(image1);
add(imgShower);
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
switch (e.getKeyCode()){
//下一张
case KeyEvent.VK_RIGHT:
setNewImage(1);
changeImage();
break;
//上一张
case KeyEvent.VK_LEFT:
setNewImage(-1);
changeImage();
break;
//随机一张
case KeyEvent.VK_UP:
setNewImage(0);
changeImage();
break;
}
}
});
}
private void changeImage(){
//设置新的图片
imgShower.setImage(image1);
//窗口改变大小
setSize(imgWidth,imgHeight);
}
private void setNewImage(int mode)
{
if(mode==1)//下一张
currentPos = (currentPos+1)%filenames.size();
else if(mode==-1)//上一张
currentPos = currentPos-1>=0?currentPos-1:filenames.size()-1;
else if(mode==0)//随机一张
currentPos = r.nextInt(0,filenames.size());
String path = filenames.get(currentPos);
imageicon1 = new ImageIcon(path);
image1 = imageicon1.getImage();
imgWidth = imageicon1.getIconWidth();
imgHeight = imageicon1.getIconHeight();
//为了保证长宽不超过屏幕我们提前设置一个合适的尺寸,使图片只能在此大小
muliple = (double)Math.min(1000.0/imgWidth,800.0/imgHeight);
imgWidth *= muliple;
imgHeight *= muliple;
//设置标题
int tmp = path.lastIndexOf('\\');
setTitle(path.substring(tmp+1));
}
public static void main(String[] args) throws Exception {
File director = MyFileGetter.getDirectory();
Vector filenames = new Vector();
MyFileGetter.getAllFileNames(director,filenames);
TestImageViwer frame = new TestImageViwer(filenames);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(frame.imgWidth, frame.imgHeight);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
4.结语
博主家里人已经阳了,现在博主还在苟延残喘,不知道能撑到什么时候,现在博主每天得负责烧饭,打扫消毒,遛狗等家务事,没多少时间学习,等我熬过这波疫情才能愉快地继续学习。大家一定要保重好身体,做好防护。
悲伤啊悲伤