Java - 在重新绘制高分辨率图像时,paintComponent() 会大大减慢程序速度

标签 java swing paintcomponent

最近我一直在做一个小项目,直到遇到一些相当烦人的事情。

程序当前执行的操作是读取程序生成的某些文件夹,其中显示文件扩展名“.jpg”和“.png”的文件(为此,用户必须手动插入这些文件夹中的图像)。

该部分一直有效,直到我们到达我创建的动画部分。这是一个具有特定 RGBA 值的矩形,一旦鼠标悬停在其上并退出它,就会更改其 alpha 值。对于低分辨率图像,此动画运行流畅,但对于高分辨率图像,其非常滞后,并且动画看起来不那么流畅。

ma​​inFrame类

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();
    }
}

电影节目面板

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();
    }
}

扫描图像

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;
    }
}

要测试它,你们需要做的就是将图像放入电影和节目文件中,该文件位于“文档”文件夹库中名为 SeriesOrganiser 的文件夹中。 (Windows 10)。

不介意对代码的一些批评,因为我知道我还有很多需要改进的地方。

最佳答案

来自paintComponent()方法的一些注释:

scanForImage findImage = new scanForImage();

不要在绘画方法中进行 I/O。绘画方法仅用于绘画

repaint();

不要调用repaint()。这将导致绘画请求不断添加到事件队列中。

如果您需要动画,请使用 Swing Timer安排动画。

g.dispose();

不要丢弃传递给该方法的 Graphics 对象。框架上的其他组件可以使用该 Graphics。

您只能对在 paintComponent() 方法中创建的 Graphic 对象使用 dispose() 方法。

关于Java - 在重新绘制高分辨率图像时,paintComponent() 会大大减慢程序速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43103428/

相关文章:

java - 贾克斯布 : Two declarations in a wsdl cause a collision in the objectFactory class

java - 这个组件的名称是什么

java - 为什么 JButton 不起作用?

Java PaintComponent 无缘无故地绘制顶部 GUI 面板的副本

java - 在接口(interface)中使用 Java 泛型

java - Applet 在 Opera 中不接收鼠标移动事件

java - JTable JComboBox 第一项名称错误

java - 调整 JPanel 大小后组件消失

Java Blackjack GUIpaintComponentdrawImage不显示所有纸牌

java - 如何找到数字在哪个范围内