在 BufferedImage 上设置 JButton 的透明度

3

我有一个问题:

我在JFrame中呈现了一个BufferedImage,然后将一个JButton添加到同一框架中。当我尝试使按钮透明时,按钮变得透明,但是忽略了它的实际位置,就像它卡在框架的左上角一样透明。 我测试了一些不同的方法来使按钮透明,但结果总是相同。

有什么想法吗?

谢谢

public class TestPanel extends JPanel {

public TestPanel(){
    JButton foo = new JButton("test");
    foo.setBackground(new Color(0, 0, 0, 0));
    foo.setBounds(20, 100, 300, 50);
    this.add(foo);
}

public void paint(Graphics g){
    Graphics2D g2 = (Graphics2D) g;
    g2.drawImage(ImageFactory.getImg(), 0, 0, null); //get a BufferedImage
    g2.dispose();
}

}

3个回答

7

我看到了一些问题,虽然我不确定它们中的哪一个引起了你的问题。我尝试按顺序列出它们:

  1. Your TestPanel doesn't specify a LayoutManager (I hope you are specifying it somewhere else in your code).
  2. You are extending a JPanel without call super paintComponent method (don't use paint). You should do this before anything else in your paintComponent method:

    public void paintComponent(Graphics g){
        super.paintComponent(g); 
    }
    
  3. remove the dispose method call. You must not destroy your graphic object.

编辑:

  1. this is a problem:

    foo.setBounds(20, 100, 300, 50);
    

    you are trying to explicitly set the bounds of your JButton. You shouldn't do that. If you are using a LayoutManager it probably ignore this directive. If you are using a null layout this could be a problem too.


我认为布局问题与LayoutManager有关。您是否指定了LayoutManager?如果是,哪一个,何处以及如何指定?请发布相关代码。 - Heisenbug
1
@Heisenbug,请将paint()方法(以及两个)更改为paintComponent() :-) +1 - mKorbel
不是“不需要销毁”,而是“不能销毁” :) - kleopatra
好的,问题已经解决了。问题确实是空布局。现在将opaque设置为false和透明背景颜色后,它可以完美地工作了。谢谢! - Simiil

4

几个问题

  • 覆盖 paint 方法是错误的,应该覆盖 paintComponent 方法
  • 按钮具有完全透明的背景,但对不透明返回 true,因此欺骗了绘制机制
  • 将作为参数传递的 Graphics 销毁是错误的

可行代码(编辑:意外删除了透明颜色设置行,已修复)

public TestPanel(){
    JButton foo = new JButton("test");
    foo.setBackground(new Color(0, 0, 0, 0));
    foo.setOpaque(false);
    foo.setBorder(BorderFactory.createLineBorder(Color.RED));
    this.add(foo);
}

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.drawImage(ImageFactory.getImg(), 0, 0, null); //get a BufferedImage
   //   g2.dispose();
}

正如其他人已经指出的一样:在Swing/AWT中,布局管理器是必需的——不使用它们会使UI代码变得脆弱且难以维护。


0

setBound() 只有在将布局设置为 null 时才有效。您的代码没有这样的说明。 现在,JPanel 的默认布局管理器是 FlowLayout。默认情况下,此布局管理器将按从左到右,从上到下的顺序排列组件。

现在,为了使您的代码按预期工作,请在构造函数中添加此行:setLayout(null)。 但请记住,将布局设置为 null 是非常不好的做法。 此外,Heisenbug 提到的要点非常值得注意。请尽量遵循它们。


-1 "..只有在将布局设置为空时,它才能起作用。" 然后其他所有内容都会开始失败。使用布局 - Andrew Thompson
@Andrew:谢谢你的指点。我想表达的是“如果布局为空,setBound()将会生效”。现在同意了吗? :) - Mohayemin
把布局设置为 null 是一个不好的想法,这个事实并没有改变。现在同意了吗? - Andrew Thompson
@Andrew:哦,我误解了你的第一条评论。我在我的答案中也提到了这是一个非常糟糕的想法:“但请记住,将布局设置为null是一个非常糟糕的做法”。我只是想清楚为什么代码没有按预期工作。即使我推荐了Heisenbug的解决方案,后来也被接受了。 - Mohayemin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接