Java - set opacity in JPanel - java

Let's say I want to make the opacity of a JPanel %20 viewable? I don't mean setOpaque (draw or not draw) or setVisible (show or hide)... I mean make it see-through JPanel.. you know?
Is this possible?

You need to set the "alpha" value for your Color object:
panel.setBackground( new Color(r, g, b, a) );
However, this will still not work properly as Swing doesn't paint transparent background properly so you need to do custom painting. The basic logic is:
JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
panel.setOpaque(false); // background of parent will be painted first
panel.setBackground( new Color(255, 0, 0, 20) );
frame.add(panel);
Check out Backgrounds With Transparency for more information on the actual painting problem and why the above code solves the problem. The link also contains a custom reusable class that does the above painting for you.

Use the alpha attribute for the color.
For instance:
panel.setBackground(new Color(0,0,0,64));
Will create a black color, with 64 of alpha ( transparency )
Resulting in this:
Here's the code
package test;
import javax.swing.*;
import java.awt.Color;
import java.awt.BorderLayout;
public class See {
public static void main( String [] args ){
JFrame frame = new JFrame();
frame.setBackground( Color.orange );
frame.add( new JPanel(){{
add( new JLabel("Center"));
setBackground(new Color(0,0,0,64));
}} , BorderLayout.CENTER );
frame.add( new JLabel("North"), BorderLayout.NORTH);
frame.add( new JLabel("South"), BorderLayout.SOUTH);
frame.pack();
frame.setVisible( true );
}
}
With out it it looks like this:
setBackground( new Color( 0,0,0 ) ); // or setBackground( Color.black );

AWTUtilities.setWindowOpacity(aWindow, aFloat);
Where aWindow is the Swing component, and aFloat is the opacity.

It doesn't work so well on windows 7.
panel.setBackground( new Color(r, g, b, a) );
the alpha channel just lightens the color.
when an element is updated on a color with an alpha channel, the computer gets confused and resets the background of the updated element without an alpha. I'm going to try
AWTUtilities.setWindowOpacity(aWindow, aFloat);
next.

If you have a custom panel and want the whole thing to be semi-transparent, I advise you to do override its method paintComponent like this :
#Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D g2d = (Graphics2D) graphics;
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
}

How about override the paintComponent method of the JPanel(in order to do this you have to sub class the JPanel itself and implement your own paintComponent method) inside the paintComponent you can retrieve a buffered image of the component, from there you can manipulate the alpha of the buffered image and paint it back to the JPanel. I have red this long time ago. Still looking for the code.

Related

JComponent disappear when resizing?

Hi i am a beginner in java, here I have my program, however, when I try resizing the panel my text just disappears?
Moreover, how can i draw a thick green line under my text which will stay under the text even when resizing, I am very clueless?
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
public class Groovy
{
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame= new JFrame("Shearing Word Demo");
frame.setResizable(true);
frame.setSize(new Dimension(500,250));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Toolkit it=Toolkit.getDefaultToolkit();
Dimension d=it.getScreenSize();
int w=frame.getWidth(), h=frame.getHeight();
frame.setLocation(d.width/2-w/2, d.height/2-h/2);
frame.add(new JComponent(){
#Override public void paintComponent(Graphics g){
Graphics2D g2=(Graphics2D) g;
g2.setColor(Color.magenta);
g2.setFont(new Font("Comic Sans MS",Font.BOLD,44));
g2.drawString("Feeling Groovy!", 110,125 );
}
});
frame.setVisible(true);
}
});
}
}
how can i draw a thick green line under my text which will stay under the text even when resizing, I
If you do custom painting then the basic steps you need to follow would be something like:
get the FontMetrics of the Graphics object using the getFonTMetrics() method
get the rectangle of text using the getStringBounds(...) method
use the setStroke(...) method of the Graphics2D object to set the thickness of the line to paint
use the drawLine(...) method Graphics2D object to paint the line based on the location of the text and the information of the Rectangle from the string bounds
An easier solution for displaying text is to use a JLabel. Then you can set the Border of the label. Read the section from the Swing tutorial on How to Use Borders for more information.
Note when doing custom painting with a JComponent you are also responsible for clearing the background of the component. So the first painting in the method should be:
g2.setColor( getBackground() );
g2.fillRect(0, 0, getWidth(), getHeight());
Most people use a JPanel for custom painting then you can just use:
super.paintComponent(g);
to make sure the background is cleared.

How add a jtextfield to a jpanel that has paint component?

I'm making a game and I want to add a JTextField to a JPanel that has Paint Component. I repaint the JPanel every 16 milliseconds.
I add() the textfield to the panel but it show up only for a single frame when i click on it.
Then I tried to repaint() the textfield but now it is flashing.
public class Screen extends JPanel {
public Screen() {
JTextField txt = new JTextField();
txt.setBounds(10, 10, 300, 50);
this.add(txt);
}
#Override
public void paint(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
g2D.setColor(Color.BLACK);
g2D.fillRect(0, 0, this.getWidth(), this.getHeight());
g2D.setColor(Color.WHITE);
g2D.fillRect(0, 0, this.getWidth(), 20);
txt.repaint();
}
}
I want to show the textfield on the top of the panel
JTextField txt = new JTextField();
When you create a JTextField you should use code like:
JTextField txt = new JTextField(10);
Now the text field can calculate its own preferred size.
//txt.setBounds(10, 10, 300, 50);
Don't use setBounds() to give a component a size. Again each Swing component is responsible for determining its own preferred size. Then the layout manager will set the size/location of the component on the panel.
//public void paint(Graphics g) {
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// add custom painting here
}
Don't override paint(). Custom painting is done by overriding the paintComponent() method. And the first statement in the method should be super.paintComopnent(g)
//g2D.setColor(Color.BLACK);
//g2D.fillRect(0, 0, this.getWidth(), this.getHeight());
Don't paint the background of the panel. That is the job of the panel and that is why you need to super.paintComponent(), to make sure the background is painted.
Then in the constructor of your JPanel class you simply use setBackground( Color.BLACK )
//txt.repaint();
Don't ever invoke repaint() on any component in a painting method.
Read the section from the Swing tutorial on Custom Painting for working examples to get you started. Use the demo code as the starting point for you program. Then you simply add a JTextField to the panel, so it will be a single line of code that is needed to display the text field.
It seems like you want to have a JTextField on a black panel. You don't need to set the colour of the panel every time in paint() method. Instead add this to the constructor:
public Screen() {
setOpaque(true);
setBackground(Color.BLACK);
//...
}
and remove paint() method.
Also, if you want to use absolute positioning with setBounds() method then you should set the layout to null setLayout(null) in constructor. If you use absolute positioning you will also need to specify the size of the panel explicitly. However, I would still suggest you use a layout manager that takes care of panel sizing as well.
See this post for more information about absolute positioning.

Issue on label and panel's transparency

Here there is my frame:
As you can see, there are some components (JLabel, JPanel, JTable, JScrollPane) on which I called the metod setBackgroundColor(new Color(r, g, b, a)).
At each update of the frame, these components show new "shadows" of other components of the frame.
How can I eliminate these "shadows"?
At each update of the frame, these components show new "shadows" of other components of the frame
Swing does not support semi transparent colors correctly since Swing expects components to be either fully opaque or fully transparent.
Therefore you need to make sure the parent component is painted first to reset the background and then manually paint the background of the component:
JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
panel.setOpaque(false); // background of parent will be painted first
panel.setBackground( new Color(255, 0, 0, 20) );
frame.add(panel);
See Backgrounds With Transparency for more information and a reusable class that will do this painting for you.

I'm trying to draw shapes in a JPanel extending a JComponent and then putting the component inside the panel but it won't work

I'm trying to draw shapes in a JPanel extending a JComponent and then putting the component inside the panel but it won't work. I've got a JFrame (500, 500) and I need the right half of it to have things drown inside. I'm clearly doing something wrong though!
This is the code I've used:
public class Componente extends JComponent{
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Shape linea = new Rectangle2D.Float(50, 50, 50, 50);
Shape cerchio = new Ellipse2D.Double(100, 100, 50, 50);
g2.setPaint(Color.BLUE);
g2.draw(linea);
g2.draw(cerchio);
}
}
public class PannelloDx extends JPanel{
PannelloDx(){
this.setBackground(Color.CYAN);
this.setSize(Esercitazione_Berni1703.finestra.getWidth()/2, Esercitazione_Berni1703.finestra.getHeight());
this.setLocation(Esercitazione_Berni1703.finestra.getWidth()/2, 0);
this.add(new Componente());
}
}
Now, the output shows the Cyan panel into the JFrame in the right half as it's supposed to. It won't show anything though!
By default a JPanel uses a FlowLayout and a FlowLayout respects the size of the component added to it. Your custom component has a preferred size of (0, 0) so there is nothing to paint.
You need to override the getPreferredSize() method of your custom panel to return the appropriate size.
Read the section from the Swing tutorial on Custom Painting for more information and examples. Check out the rest of the tutorial for Swing basics as well.

Scrolls not appears

I want add JScrolpane to JPanel, but that not appears. In JLabel works fine and its very easy. I am using JPanel beacuse I'll add some image proccessing stuff to my program. There is my code:
public void draw(){
panel=new JPanel(){
protected void paintComponent(Graphics g){
Graphics g2 = g.create();
g2.drawImage(image, 0, 0, this);
g2.dispose();
}
};
panel.setBorder(BorderFactory.createEtchedBorder());
panel.setPreferredSize(new Dimension(400, 330));
s=new JScrollPane(panel);
s.setPreferredSize(new Dimension(400,285));
this.getContentPane().add(s,BorderLayout.CENTER);
add(panel);
revalidate();
repaint();
}
s=new JScrollPane(panel);
s.setPreferredSize(new Dimension(400,285));
this.getContentPane().add(s,BorderLayout.CENTER);
add(panel); // ****** ????????????
revalidate();
repaint();
}
You're adding the JPanel to the GUI not the JScrollPane, so you really shouldn't expect to see any scrollpanes if they've not been added anywhere.
Solution: Add your JScrollPane, s, that holds the JPanel to the GUI, not JPanel itself.
You dont honor the paint chain, call super.paintComponent(g) as first call in overridden paintComponent method. i.e
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
//draw here
}
or visual artifacts may occur.
Also note the #Override annotation which should be used with overridden methods in order to gain the advantage of compiler checking that we overrode the method correctly.
There is no need for getContentPane().add(..) simply call add on JFrame instance as add(..) along with remove(..) and setLayout(..) have been forward to the JFrames contentPane
Also not a good idea to go extending JFrame for nor reason, simply create an instance and use that i.e:
JFrame frame=new JFrame("Title here");
...
frame.add(..);
...
frame.pack();
frame.visible(true);
Also draw onto the Graphics object passed into paintComponent g dont go creating your own in paintComponent. Unless of course you're doing if for the reason #HFOE mentioned in below comment :).
No need for this parameter in drawImage(..) unless your JPanel implements on ImageObserver or the image may not be fully loaded when painting occurs. Simply use null.
And just for the cherry on top use some Graphics2D and RenderHints as seen here. This will allow for a better quality image to be drawn and text.
I got it! The main reason for me was no-layout manager and no-declarated size of this. There is my code:
public void draw(){
panel=new JPanel(new BorderLayout()){
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img, 0, 0, null);
}
};
panel.setBounds(0, 0, img.getWidth(), img.getHeight());
panel.setPreferredSize(new Dimension(img.getWidth(),obraz.getHeight()));
JScrollPane scrolls=new JScrollPane(panel,ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
add(scrolls);
validate();
repaint();
}
But if someone will want copy this code in the future, there is one thing to be known- a size of Jpanel isn't refreshing (it's always one size of first opened image), but I have scrolsl and I am satisfied for now ;). Thanks a lot for everyone.

Categories

Resources