Java Swing - Translucent Components

梦想的初衷 提交于 2019-12-11 01:56:51

问题


I recently asked a question about translucent components causing odd artifacts from seemingly not updating properly. The answer I received caused the artifacts to go away, but at the cost of translucency.

The solution was to- for every translucent component- also call the setOpaque(false) function. This way, Swing knew that it needed to redraw the background behind those components.

However, this came at the cost of the translucency that I was trying to achieve. It caused the components to become transparent instead.

The premise is this: I am designing the GUI for a chat client, and a feature request was to have a background. I successfully got the background working by following a code snippet for extending the JPanel class, but then I wanted the components to allow the background to show. After setting their translucency, remnants of updated components were being displayed where they shouldn't have been. I came here and got my problem solved, but now I've got a new problem. So here we are.

So, here is what I've surmised:

-Calling the setOpaque(false) function for each desired component and NOT setting a translucent color does not achieve what I want.

-Setting a translucent color and NOT calling setOpaque(false) allows the translucent background to show, but causes artifacts, putting me back at square one.

So I need some middle ground between transparent with no artifacts, and translucent with artifacts. Namely, I want a translucent background (not completely transparent) that has no artifacts.

It seems like I'm going to need to override the JFrame to cause it to repaint all its components, regardless of the opacity. Unless there's something I'm missing.. which is why I'm here!

Thanks!

(Here's a link to the original question, with a picture for reference: Java Swing - Translucent Components causing Artifacts)


回答1:


One option would be to override the components and draw the background yourself:

class TranslucentLabel extends JLabel {
    public TranslucentLabel(String text) {
        super(text);
        setOpaque(false);
    }

    @Override
    public void paintComponent(Graphics g) {
        g.setColor(new Color(255, 0, 0, 64));
        Insets insets = getInsets();
        g.fillRect(insets.left, insets.top, 
                getWidth() - insets.left - insets.right, 
                getHeight() - insets.top - insets.bottom);
        super.paintComponent(g);
    }
}

EDIT: Alternatively you could draw the translucent background colour for the child components directly onto the panel, then you would not have to override components:

class YourPanel extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D)g.create();

        // Draw your background image here to g2d.

        g2d.setColor(new Color(255, 0, 0, 64));
        Area area = new Area();
        for (Component component : getComponents()) {
            area.add(new Area(component.getBounds()));
        }
        g2d.fill(area);
        g2d.dispose();
    }
}

There is a disadvantage to this approach. If there is a genuinely transparent part of a component (such as a rounded border), then its entire background will be coloured.



来源:https://stackoverflow.com/questions/4982960/java-swing-translucent-components

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!