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.
Related
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.
I want to make a transparent background jTextArea.
I try to setBackground(new color(0,0,0,0));
jTextField is Working, jTextArea didn't working.
like this code.
// Not working.. Just remains gray.
jScrollPane1.setOpaque(false);
jScrollPane1.setBackground(new Color(0,0,0,0));
jTextArea1.setOpaque(false);
jTextArea1.setBackground(new Color(0,0,0,0));
// Working.. As it wants to be transparent.
jTextField1.setOpaque(false);
jTextField1.setBackground(new Color(0,0,0,0));
How can I jTextArea transparent background?
Thanks & Regards.
A JScrollPane is a composed component, it controls/contains a JViewport which is the component that does the drawings. See API:
A common operation to want to do is to set the background color that
will be used if the main viewport view is smaller than the viewport,
or is not opaque. This can be accomplished by setting the background
color of the viewport, via scrollPane.getViewport().setBackground().
The reason for setting the color of the viewport and not the
scrollpane is that by default JViewport is opaque which, among other
things, means it will completely fill in its background using its
background color. Therefore when JScrollPane draws its background the
viewport will usually draw over it.
So you should change the opaque and color properties of the JViewportas well. You can access it with jScrollPane1.getViewport().
The following worked for me.
JTextArea textArea = new JTextArea();
textArea.setOpaque(false);
textArea.setBackground(new Color(red, green, blue, alpha));
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.getViewport().setOpaque(false);
scrollPane.setOpaque(false);
This is example include 50% transparent
JTextArea textArea = new JTextArea();
textArea.setOpaque(false);
JScrollPane scrollPane = new JScrollPane(textArea) {
#Override
protected void paintComponent(Graphics g) {
try {
Composite composite = ((Graphics2D)g).getComposite();
((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
((Graphics2D)g).setComposite(composite);
paintChildren(g);
}
catch(IndexOutOfBoundsException e) {
super.paintComponent(g);
}
}
};
scrollPane.getViewport().setOpaque(false);
scrollPane.setOpaque(false);
edit sorry for the bug. This is work.
I've been using Swing for a long time and starting to get into JavaFX. I'm having trouble figuring out how to create a resizable painting area.
What I'd like is the equivalent to the Swing code:
JPanel parent = new JPanel(new BorderLayout());
JPanel drawArea = new JPanel(){
protected void paintComponent(Graphics g)
{
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.red);
g.drawLine(0, 0, getWidth(), getHeight());
g.drawLine(getWidth(), 0, 0, getHeight());
}
};
parent.add(drawArea, BorderLayout.CENTER);
This will nicely scale to fit the parent container whenever you change its size.
I'm trying to do the same in JavaFX using a BorderPane for the parent and a Canvas for the inner control, based on the code here:
http://www.javacodegeeks.com/2014/04/javafx-tip-1-resizable-canvas.html
This works by setting the canvas to the dimensions of the parent component whenever they change - however, this prevents the canvas from shrinking when the the parent ought to shrink since the parent size now includes its child canvas size. So the only way this example with work is if my canvas uses the stage directly as a parent. It also seems like a lot of work to set this up.
Is there any way to get a simple JPanel-like component that will automatically fit its parent and let me catch a resize event so I can repaint it?
After I created a window, which should be completely black, there are white colors at the right and bottom edges. What is it that I may be doing wrong ?
this is the constructor where I do initialisation of window :-
public Panel()
{
Thread t = new Thread(this);
addKeyListener(this);
setFocusable(true);
this.setPreferredSize(new Dimension(gameWidth, gameHeight));
JFrame f = new JFrame("AlienBusters");
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
t.start();
}
this is the paint method where I made the window black :-
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, gameWidth, gameHeight);
}
Five things...
Calling setResizable after pack, not a good idea, setResizable can change the frame border size, which affects the available content size...
Using KeyListener, seriously, see How to Use Key Bindings and save youreself the head ache...
Relying on magic numbers instead of imperical values, g.fillRect(0, 0, gameWidth, gameHeight); should be g.fillRect(0, 0, getWidth(), getHeight()); or better, simply use setBackground(Color.BLACK) and get it for free via super.paintComponent...and paintComponent should be protected ;)
Calling setPreferredSize. This means that the size could be changed, which, probably, isn't what you really want. Instead, override getPreferredSize instead. See Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? for more details
Constructing a frame within the constructor of a component, the component shouldn't care how it's going to be displayed, it should just focus on it's job.
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.