我试图创建一个以图片为背景的JPanel,我能够做但是从GIF中可以看出,从选择不同的条目时似乎存在某种绘画问题JList。除了它的alpha值为65之外,JList没有什么特别之处,这意味着它几乎是透明的。我想知道如何修复奇怪的视觉故障。
我自定义JPanel的代码......
package com.css.aor.graphics;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;
/**
* @author Asmicor
*/
public class JImagePanel extends JPanel {
private static final long serialVersionUID = 248015296776870365L;
private Image img;
private boolean autoScale;
/**
* A JPanel that draws an image as the background in the center of the panel
*
* @param img Image that will be drawn as the background
* @param autoScale Should the image be scaled to fit the whole space of the panel
*/
public JImagePanel(Image img, boolean autoScale) {
this.img = img;
this.autoScale = autoScale;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (autoScale) {
int h = img.getHeight(null);
int w = img.getWidth(null);
// Scale Horizontally:
if (w > this.getWidth()) {
img = img.getScaledInstance(getWidth(), -1, Image.SCALE_SMOOTH);
h = img.getHeight(null);
}
// Scale Vertically:
if (h > this.getHeight()) {
img = img.getScaledInstance(-1, getHeight(), Image.SCALE_SMOOTH);
}
}
// Center Images
int x = (getWidth() - img.getWidth(null)) / 2;
int y = (getHeight() - img.getHeight(null)) / 2;
g.drawImage(img, x, y, this);
}
}
当我在g.drawImage之后添加一个repaint()时,问题似乎已经解决了,但据我所知,这不是一件好事。
编辑: 我注意到,当我向JList添加一个监听器,当所选值被更改,然后在整个框架上调用重绘时,这个问题似乎也解决了,所以我认为某些事情的顺序出错了重新绘制组件。
示例可运行代码...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.AbstractListModel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
public class Test {
private class JImagePanel extends JPanel {
private static final long serialVersionUID = 248015296776870365L;
private Image img;
private boolean autoScale = false;
/**
* A JPanel that draws an image as the background in the center of the panel
*
* @param img Image that will be drawn as the background
* @param autoScale Should the image be scaled to fit the whole space of the panel
*/
public JImagePanel(Image img, boolean autoScale) {
this.img = img;
this.autoScale = autoScale;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
if (autoScale) {
int h = img.getHeight(null);
int w = img.getWidth(null);
// Scale Horizontally:
if (w > this.getWidth()) {
img = img.getScaledInstance(getWidth(), -1, Image.SCALE_SMOOTH);
h = img.getHeight(null);
}
// Scale Vertically:
if (h > this.getHeight()) {
img = img.getScaledInstance(-1, getHeight(), Image.SCALE_SMOOTH);
}
}
// Center Images
int x = (getWidth() - img.getWidth(null)) / 2;
int y = (getHeight() - img.getHeight(null)) / 2;
g.drawImage(img, x, y, this);
}
}
}
private JFrame frame;
private JImagePanel panel;
private JList list;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test window = new Test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Test() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JImagePanel(Toolkit.getDefaultToolkit().getImage("C:\\Users\\Asmicor\\Desktop\\lh8vuSc.png"), true); // <-------- Just change this to a viable path
frame.getContentPane().add(panel, BorderLayout.CENTER);
list = new JList();
list.setModel(new AbstractListModel() {
String[] values = new String[] {"ghgfhgfhgfhgfhgfh", "gfhgfhgfhgfhgfhgfh", "gfhgfhgfhgfhgfhgfh", "gfhgfhgfhgfhdshs", "hgdfgdsfgsgdsfgdsfg", "dfhgfhdgfhdfhgfdhdgh"};
public int getSize() {
return values.length;
}
public Object getElementAt(int index) {
return values[index];
}
});
list.setBackground(new Color(0, 125, 50, 65));
GroupLayout gl_panel = new GroupLayout(panel);
gl_panel.setHorizontalGroup(
gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(Alignment.TRAILING, gl_panel.createSequentialGroup()
.addContainerGap(41, Short.MAX_VALUE)
.addComponent(list, GroupLayout.PREFERRED_SIZE, 359, GroupLayout.PREFERRED_SIZE)
.addGap(34))
);
gl_panel.setVerticalGroup(
gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addGap(19)
.addComponent(list, GroupLayout.PREFERRED_SIZE, 208, GroupLayout.PREFERRED_SIZE)
.addContainerGap(34, Short.MAX_VALUE))
);
panel.setLayout(gl_panel);
}
}
EDIT2:从我可以收集的内容来看,任何在图像上绘制透明背景的组件都会发生这种情况。我在JLabel和JTable上进行了测试,两者都有类似的视觉故障。唯一真正的解决方法是将repaint()添加到我的paintComponent的JImagePanel,但我的CPU使用率非常高。