Setopaque(True/False); Java

setOpaque(true/false); Java

The short answer to your question is that "opaque" is defined in English as completely non-transparent. Therefore an opaque component is one which paints its entire rectangle, and every pixel is not at all translucent to any degree.

However, the Swing component opacity API is one of those mis-designed and therefore often mis-used APIs.

What's important to understand is that isOpaque is a contract between the Swing system and a particular component. If it returns true, the component guarantees to non-translucently paint every pixel of its rectangular area. This API should have been abstract to force all component writers to consider it. The isOpaque API is used by Swing's painting system to determine whether the area covered by a given component must be painted for components which overlap it and which are behind it, including the component's container and ancestors. If a component returns true to this API, the Swing system may optimize painting to not paint anything in that area until invoking the specific component's paint method.

Because of contractual implication of isOpaque, the API setOpaque should not exist, since it is actually incorrect for anything external to call setOpaque since, in turn, the external thing can't know whether the component in question will (or even can) honor it. Instead, isOpaque should have been overridden by each concrete component to return whether it actually is, in fact, opaque given its current properties.

Because the setOpaque API does exist, many components have mis-implemented it (quite understandably) to drive whether or not they will paint their "background" (for example JLabel and JPanel filling with their background color). The effect of this is to create an impression with users of the API to think that setOpaque drives whether or not that background should paint, but it doesn't.

Furthermore, if, say, you wish to paint a JLabel with a translucent background you need to set a background color with an alpha value, and do setOpaque(true), but it's not actually opaque - it's translucent; the components behind it still need to paint in order for the component to render properly.

This problem was exposed in a significant way with the Java 6's new Nimbus Look & Feel. There are numerous bug reports regarding transparent components filed against Nimbus (see stack overflow question Java Nimbus LAF with transparent text fields). The response of the Nimbus development team is this:

This is a problem [in] the orginal design of Swing and how it has been confusing for years. The issue is setOpaque(false) has had a side effect in [existing] LAFs which is that of hiding the background which is not really what it is [meant] for. It is [meant] to say that the component may have transparent parts and [Swing] should paint the parent component behind it.

So, in summary, you should not use setOpaque. If you do use it, bear in mind that the combination of some Look & Feels and some components may do "surprising" things. And, in the end, there is actually no right answer.

How to use setOpaque(true/false) in an if statement

The if statement works fine, although better to use if (!label.isOpaque()) {

You need to redraw the GUI component via repaint() for the background to show:

    button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!label.isOpaque()) {
label.setOpaque(true);
label.revalidate();
label.repaint();
}
}
});

setOpaque is true, but JPanel won't change the background color

Inside your MainDishPanel you need to set the background color for the JCheckBox to white, or you can just setOpaque to false on your JCheckBox

import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JCheckBox;
import javax.swing.JPanel;

public class MainDishPanel extends JPanel {

JCheckBox box1 = new JCheckBox("Hamburger 5 dollars"), box2 = new JCheckBox("Pizza 5 dollars"),
box3 = new JCheckBox("French Hot dog 5 dollars");

MainDishPanel() {
setOpaque(true);
setBackground(Color.WHITE);
setLayout(new GridLayout(3, 1));

box1.setBackground(Color.WHITE); // or box1.setOpaque(false);
box2.setBackground(Color.WHITE);
box3.setBackground(Color.WHITE);

add(box1);
add(box2);
add(box3);
setVisible(true);
}
}

Does using setOpaque(false) impact painting performance on Swing JComponents?

Yes it does add extra work when painting but I doubt you would have to worry about it.

Basically, whenever you repaint a component that is transparent you need to go up the chain to find a parent that is not opaque and then paint that component first, before painting the child component.

So the bottom line is don't worry about it. If you have a reason to use transparency then use it. If you don't have a reason then you shouldn't be using it.

You may want to check out Background With Transparency. It goes into a little more detail on what the opaque property means and how it affects painting and the problem you will have if you do use a transparent background.

jLabel.setOpaque(true) does not work

Works like a charm for me:

import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class TestJLabel {

protected void initUI() {
JFrame frame = new JFrame(TestJLabel.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel key = new JLabel("Some opaque label with a yellow background.");
key.setBackground(Color.YELLOW);
key.setOpaque(true);
frame.add(key);
frame.pack();
frame.setVisible(true);

}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
new TestJLabel().initUI();
}
});
}

}

Resulting in:

Sample Image

java setOpaque(false) makes hovering slow

The best way to do this is probably to use a CardLayout which is already set up for good behavior.

Here's an MCVE.

mouseover panels MCVE screenshot

package mcve;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.net.*;
import java.io.*;

public class MouseoverPanels {
public static void main(String[] args) {
SwingUtilities.invokeLater(MouseoverPanels::new);
}

MouseoverPanels() {
JFrame frame = new JFrame("Mouseover Panels");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel buttons = new JPanel();
buttons.setBackground(Color.WHITE);

buttons.add(new MouseoverPanel("Queen", QUEEN_IMG));
buttons.add(new MouseoverPanel("King", KING_IMG));
buttons.add(new MouseoverPanel("Rook", ROOK_IMG));
buttons.add(new MouseoverPanel("Knight", KNIGHT_IMG));
buttons.add(new MouseoverPanel("Pawn", PAWN_IMG));

frame.setContentPane(buttons);

frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

class MouseoverPanel extends JPanel {
static final String BUTTON_KEY = "BUTTON";
static final String ICON_KEY = "ICON";

final CardLayout layout = new CardLayout();

MouseoverPanel(String text, Image img) {
setLayout(layout);
setOpaque(false);

JButton button = new JButton(text);
button.setBorderPainted(false);
button.setOpaque(false);

JLabel icon = new JLabel(new ImageIcon(img));
icon.setOpaque(false);

add(button, BUTTON_KEY);
add(icon, ICON_KEY);

layout.show(this, ICON_KEY);

MouseoverListener ml = new MouseoverListener();

addMouseListener(ml);
button.addMouseListener(ml);
icon.addMouseListener(ml);
}

class MouseoverListener extends MouseAdapter {
@Override
public void mouseEntered(MouseEvent e) {
recomputeView(e);
}
@Override
public void mouseExited(MouseEvent e) {
recomputeView(e);
}
void recomputeView(MouseEvent e) {
Component comp = e.getComponent();
Point loc = SwingUtilities.convertPoint(comp, e.getPoint(), MouseoverPanel.this);
String key = contains(loc) ? BUTTON_KEY : ICON_KEY;
layout.show(MouseoverPanel.this, key);
}
}
}

static final Image QUEEN_IMG,
KING_IMG,
ROOK_IMG,
KNIGHT_IMG,
PAWN_IMG;
static {
try {
// source for sprite sheet: https://stackoverflow.com/a/19209651/2891664
BufferedImage sprites = ImageIO.read(new URL("https://i.stack.imgur.com/memI0.png"));
int n = 64;
QUEEN_IMG = sprites.getSubimage(0 * n, 0, n, n);
KING_IMG = sprites.getSubimage(1 * n, 0, n, n);
ROOK_IMG = sprites.getSubimage(2 * n, 0, n, n);
KNIGHT_IMG = sprites.getSubimage(3 * n, 0, n, n);
PAWN_IMG = sprites.getSubimage(4 * n, 0, n, n);
} catch (IOException x) {
throw new UncheckedIOException(x);
}
}
}

I think the performance hit you're seeing is probably because calling setVisible may cause revalidate to be called, which invokes the layout manager, but it's hard to say for sure, especially without a proper MCVE (see).


Here's another example which does this via custom painting only. An approach like this should be easier to animate. This might not normally be feasible, except that the only "real" component we're dealing with here is the text itself.

example with only custom painting

package mcve;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.net.*;
import java.io.*;
import java.util.*;

public class MouseoverPanels2 {
public static void main(String[] args) {
SwingUtilities.invokeLater(MouseoverPanels2::new);
}

MouseoverPanels2() {
JFrame frame = new JFrame("Mouseover Panels");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel buttons = new JPanel();
buttons.setBackground(Color.WHITE);

buttons.add(new MouseoverLabel("Queen", QUEEN_IMG, QUEEN_IMG_H));
buttons.add(new MouseoverLabel("King", KING_IMG, KING_IMG_H));
buttons.add(new MouseoverLabel("Rook", ROOK_IMG, ROOK_IMG_H));
buttons.add(new MouseoverLabel("Knight", KNIGHT_IMG, KNIGHT_IMG_H));
buttons.add(new MouseoverLabel("Pawn", PAWN_IMG, PAWN_IMG_H));

frame.setContentPane(buttons);

frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

class MouseoverLabel extends JComponent {
final JLabel label;
final Image image, hover;

final Dimension imageMaxSize;

boolean isHovering = false;

MouseoverLabel(String text, Image image, Image hover) {
setLayout(new BorderLayout());
setOpaque(false);

this.image = Objects.requireNonNull(image);
this.hover = Objects.requireNonNull(hover);

imageMaxSize =
new Dimension(Math.max(image.getWidth(this), hover.getWidth(this)),
Math.max(image.getHeight(this), hover.getHeight(this)));

label = new JLabel(text);
label.setForeground(Color.RED);
label.setOpaque(false);
label.setHorizontalAlignment(JLabel.CENTER);
add(label, BorderLayout.CENTER);

MouseoverListener ml = new MouseoverListener();

addMouseListener(ml);
label.addMouseListener(ml);
}

private Dimension getMax(Dimension size) {
size.width = Math.max(size.width, imageMaxSize.width);
size.height = Math.max(size.height, imageMaxSize.height);
return size;
}

@Override
public Dimension getPreferredSize() {
return getMax(super.getPreferredSize());
}
@Override
public Dimension getMinimumSize() {
return getMax(super.getMinimumSize());
}
@Override
public Dimension getMaximumSize() {
return getMax(super.getMaximumSize());
}

@Override
protected void paintChildren(Graphics g) {
// Note that the label is always "visible",
// so it will e.g. receive mouse events even
// while we aren't painting it.
// If the label needs to receive, say, mouse
// clicks, then you need to check isHovering
// in the mouse click listener.
// If the label is a JButton, then you could
// call button.setEnabled(isHovering) in the
// MouseoverListener.
if (isHovering) {
paintImage(g, hover);
super.paintChildren(g);
} else {
paintImage(g, image);
}
}

private void paintImage(Graphics g, Image image) {
int w = image.getWidth(this);
int h = image.getHeight(this);
int x = (getWidth() - w) / 2;
int y = (getHeight() - h) / 2;
g.drawImage(image, x, y, w, h, this);
}

class MouseoverListener extends MouseAdapter {
@Override
public void mouseEntered(MouseEvent e) {
recomputeView(e);
}
@Override
public void mouseExited(MouseEvent e) {
recomputeView(e);
}
void recomputeView(MouseEvent e) {
Component comp = e.getComponent();
Point loc = SwingUtilities.convertPoint(comp, e.getPoint(), MouseoverLabel.this);
isHovering = contains(loc);
repaint();
}
}
}

static final Image QUEEN_IMG,
QUEEN_IMG_H,
KING_IMG,
KING_IMG_H,
ROOK_IMG,
ROOK_IMG_H,
KNIGHT_IMG,
KNIGHT_IMG_H,
PAWN_IMG,
PAWN_IMG_H;
static {
try {
// source for sprite sheet: https://stackoverflow.com/a/19209651/2891664
BufferedImage sprites = ImageIO.read(new URL("https://i.stack.imgur.com/memI0.png"));
int n = 64;
QUEEN_IMG = sprites.getSubimage(0 * n, 0, n, n);
QUEEN_IMG_H = sprites.getSubimage(0 * n, n, n, n);
KING_IMG = sprites.getSubimage(1 * n, 0, n, n);
KING_IMG_H = sprites.getSubimage(1 * n, n, n, n);
ROOK_IMG = sprites.getSubimage(2 * n, 0, n, n);
ROOK_IMG_H = sprites.getSubimage(2 * n, n, n, n);
KNIGHT_IMG = sprites.getSubimage(3 * n, 0, n, n);
KNIGHT_IMG_H = sprites.getSubimage(3 * n, n, n, n);
PAWN_IMG = sprites.getSubimage(4 * n, 0, n, n);
PAWN_IMG_H = sprites.getSubimage(4 * n, n, n, n);
} catch (IOException x) {
throw new UncheckedIOException(x);
}
}
}

My JRadioButton change look with setOpaque(false)

You can create a class which extends the JRadioButton and add all the properties inside the class:

        setOpaque(false);
setContentAreaFilled(false);
setBorderPainted(false);
setForeground(Color.white);
setBackground(Color.BLACK);

Sample output:

picture

Code:

public class Sample extends JPanel {

public Sample() {
super(new BorderLayout());
setBackground(Color.BLACK);

TransparentButton testButton = new TransparentButton("hello");
testButton.setSelected(true);

add(testButton, BorderLayout.LINE_START);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}

private static void createAndShowGUI() {
JFrame frame = new JFrame("Hello Word demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new Sample();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}

class TransparentButton extends JRadioButton {
public TransparentButton(String string) {
super(string);
setOpaque(false);
setContentAreaFilled(false);
setBorderPainted(false);
setForeground(Color.white);
setBackground(Color.BLACK);
}
}

}


Related Topics



Leave a reply



Submit