【发布时间】:2017-10-24 13:20:12
【问题描述】:
我有一个任务执行器,它有 5 个外部面板,每个外部面板都是一个 JFrame,它有一个 innerPanel。 innerpanel 是负责绘制图像的JPanel。我一遍又一遍地显示和删除许多图像,我的表现很差。
有人可以建议一种在不使用JFrame 的情况下加载和删除许多图像的方法吗?
我在屏幕的不同部分显示图像,有时持续时间极短50-1500ms。有时图像仅部分加载,而在其他情况下则根本不加载。
Main
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleWithFixedDelay(new ImageTask(new OuterPanel(ScreenPosition.CENTER)), 0, 3, TimeUnit.SECONDS);
scheduledExecutorService.scheduleWithFixedDelay(new ImageTask(new OuterPanel(ScreenPosition.CENTER)), 0, 3, TimeUnit.SECONDS);
scheduledExecutorService.scheduleWithFixedDelay(new ImageTask(new OuterPanel(ScreenPosition.CENTER)), 0, 3, TimeUnit.SECONDS);
scheduledExecutorService.scheduleWithFixedDelay(new ImageTask(new OuterPanel(ScreenPosition.CENTER)), 0, 3, TimeUnit.SECONDS);
scheduledExecutorService.scheduleWithFixedDelay(new ImageTask(new OuterPanel(ScreenPosition.CENTER)), 0, 3, TimeUnit.SECONDS);
}
}
ImageTask
public class ImageTask implements Runnable {
private OuterPanel outerPanel;
private int messageIndex;
public ImageTask(OuterPanel outerPanel) {
this.outerPanel = outerPanel;
}
@Override
public void run() {
outerPanel.setMessage(imagePath);
outerPanel.setVisible(true);
try {
TimeUnit.MILLISECONDS.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
outerPanel.setVisible(false);
}
}
OuterPanel
public class OuterPanel extends JFrame {
private InnerPanel innerPanel;
public static int height = 200;
public static int width = 200;
public OuterPanel(ScreenPosition screenPosition) {
initComponents();
setFocusable(false);
setUndecorated(true);
setBackground(new Color(0, 0, 0, 0));
setAlwaysOnTop(true);
setSize(SetScreenLocation.screenSize.width, SetScreenLocation.screenSize.height);
setFocusableWindowState(false);
setEnabled(false);
pack();
setLocation(0, 0);
}
private void initComponents() {
innerPanel = new InnerPanel();
add(innerPanel);
}
public void setMessage(Message message) {
ImageIcon icon = IconFetch.getInstance().getIcon(message.getImagePath());
if (icon != null) {
Image img = IconFetch.getInstance().getScaledImage(icon.getImage(), width, height);
innerPanel.setImage(img);
}
}
}
InnerPanel
public class InnerPanel extends JPanel {
private String message;
private Image img;
public InnerPanel() {
setOpaque(false);
setPreferredSize(new Dimension(900, 450));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if (img != null) {
x = (this.getWidth() - img.getWidth(null)) / 2;
y = (this.getHeight() - img.getHeight(null)) / 2;
g2d.drawImage(img, x, y, this);
}
}
public void setImage(Image image) {
this.img = image;
repaint();
}
}
【问题讨论】:
-
为了更好的帮助,请尽快发布正确的minimal reproducible example,这个缺少方法调用和
main方法,所以我们无法知道您是否将程序放在 EDT 上,如果您正在使用自己的线程或Swing Timer或Utils Timer -
1) 获取示例图像的一种方法(如@Frakcool 所述)是热链接到在this Q&A 中看到的图像。 2) 见The Use of Multiple JFrames, Good/Bad Practice?
-
我已经看到了,使用 JFrame 是一个问题,原因有很多。它创建了许多堆叠在一起的窗口,并导致性能问题。我还需要重复加载多张图像并将它们显示在屏幕的不同部分,有时需要很短的时间。我开始认为这不是 Java 可以做到的。
-
提示:如果你想回复某人,你应该在他们的名字前添加
@,例如@AndrewThompson。你为什么要创建新的JFrame并在这么短的时间内显示它们?我认为最好创建一个JFrame,更改图像及其在屏幕上的位置,而不是每次都创建新图像以及使用Swing Timer而不调用.sleep(...)。 -
“我还需要重复加载多个图像并将它们显示在屏幕的不同部分” - 也许考虑某种缓存,加载图像可能会很耗时。 “我开始认为这不是 Java 可以完成的事情” - 我很确定它可以,但你可能需要注意你的资源管理,重新 -在可能的情况下使用元素,这可能意味着拥有一个不可见的帧池,进一步减少对象创建和销毁的开销。您还需要小心,因为 Swing 不是线程安全的
标签: java multithreading image swing jpanel