Java - 重绘高分辨率图像时,paintComponent() 会大大降低程序速度
Java - paintComponent() drastically slowing down the program when repainting an image of high resolution
最近在做一个小项目,遇到了比较烦人的事情
程序当前所做的是读取程序生成的某些文件夹,其中显示文件扩展名为“.jpg”和“.png”的文件(为此,用户必须在这些文件夹中手动插入图像)。
该部分有效,直到我们到达我的动画部分 created.This 是一个具有特定 RGBA 值的矩形,一旦鼠标悬停在它上面并退出它就会改变它的 alpha 值。对于低分辨率图像,此动画效果流畅,但对于高分辨率图像,它非常滞后并且动画看起来不那么流畅。
mainFrame Class
package seriesorganiser;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*
* @author Luca Muscat
*/
public class mainFrame {
private static boolean check;
private static final String DOCUMENTS_LOCATION = System.getProperty("user.home") + "\Documents";
public static void main(String[] args) throws IOException {
check = new File(DOCUMENTS_LOCATION + "\SeriesOrganiser").exists();
if (!check) {
new File(DOCUMENTS_LOCATION + "\SeriesOrganiser").mkdir();
new File(DOCUMENTS_LOCATION + "\SeriesOrganiser\Shows").mkdir();
new File(DOCUMENTS_LOCATION + "\SeriesOrganiser\Movies").mkdir();
}
JFrame frame = new JFrame("Series Organiser");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//Layout Handler
JPanel container = new JPanel();
//Movies=0, Shows=1.
JPanel moviesPanel = new moviesShowsPanel(0);
JPanel showsPanel = new moviesShowsPanel(1);
container.setLayout(new GridLayout(1, 2));
container.add(moviesPanel);
container.add(showsPanel);
frame.add(container);
frame.pack();
}
}
moviesShowsPanel
package seriesorganiser;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
/**
*
* @author Luca Muscat
*/
public class moviesShowsPanel extends JPanel {
int alpha = 255 / 2;
boolean isMouseOver = false;
boolean isMouseHover = false;
public final static int SHOWS_GENRE = 1;
public final static int MOVIES_GENRE = 0;
private int genreHolder;
public moviesShowsPanel(int genre) {
genreHolder=genre;
setPreferredSize(new Dimension(600, 600));
setBorder(BorderFactory.createLineBorder(Color.black));
setBackground(Color.LIGHT_GRAY);
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent me) {
if(!isMouseOver)repaint();
isMouseOver = true;
}
@Override
public void mouseExited(MouseEvent me) {
if(isMouseOver)repaint();
isMouseOver = false;
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
scanForImage findImage = new scanForImage();
if (isMouseOver && alpha>10) {
alpha-=10;
}
if(!isMouseOver && alpha<145){
alpha+=10;
}
try {
if(genreHolder==MOVIES_GENRE){
g.drawImage(findImage.findMoviesImage(), 0, 0, getWidth(), getHeight(), null);
}
if(genreHolder==SHOWS_GENRE){
g.drawImage(findImage.findShowsImage(),0,0,getWidth(),getHeight(),null);
}
} catch (IOException ex) {
Logger.getLogger(moviesShowsPanel.class.getName()).log(Level.SEVERE, null, ex);
}
g.setColor(new Color(214, 229, 255, alpha));
g.fillRect(0, 0, getWidth(), getHeight());
repaint();
}
}
scanForImage
package seriesorganiser;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/**
*
* @author Luca Muscat
*/
public class scanForImage {
private static final String DOCUMENTS_LOCATION = System.getProperty("user.home")+"\Documents";
BufferedImage findMoviesImage() throws IOException{
BufferedImage img = null;
File folderMovies = new File(DOCUMENTS_LOCATION+"\SeriesOrganiser\Movies");
img=DRY(folderMovies);
return img;
}
BufferedImage findShowsImage()throws IOException{
BufferedImage img=null;
File folderShows = new File(DOCUMENTS_LOCATION+"\SeriesOrganiser\Shows");
img = DRY(folderShows);
return img;
}
private BufferedImage DRY(File f)throws IOException{
BufferedImage img=null;
String filepath=String.valueOf(f);
File[] listOfFiles=f.listFiles();
for(File c:listOfFiles){
if(c.isFile()){
if(c.getName().contains(".jpg") || c.getName().contains(".png")){
img=ImageIO.read(new File(filepath+"\"+c.getName()));
break;
}
}
}
return img;
}
}
要测试它,你们需要做的就是将图像放入电影和节目文件中,这些文件位于 "Documents" 文件夹库中名为 SeriesOrganiser 的文件夹中。 (Windows 10).
不介意对代码的一些批评,因为我知道我还有很多需要改进的地方。
来自 paintComponent() 方法的一些评论:
scanForImage findImage = new scanForImage();
画法中不要I/O。一种绘画方法,仅作绘画用
repaint();
不要调用 repaint()
。这将导致绘画请求不断添加到事件队列中。
如果您需要动画,请使用 Swing Timer 安排动画。
g.dispose();
不要释放传递给该方法的 Graphics 对象。框架上的其他组件可能会使用此图形。
您只能对在 paintComponent()
方法中创建的 Graphic
对象使用 dispose()
方法。
最近在做一个小项目,遇到了比较烦人的事情
程序当前所做的是读取程序生成的某些文件夹,其中显示文件扩展名为“.jpg”和“.png”的文件(为此,用户必须在这些文件夹中手动插入图像)。
该部分有效,直到我们到达我的动画部分 created.This 是一个具有特定 RGBA 值的矩形,一旦鼠标悬停在它上面并退出它就会改变它的 alpha 值。对于低分辨率图像,此动画效果流畅,但对于高分辨率图像,它非常滞后并且动画看起来不那么流畅。
mainFrame Class
package seriesorganiser;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*
* @author Luca Muscat
*/
public class mainFrame {
private static boolean check;
private static final String DOCUMENTS_LOCATION = System.getProperty("user.home") + "\Documents";
public static void main(String[] args) throws IOException {
check = new File(DOCUMENTS_LOCATION + "\SeriesOrganiser").exists();
if (!check) {
new File(DOCUMENTS_LOCATION + "\SeriesOrganiser").mkdir();
new File(DOCUMENTS_LOCATION + "\SeriesOrganiser\Shows").mkdir();
new File(DOCUMENTS_LOCATION + "\SeriesOrganiser\Movies").mkdir();
}
JFrame frame = new JFrame("Series Organiser");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//Layout Handler
JPanel container = new JPanel();
//Movies=0, Shows=1.
JPanel moviesPanel = new moviesShowsPanel(0);
JPanel showsPanel = new moviesShowsPanel(1);
container.setLayout(new GridLayout(1, 2));
container.add(moviesPanel);
container.add(showsPanel);
frame.add(container);
frame.pack();
}
}
moviesShowsPanel
package seriesorganiser;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
/**
*
* @author Luca Muscat
*/
public class moviesShowsPanel extends JPanel {
int alpha = 255 / 2;
boolean isMouseOver = false;
boolean isMouseHover = false;
public final static int SHOWS_GENRE = 1;
public final static int MOVIES_GENRE = 0;
private int genreHolder;
public moviesShowsPanel(int genre) {
genreHolder=genre;
setPreferredSize(new Dimension(600, 600));
setBorder(BorderFactory.createLineBorder(Color.black));
setBackground(Color.LIGHT_GRAY);
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent me) {
if(!isMouseOver)repaint();
isMouseOver = true;
}
@Override
public void mouseExited(MouseEvent me) {
if(isMouseOver)repaint();
isMouseOver = false;
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
scanForImage findImage = new scanForImage();
if (isMouseOver && alpha>10) {
alpha-=10;
}
if(!isMouseOver && alpha<145){
alpha+=10;
}
try {
if(genreHolder==MOVIES_GENRE){
g.drawImage(findImage.findMoviesImage(), 0, 0, getWidth(), getHeight(), null);
}
if(genreHolder==SHOWS_GENRE){
g.drawImage(findImage.findShowsImage(),0,0,getWidth(),getHeight(),null);
}
} catch (IOException ex) {
Logger.getLogger(moviesShowsPanel.class.getName()).log(Level.SEVERE, null, ex);
}
g.setColor(new Color(214, 229, 255, alpha));
g.fillRect(0, 0, getWidth(), getHeight());
repaint();
}
}
scanForImage
package seriesorganiser;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/**
*
* @author Luca Muscat
*/
public class scanForImage {
private static final String DOCUMENTS_LOCATION = System.getProperty("user.home")+"\Documents";
BufferedImage findMoviesImage() throws IOException{
BufferedImage img = null;
File folderMovies = new File(DOCUMENTS_LOCATION+"\SeriesOrganiser\Movies");
img=DRY(folderMovies);
return img;
}
BufferedImage findShowsImage()throws IOException{
BufferedImage img=null;
File folderShows = new File(DOCUMENTS_LOCATION+"\SeriesOrganiser\Shows");
img = DRY(folderShows);
return img;
}
private BufferedImage DRY(File f)throws IOException{
BufferedImage img=null;
String filepath=String.valueOf(f);
File[] listOfFiles=f.listFiles();
for(File c:listOfFiles){
if(c.isFile()){
if(c.getName().contains(".jpg") || c.getName().contains(".png")){
img=ImageIO.read(new File(filepath+"\"+c.getName()));
break;
}
}
}
return img;
}
}
要测试它,你们需要做的就是将图像放入电影和节目文件中,这些文件位于 "Documents" 文件夹库中名为 SeriesOrganiser 的文件夹中。 (Windows 10).
不介意对代码的一些批评,因为我知道我还有很多需要改进的地方。
来自 paintComponent() 方法的一些评论:
scanForImage findImage = new scanForImage();
画法中不要I/O。一种绘画方法,仅作绘画用
repaint();
不要调用 repaint()
。这将导致绘画请求不断添加到事件队列中。
如果您需要动画,请使用 Swing Timer 安排动画。
g.dispose();
不要释放传递给该方法的 Graphics 对象。框架上的其他组件可能会使用此图形。
您只能对在 paintComponent()
方法中创建的 Graphic
对象使用 dispose()
方法。