如何刷新其中包含 BufferedImage 的 JFrame?
How can I refresh a JFrame with BufferedImage in it?
除了我的问题,我做了以下class做一个JFrame
:
package myprojects;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
class BackgroundImageJFrame extends JFrame {
public BackgroundImageJFrame(BufferedImage img) {
setTitle("Background Color for JFrame");
int h = img.getHeight();
int w = img.getWidth();
setSize(w, h);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
setLayout(new BorderLayout());
setContentPane(new JLabel(new ImageIcon(img)));
setLayout(new FlowLayout());
// Just for refresh :) Not optional!
setSize(w-1, h-1);
setSize(w, h);
}
}
我用 new BackgroundImageJFrame(img);
调用。因为我想刷新此 JFrame
的内容,所以这不是最佳工作方式,因为这每次都会创建一个新的 JFrame
。
我怎样才能改变它以只刷新 JFrame
?
您可以非常简单地通过存储 JLabel
控件,然后使用方法设置图像来完成此操作。确保将图像设置为 Event Dispatch Thread!
我修改了代码,根据@MadProgrammer 的精彩评论以更稳定的方式执行此操作。
此版本与上一版本之间解决的问题的简要总结:
- 您不希望
contentPane
成为 JLabel
,因为这会使以后添加其他控件变得更加困难并且没有布局管理器。我在两者之间添加了一个JPanel
,并给它BorderLayout
。
- 调用者应该负责线程安全。原来我没有这样做,因为你没有提供任何调用代码,但在这里,我做了事件调度线程委托。确保在调用
setBackgroundImage()
. 之前使用 EventQueue.invokeLater
切换到事件调度线程,就像我在 main 中所做的那样
- 我在 JLabel 上使用
setSize
和 setPreferredSize
,以便布局管理器可以正确地为控件选择合适的大小,这样 frame.pack
就可以按预期工作。
- 我在构造函数之外的
initComponents
方法中创建控件,以使代码更易于理解,并便于以后在必要时添加更多构造函数。
代码如下:
public class NonogramSolutionJFrame extends JFrame {
private final JLabel label;
private final JPanel panel;
public NonogramSolutionJFrame(BufferedImage img) {
panel = new JPanel();
label = new JLabel();
initComponents(img);
}
private final void initComponents(BufferedImage img) {
setTitle("Background Color for JFrame");
setBackgroundImage(img);
setContentPane(panel);
panel.setLayout(new BorderLayout());
panel.add(label, BorderLayout.CENTER);
setLocationRelativeTo(null);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void setBackgroundImage(final BufferedImage img) {
label.setIcon(new ImageIcon(img));
label.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
}
public static void main(String... args) throws Exception {
BufferedImage img = ImageIO.read(NonogramSolutionJFrame.class.getResource("/nonogram.png"));
NonogramSolutionJFrame frame = new NonogramSolutionJFrame(img);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
frame.setVisible(true);
}
});
}
}
使用您 中的图像,此代码生成以下内容(在 Linux 上):
除了我的问题JFrame
:
package myprojects;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
class BackgroundImageJFrame extends JFrame {
public BackgroundImageJFrame(BufferedImage img) {
setTitle("Background Color for JFrame");
int h = img.getHeight();
int w = img.getWidth();
setSize(w, h);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
setLayout(new BorderLayout());
setContentPane(new JLabel(new ImageIcon(img)));
setLayout(new FlowLayout());
// Just for refresh :) Not optional!
setSize(w-1, h-1);
setSize(w, h);
}
}
我用 new BackgroundImageJFrame(img);
调用。因为我想刷新此 JFrame
的内容,所以这不是最佳工作方式,因为这每次都会创建一个新的 JFrame
。
我怎样才能改变它以只刷新 JFrame
?
您可以非常简单地通过存储 JLabel
控件,然后使用方法设置图像来完成此操作。确保将图像设置为 Event Dispatch Thread!
我修改了代码,根据@MadProgrammer 的精彩评论以更稳定的方式执行此操作。
此版本与上一版本之间解决的问题的简要总结:
- 您不希望
contentPane
成为JLabel
,因为这会使以后添加其他控件变得更加困难并且没有布局管理器。我在两者之间添加了一个JPanel
,并给它BorderLayout
。 - 调用者应该负责线程安全。原来我没有这样做,因为你没有提供任何调用代码,但在这里,我做了事件调度线程委托。确保在调用
setBackgroundImage()
. 之前使用 - 我在 JLabel 上使用
setSize
和setPreferredSize
,以便布局管理器可以正确地为控件选择合适的大小,这样frame.pack
就可以按预期工作。 - 我在构造函数之外的
initComponents
方法中创建控件,以使代码更易于理解,并便于以后在必要时添加更多构造函数。
EventQueue.invokeLater
切换到事件调度线程,就像我在 main 中所做的那样
代码如下:
public class NonogramSolutionJFrame extends JFrame {
private final JLabel label;
private final JPanel panel;
public NonogramSolutionJFrame(BufferedImage img) {
panel = new JPanel();
label = new JLabel();
initComponents(img);
}
private final void initComponents(BufferedImage img) {
setTitle("Background Color for JFrame");
setBackgroundImage(img);
setContentPane(panel);
panel.setLayout(new BorderLayout());
panel.add(label, BorderLayout.CENTER);
setLocationRelativeTo(null);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void setBackgroundImage(final BufferedImage img) {
label.setIcon(new ImageIcon(img));
label.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
}
public static void main(String... args) throws Exception {
BufferedImage img = ImageIO.read(NonogramSolutionJFrame.class.getResource("/nonogram.png"));
NonogramSolutionJFrame frame = new NonogramSolutionJFrame(img);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
frame.setVisible(true);
}
});
}
}
使用您