我正在创建一个应用程序,您可以将背景更改为任何图片,或者只保留默认图片。它由一个ImagePanel
类组成,它覆盖在paintComponent上,将imageicon设置为背景。
GUISettings
类,以便用户从带有过滤器的FileChooser中选择图像,然后将file.getPath()字符串传递给ImagePanel
类,重新验证gui,但没有更改后台,甚至没有我在ImagePanel
控制台上显示的调试打印。以下是代码(简化):
ImagePanel
类:
public class ImagePanel extends JPanel{
private String defaultbg = "Icons/background.jpg";
private String path = "";
private BufferedImage img;
private GridBagConstraints gbc = new GridBagConstraints();
public ImageIcon bgicon;
private Image bg;
public static boolean defaultbgset = true;
public ImagePanel(){
if(defaultbgset){
path = defaultbg;
System.out.println("path in default = " + path);
} else {
if(GUISettings.getPath() != null){
path = GUISettings.getPath();
System.out.println("path in userBG = " + path);
}
}
bgicon = new ImageIcon(getClass().getResource(path));
bg = (new ImageIcon(bgicon.getImage().getScaledInstance(1024, 800, java.awt.Image.SCALE_SMOOTH))).getImage();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
}
public ImageIcon getDrawBoardBackground(){
return bgicon;
}
public void setPath(String p){
this.path = p;
}
public void resetPath(){
this.path = defaultbg;
}
}
现在是GUISettings
类:
public class GUISettings extends JPanel implements ActionListener{
private TitledBorder title = BorderFactory.createTitledBorder("User Interface Settings");
private JLabel lbackground, userbg;
private JTextField bgpath;
private GridBagConstraints gbc = new GridBagConstraints();
public static JRadioButton default_bg, user_bg;
private JButton browse;
public static File file;
private JLabel userfile = new JLabel("Not chosen.");
public static String userBgPath = null;
public GUISettings(){
//this.setLayout(new GridBagLayout());
Dimension size = getPreferredSize();
size.setSize(200,150); //w, h
this.setPreferredSize(size);
this.setBorder(title);
JPanel toppane = new JPanel();
toppane.setLayout(new GridBagLayout());
(..)
browse = new JButton("Choose file");
browse.setActionCommand("browse");
browse.addActionListener(this);
gbc.gridx = 1;
gbc.gridy = 2;
gbc.insets = new Insets(0,0,0,0);
toppane.add(browse,gbc);
gbc.gridx = 2;
gbc.gridy = 2;
gbc.insets = new Insets(0,5,0,0);
toppane.add(userfile,gbc);
add(toppane, BorderLayout.NORTH);
JPanel midpane = new JPanel();
midpane.setLayout(new GridBagLayout());
add(midpane, BorderLayout.CENTER);
(..)
}
@Override
public void actionPerformed(ActionEvent e) {
if("browse".equalsIgnoreCase(e.getActionCommand())){
final JFileChooser fc = new JFileChooser();
fc.setFileFilter(new ExtensionFileFilter());
int returnVal = fc.showOpenDialog(fc);
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
//This is where a real application would open the file.
userfile.setText(file.getName());
userBgPath = file.getPath();
// THIS IS WHERE I UPDATE PATH etc.
MainFrame.bg.setPath(userBgPath);
MainFrame.bg.defaultbgset = false; // set to user
MainFrame.bg.repaint();
MainFrame.bg.revalidate();
user_bg.setSelected(true);
System.out.println("File: " + file.getName() + ".");
} else {
MainFrame.bg.defaultbgset = true;
MainFrame.bg.resetPath();
MainFrame.bg.repaint();
MainFrame.bg.revalidate();
default_bg.setSelected(true);
}
} // end of if
}
public static String getPath(){
return userBgPath;
}
}
答案 0 :(得分:4)
@Override
public void paintComponent(Graphics g) {
g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
}
这应该写成:
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
}
无论何时以任何方式更改ImagePanel的图像,都必须调用repaint()
对象的ImagePanel
方法(比如imagepanel)..使用
imagePanel.repaint()
。
<强>更新强>
在我看来,你应该在ImagePanel
类中有一个方法来设置图像并在那里重新绘制JPanel
本身,如:
public void setImage(Image bg)
{
this.bg = bg;
repaint();
}
这样可以避免在明确使用repaint()
对象的ImagePanel
方法时使用它。
答案 1 :(得分:4)
然后将file.getPath()字符串传递给ImagePanel类
传递路径不会做任何事情。实际上,当路径发生变化时,您需要读取图像。所以在你的set path方法中,我猜你需要添加如下代码:
bgicon = new ImageIcon(getClass().getResource(path));
bg = (new ImageIcon(bgicon.getImage().getScaledInstance(1024, 800, java.awt.Image.SCALE_SMOOTH))).getImage();
repaint();
班级应该负责重画自己。