我正在为游戏制作自定义菜单,并尝试绘制组件时遇到问题。 这个想法是,让图片或视频在后台运行,其上面有一个面板,其中包含一些自定义菜单项。
包含菜单项的面板应该是半透明的,这就是我猜的问题。
因为有点难以解释我已经建立了一个展示这个问题的例子。在鼠标悬停时重新绘制菜单项没有任何问题,但看起来重绘也会影响不应绘制的面板部分,因为实际菜单项的形状不适合面板矩形形状。这导致我的菜单项具有难看的黑色边缘,不应该在那里(右上角和左下角)。
希望你们知道这个原因的解决方案我开始变得非常恼火。我尝试了我在这里或网上其他地方找到的所有东西,但看起来所有其他问题只需要处理重绘一个不会改变的形状。
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class TransparentDrawTest extends JPanel implements MouseListener {
private final static Dimension SIZE = new Dimension(400, 50);
private boolean isSelected;
private boolean isClicked;
public static void main(String[] args) {
JFrame testFrame = new JFrame();
testFrame.setSize(500, 100);
testFrame.setResizable(false);
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
testFrame.setLocationRelativeTo(null);
testFrame.setBackground(Color.WHITE);
JPanel semiTransPanel = new JPanel();
semiTransPanel.setBackground(new Color(0.0f, 0.0f, 0.0f, 0.6f));
semiTransPanel.setOpaque(true);
semiTransPanel.add(new TransparentDrawTest());
testFrame.add(semiTransPanel);
testFrame.setVisible(true);
}
public TransparentDrawTest() {
this.addMouseListener(this);
this.setSize(SIZE);
this.setMinimumSize(SIZE);
this.setMaximumSize(SIZE);
this.setPreferredSize(SIZE);
this.setOpaque(false);
}
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
g2d.fillRect(0, 0, 400, 50);
int[] pointsX;
int[] pointsY;
if (this.isSelected) {
pointsX = new int[] { 2, 348, 398, 48 };
pointsY = new int[] { 2, 2, 48, 48 };
}
else {
pointsX = new int[] { 2, 298, 348, 48 };
pointsY = new int[] { 2, 2, 48, 48 };
}
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(5));
g2d.setColor(Color.WHITE);
g2d.drawPolygon(pointsX, pointsY, 4);
if (this.isClicked)
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f));
else
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g.fillPolygon(pointsX, pointsY, 4);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
this.isSelected = true;
this.repaint();
}
@Override
public void mouseExited(MouseEvent e) {
this.isSelected = false;
this.repaint();
}
@Override
public void mousePressed(MouseEvent e) {
this.isClicked = true;
this.repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
this.isClicked = false;
this.repaint();
}
}
答案 0 :(得分:2)
至少有两件事我能看到会给你带来麻烦...
首先,您正在更改Graphics
上下文的字母组合,但您没有休息....
Graphics2D g2d = (Graphics2D) g;
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
Graphics
上下文是一个共享资源,在当前绘制周期中绘制的所有组件都将被赋予相同的Graphics
实例,这意味着您对其所做的任何更改都将传递给正在绘制的其他组件。
相反,您应该创建Graphics
上下文的临时副本,然后使用它...
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
//...
// If you create it, you must dispose of it...
g2d.dispose();
其次,您将不透明组件的背景颜色设置为半透明值...
semiTransPanel.setBackground(new Color(0.0f, 0.0f, 0.0f, 0.6f));
问题是,Swing只处理组件而且不透明或透明。通过这样做,Swing不会知道它也应该更新这个下面的组件。基本上它会认为组件是不透明的(因为它是)并且不会更新下面的组件......
基本上,你需要做一些类似于你使用TransparentDrawTest
面板所做的事情,并假装它,例如......
JPanel semiTransPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(0.6f));
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
}
};
semiTransPanel.setBackground(new Color(0.0f, 0.0f, 0.0f));
semiTransPanel.setOpaque(false);
我也无法弄清楚你为什么要这样做......
g2d.fillRect(0, 0, 400, 50);
在TransparentDrawTest
窗格中...
你应该首先调用super.paintComponent(g)
,这实际上是这个方法的作用,它清除了绘制的Graphics
上下文...等等;)
更新了示例代码...
这是我用来测试代码的示例代码......
Ps:我改变了半透明面板的背景颜色,所以我可以看到差异......
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TransparentDrawTest extends JPanel implements MouseListener {
private final static Dimension SIZE = new Dimension(400, 50);
private boolean isSelected;
private boolean isClicked;
public static void main(String[] args) {
JFrame testFrame = new JFrame();
testFrame.setSize(500, 100);
testFrame.setResizable(false);
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
testFrame.setLocationRelativeTo(null);
testFrame.setBackground(Color.WHITE);
JPanel semiTransPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getBackground());
g2d.setComposite(AlphaComposite.SrcOver.derive(0.6f));
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
}
};
semiTransPanel.setOpaque(false);
semiTransPanel.setBackground(Color.RED);
semiTransPanel.add(new TransparentDrawTest());
testFrame.add(semiTransPanel);
testFrame.setVisible(true);
}
public TransparentDrawTest() {
this.addMouseListener(this);
this.setSize(SIZE);
this.setMinimumSize(SIZE);
this.setMaximumSize(SIZE);
this.setPreferredSize(SIZE);
this.setOpaque(false);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int[] pointsX;
int[] pointsY;
if (this.isSelected) {
pointsX = new int[]{2, 348, 398, 48};
pointsY = new int[]{2, 2, 48, 48};
} else {
pointsX = new int[]{2, 298, 348, 48};
pointsY = new int[]{2, 2, 48, 48};
}
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(5));
g2d.setColor(Color.WHITE);
Composite comp = g2d.getComposite();
if (this.isClicked) {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f));
} else {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
}
g2d.fillPolygon(pointsX, pointsY, 4);
g2d.setComposite(comp);
g2d.drawPolygon(pointsX, pointsY, 4);
g2d.dispose();
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
this.isSelected = true;
this.repaint();
}
@Override
public void mouseExited(MouseEvent e) {
this.isSelected = false;
this.repaint();
}
@Override
public void mousePressed(MouseEvent e) {
this.isClicked = true;
this.repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
this.isClicked = false;
this.repaint();
}
}
答案 1 :(得分:0)
有关可能的问题和简单的解决方案,请参阅Backgrounds With Transparency:
//testFrame.add(semiTransPanel);
testFrame.add( new AlphaContainer(semiTransPanel) );