该篇主要运用Java swing的基础知识,展示的应用结果。
用到的内容:
import swingTool.ImageView;
import javax.imageio.ImageIO;(本文主要是读文件)
import javax.swing.*;
import javax.swing.border.Border;(对于边框的复合使用)
import java.awt.*;
import java.awt.event.MouseAdapter;(鼠标适配器,实现了各类鼠标事件,写起来更简洁)
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
具体应用到的知识,大家可以向我询问,我尽力解决。本人还在努力学习中,不足之处,多多谅解。
import swingTool.ImageView;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author stardream Email:stardream0000@163.com
* @Description
* @2020/8/25 22:59
*/
public class Test20 extends JFrame {
JPanel jp1=new JPanel();//上面一排容器
JPanel jp2=new JPanel();//中间大图容器
ImageView panel=new ImageView();//画图本质上还是在panel上
List<ImageButton> imagelist=new ArrayList();
public Test20(String title) {
super(title);
setLayout(new BorderLayout());
setSize(600, 500);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//将jp1宽度设置足够大,高度不变
jp1.setPreferredSize(new Dimension(Toolkit.getDefaultToolkit().getScreenSize().width+10,100));//往JScrollPane添加面板时,要设置jp1的尺寸,
// jsc是根据jp1的尺寸来具体确定是否显示滚动条
JScrollPane jsp=new JScrollPane(jp1,JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
jsp.setPreferredSize(new Dimension(0,100));
add(jsp,BorderLayout.NORTH);
jp2.setLayout(new BorderLayout());
add(jp2,BorderLayout.CENTER);
//中间大图
panel.setScaleType(ImageView.FIT_CENTER);
panel.setBgColor(Color.WHITE);
panel.setBorder(BorderFactory.createMatteBorder(1,0,0,0, Color.black));
jp2.add(panel,BorderLayout.CENTER);
//上面一排
jp1.setLayout(new MyXLayoutMan());
jp1.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
File imagefiles=new File("E:\\java\\images");
File[]images=imagefiles.listFiles();
for(File f:images){
ImageButton imageButton = new ImageButton(f);
Border lines=BorderFactory.createLineBorder(Color.white);
Border padding=BorderFactory.createEmptyBorder(5,5,5,5);
imageButton.setBorder(BorderFactory.createCompoundBorder(padding,lines));
imageButton.setPreferredSize(new Dimension(100,100));
imageButton.setBgColor(Color.WHITE);
imageButton.addMouseListener(new clickListener());
jp1.add(imageButton,"auto");
imagelist.add(imageButton);
}
setVisible(true);
}
class clickListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
ImageButton imagebutton =(ImageButton) e.getSource();
Image selectedimage = imagebutton.getImage();
for (ImageButton ib:imagelist) {
Image image = ib.getImage();
if(image==selectedimage) {
imagebutton.setBorder(BorderFactory.createLineBorder(Color.yellow, 3));
}else{
ib.setBorder(BorderFactory.createLineBorder(Color.white,3));}
}
panel.showImage(selectedimage);
}
}
public static void main(String[] args) {
new Test20("图片查看器");
}
}
class ImageButton extends ImageView{//显示图片按钮
private File f;
public ImageButton(File f){
this.f=f;
BufferedImage image=null;
try {
image = ImageIO.read(f);
} catch (IOException e) {
e.printStackTrace();
}
showImage(image);
setScaleType(ImageView.FIT_XY);
}
}
附上本文所用到的工具类
1、水平布局器
public class MyXLayoutMan implements LayoutManager2
{
private List<Item> items = new ArrayList<>();
private int gap = 2;
private boolean usePerferredSize = false; // 竖立方向是否占满
public MyXLayoutMan()
{
}
public MyXLayoutMan(int gap)
{
this.gap = gap; // 控件之间的间距
}
public MyXLayoutMan(int gap, boolean usePerferredSize)
{
this.gap = gap;
this.usePerferredSize = usePerferredSize;
}
@Override
public void addLayoutComponent(String name, Component comp)
{
Item item = new Item();
item.comp = comp;
item.constraints = "auto";
items.add(item);
}
@Override
public void removeLayoutComponent(Component comp)
{
Iterator<Item> iter = items.iterator();
while(iter.hasNext())
{
Item item = iter.next();
if(item.comp == comp)
{
iter.remove();
}
}
}
@Override
public void addLayoutComponent(Component comp, Object constraints)
{
Item item = new Item();
item.comp = comp;
item.constraints = (String) constraints;
items.add(item);
}
@Override
public Dimension preferredLayoutSize(Container parent)
{
return new Dimension(30,30);
}
@Override
public Dimension minimumLayoutSize(Container parent)
{
return new Dimension(30,30);
}
@Override
public Dimension maximumLayoutSize(Container target)
{
return new Dimension(30,30);
}
@Override
public void layoutContainer(Container parent)
{
// 得到内矩形
Rectangle rect = new Rectangle(parent.getWidth(), parent.getHeight());
//Rectangle rect = parent.getBounds();
Insets insets = parent.getInsets();
rect.x += insets.left;
rect.y += insets.top;
rect.width -= (insets.left + insets.right);
rect.height -= (insets.top + insets.bottom);
// 第一轮:过滤到无效的 Item ( 有些控件是隐藏的 )
List<Item> validItems = new ArrayList<>();
for(Item it: items )
{
if(it.comp.isVisible())
validItems.add(it);
}
// 第二轮处理:百分比,像素,auto的,直接计算出结果; 权重的,在第三轮计算
int totalGapSize = gap * (validItems.size() - 1);// 间距大小
int validSize = rect.width - totalGapSize;
int totalSize = 0;
int totalWeight = 0;
for(Item it : validItems)
{
Dimension preferred = it.comp.getPreferredSize();
it.width = preferred.width;
it.height = usePerferredSize ? preferred.height : rect.height;
it.weight = 0;
// 计算宽度
String cstr = it.constraints;
if( cstr == null || cstr.length() == 0)
{
//System.out.println("(AfRowLayout) Warn: Must define constraints when added to container!");
}
else if( cstr.equals("auto"))
{
}
else if(cstr.endsWith("%")) // 按百分比
{
int num = Integer.valueOf(cstr.substring(0,cstr.length()-1));
it.width = validSize * num / 100;
}
else if(cstr.endsWith("w")) // 按权重
{
int num = Integer.valueOf(cstr.substring(0,cstr.length()-1));
it.width = 0;
it.weight = num;
}
else if(cstr.endsWith("px")) // 按权重
{
int num = Integer.valueOf(cstr.substring(0,cstr.length()-2));
it.width = num;
}
else // 按像素
{
int num = Integer.valueOf(cstr);
it.width = num;
}
totalSize += it.width;
totalWeight += it.weight;
//System.out.println("计算值:width=" + it.width + ",weight=" + it.weight);
}
// 第三轮: 剩余空间按权重分配
if( totalWeight > 0)
{
int remainSize = validSize - totalSize;
double unit = (double) remainSize / totalWeight;
for(Item it : validItems)
{
if(it.weight > 0)
{
it.width = (int)( unit * it.weight );
}
}
}
//System.out.println("总宽度: " + rect.width);
// 第四轮: 按宽度和高度布局
int x = 0;
for(Item it : validItems)
{
int y = (rect.height - it.height)/2;
if(x + it.width > rect.width)
it.width = rect.width - x;
if(it.width <= 0) break;
it.comp.setBounds(rect.x + x, rect.y + y, it.width, it.height);
//System.out.println("宽度: " + it.width);
x += it.width;
x += gap; // 间距
}
}
@Override
public float getLayoutAlignmentX(Container target)
{
return 0;
}
@Override
public float getLayoutAlignmentY(Container target)
{
return 0;
}
@Override
public void invalidateLayout(Container target)
{
}
///
private static class Item
{
Component comp;
String constraints = "auto";
int width = 0;
int height = 0;
int weight = 0; // 权重
}
}
2、显示图片工具
public class ImageView extends JPanel
{
//
public static final int FIT_XY = 0;
public static final int FIT_CENTER = 1;
public static final int FIT_CENTER_INSIDE = 2;
private Image image;
private int scaleType = FIT_CENTER;
private Color bgColor = Color.WHITE; // 背景色
public ImageView()
{
this.setOpaque(false);
}
public Image getImage()
{
return image;
}
public void showImage(Image image)
{
this.image = image;
repaint();
}
public int getScaleType()
{
return scaleType;
}
public void setScaleType(int scaleType)
{
this.scaleType = scaleType;
repaint();
}
public Color getBgColor()
{
return bgColor;
}
public void setBgColor(Color bgColor)
{
this.bgColor = bgColor;
repaint();
}
@Override
protected void paintComponent(Graphics g)
{
// 先调用父类的 paintComponent(), 绘制必要的边框和背景
super.paintComponent(g);
// 本控件的宽度和高度
int width = this.getWidth();
int height = this.getHeight();
// 清除显示
//g.clearRect(0, 0, width, height);
// 背景色
g.setColor(bgColor);
g.fillRect(0, 0, width,height);
/
if(image != null)
{
int imgW = image.getWidth(null);
int imgH = image.getHeight(null);
// 使用 AfImageScaler 来计算
MyImageScaler scaler = new MyImageScaler(imgW, imgH, width,height);
// 根据缩放类型,来计算目标区域
Rectangle fit = scaler.fitXY();
if(scaleType == FIT_CENTER)
fit = scaler.fitCenter();
else if(scaleType == FIT_CENTER_INSIDE)
fit = scaler.fitCenterInside();
// 绘制
g.drawImage(image, fit.x, fit.y, fit.width, fit.height, null);
}
}
}
3、图片比例工具
// 图片缩放计算
//具体在哪放图片,通过计算得到适合的图片矩形
public class MyImageScaler
{
// 输入参数
private int imgW,imgH; // 图片的宽度、高度
private Rectangle rect; // 要绘制的目标区域
// imgW, imgH, 图片的宽度/高度
// rect: 目标区域
public MyImageScaler(int imgW, int imgH, Rectangle rect)
{
this.imgW = imgW;
this.imgH = imgH;
this.rect = rect;
}
public MyImageScaler(int imgW, int imgH, int dstW, int dstH)
{
this(imgW, imgH, new Rectangle(dstW, dstH));
}
// 拉伸显示,占满空间(比例可能失调)
public Rectangle fitXY()
{
return this.rect;
}
// 居中显示,保持长宽比,且适合目标矩形(缩小显示)
public Rectangle fitCenter()
{
int width = rect.width;
int height = rect.height;
int fitW = width;
int fitH = width * imgH / imgW;
if( fitH > height )
{
fitH = height;
fitW = height * imgW / imgH;
}
int x = (width - fitW ) /2;
int y = (height - fitH ) /2;
// 结果
return new Rectangle(rect.x + x, rect.y + y, fitW, fitH);
}
// 如果图片小于目标矩形,则直接居中显示
// 如果图片大于目标矩形,则按fitCenter()缩放后显示
public Rectangle fitCenterInside()
{
int width = rect.width;
int height = rect.height;
int fitW, fitH;
if(imgW <= width && imgH <= height)
{
fitW = imgW;
fitH = imgH;
int x = (width - fitW ) /2;
int y = (height - fitH ) /2;
return new Rectangle(rect.x + x, rect.y + y, fitW, fitH);
}
else
{
return fitCenter();
}
}
}