java - 首次使用 JScrollPane 显示图像时窗口滞后
问题描述
我正在尝试在 JScrollPane 中显示一堆 ImagePanel。这个应用程序的问题是每次新的一行面板进入视口时,整个窗口都会冻结一小段时间。但是,一旦滚动到最后,窗口将不会再次滞后。
这种滞后的原因是什么?我如何从一开始就防止它发生?
我的猜测是面板在滚动到之前不会被绘制。所以我尝试在将它们添加到背景后对它们调用重绘,但这不起作用:(
主类.java:
import javax.swing.SwingUtilities;
public class MainClass {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainFrame frame = new MainFrame();
}
});
}
}
MainFrame.java:
import java.awt.*;
import javax.swing.*;
public class MainFrame extends JFrame {
private static final long serialVersionUID = -254980289568295701L;
public MainFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState(JFrame.MAXIMIZED_BOTH);
JPanel background = new JPanel();
JScrollPane scrollPane = new JScrollPane(background,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
ImagePanel ipanel;
background.setPreferredSize(new Dimension(this.getWidth(),
this.getHeight() + 3000));
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
scrollPane.getVerticalScrollBar().setUnitIncrement(20);
add(scrollPane);
for (int i = 0; i < 40; i++) {
ipanel = new ImagePanel();
ipanel.setPreferredSize(new Dimension(300, 400));
ipanel.setSize(new Dimension(300, 400));
background.add(ipanel);
}
setVisible(true);
}
}
ImagePanel.java:
import java.awt.*;
import javax.swing.JPanel;
import java.awt.image.BufferedImage;
public class ImagePanel extends JPanel {
private static final long serialVersionUID = 1997246878999790104L;
private Image image;
private int width;
private int height;
public ImagePanel() {
width = 300;
height = 400;
BufferedImage bufferedImage = new BufferedImage(2000, 2000, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufferedImage.createGraphics();
g2d.setColor(Color.white);
g2d.fillRect(0, 0, 2000, 2000);
g2d.setColor(Color.black);
g2d.fillOval(0, 0, 2000, 2000);
g2d.setColor(Color.yellow);
g2d.fillOval(1500, 300, 400, 400);
g2d.fillOval(1200, 600, 400, 400);
g2d.fillOval(900, 900, 400, 400);
g2d.fillOval(600, 1200, 400, 400);
g2d.fillOval(300, 1500, 400, 400);
g2d.dispose();
image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
解决方案
我将您的代码更改为我们 aJLabel
以显示图像。
加载需要更长的时间,但滚动效果很好:
import java.awt.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
//public class ImagePanel extends JPanel {
public class ImagePanel extends JLabel {
private static final long serialVersionUID = 1997246878999790104L;
private Image image;
private int width;
private int height;
public ImagePanel() {
width = 300;
height = 400;
BufferedImage bufferedImage = new BufferedImage(2000, 2000, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufferedImage.createGraphics();
g2d.setColor(Color.white);
g2d.fillRect(0, 0, 2000, 2000);
g2d.setColor(Color.black);
g2d.fillOval(0, 0, 2000, 2000);
g2d.setColor(Color.yellow);
g2d.fillOval(1500, 300, 400, 400);
g2d.fillOval(1200, 600, 400, 400);
g2d.fillOval(900, 900, 400, 400);
g2d.fillOval(600, 1200, 400, 400);
g2d.fillOval(300, 1500, 400, 400);
g2d.dispose();
image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
setIcon( new ImageIcon(image) );
}
// @Override
protected void xxxpaintComponent(Graphics g) {
super.paintComponent(g);
// g.drawImage(image, 0, 0, this);
g.drawImage(image, 0, 0, null);
}
}
推荐阅读
- amazon-s3 - pyspark write overwrite 已分区但仍在覆盖先前的加载
- python - 我可以使用函数参数来创建全局变量吗?
- c - 我如何让它正确退出程序?
- mysql - 如何将唯一数据从 sql server 划分到两台不同的计算机
- twilio - 如何在 Twilio 中关闭退出功能
- asynchronous - 带有 DataReader LoadAsync 函数的 C++/CX concurrency::create_task 原因:“操作标识符无效。”
- css - 侧边栏在 wordpress 网站上损坏
- javascript - 如何使用 Bootstrap 4 轮播重置“点击”功能
- javascript - 用 JS 添加行并返回 Object
- sql - 为什么这个 Redshift 创建表查询与 DISTKEY 和 DISTSTYLE 不起作用?