Make JPanel background transparent without text overlapping - java

I am making something that resembles a subtitle player that will go over a video.
I would like to make the background transparent so that the box that the text is in will not interfere with the movie/TV show playing behind it. I have tried 2 ways to do this and each way results in the same problem. The text does not disappear when the next sentence appears. If the background is a color (Eg: Color.red), then this works fine. After a certain time, I call text.setText("next sentence"), but this does not work with a transparent background. The relevant code is as follows. text is a JTextField
I should mention the video is not in this program. This program is ONLY subtitles.
First way:
text.setBackground(new Color(0,0,0,0));
Second way: (using a transparent image)
Graphics c = myPicture.getGraphics();
text.paintAll(c);
I update the text like this.
Thread.sleep(Graphix.subtitles.get(counter).getStart());
text.setText(Graphix.subtitles.get(counter).getText());
This also makes it overlap.
text.setForeground(Color.blue);
text.setBackground(new Color(0,0,0,0));
text.setOpaque(false);
The relevant code from Main is as follows.
final JFrame JFwindow = new JFrame("Subtitles");
JFwindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFwindow.getContentPane().add(new Subtitles());
JFwindow.setSize(1300, 150);
JFwindow.setUndecorated(true);
JFwindow.setBackground(new Color(0,0,0,0f));
JFwindow.pack();
JFwindow.setVisible(true);

Transparency is achieved by calling JPanel#setOpaque and passing it false.
You should NEVER be calling getGraphics. getGraphics and return null and is, at best, only as snap shot. Once the RepaintManager starts a new paint cycle, the results of painting to it will be overridden.
Using a tarnsparent color will only confuse the RepaintManager as it won't know that it needs to paint under the component
Sleeping within the Event Dispatching Thread (EDT) will stop Swing from performing any updates (as well as process any events). Instead I'd recommend using a javax.swing.Timer. See Concurrency in Swing for more details.
If you're using the VLC bindings, then it can't be achieved
Don't forget to make all the parent containers that the sub titles are contained in transparent as well

Related

Java - Graphical glitches on background repaint

I'm making a microwave simulation program and having an annoying problem. I want the microwaves viewing window to change color on a button press, to visualize that the microwave is on. However, because I also have a jlabel with an icon (food image) in the background, I need the background to be semi transparent. I've accomplished this adding an alpha value to the jPanel (cookingWindow).
It starts like this
So what I've basically done is set an actionEvent to the start button with the following code.
cookingWindow.setBackground(new Color (250,234,1, 150));
cookingWindow.repaint();
This works, except this happens
When I minimise and maximise the window, everything goes back to place. But obviously, it would be preferable if you didn't have to minimise the window. Any ideas on how to stop this visual bug?
See Backgrounds With Transparency for an explanation of the problem and a couple of solutions.
Basically the problem is how the Swing opaque property handles transparent backgrounds (it doesn't).
Revalidating and repainting the jFrame seems to do fix everything up. I was previously only repainting the jPanel.

Painting JPanel to printable when it's not on screen

I am using JPanels to simulate a print preview and just printing the content panel, however I have ran into a problem whereby if I try to print multiple panels that are essentially the same document, only the the one currently being displayed on screen will print.
Is there a way I can force the JPanel to repaint even if it is not currently on screen?
I have tried:
Disabling double buffering via:
JComponent.setDoubleBuffered()
RepaintManager.setDoubleBufferingEnabled()
Painting Twice
Painting through paint()
Painting through repaint()
Painting through print()
I couldn't get it to paint off screen and I felt like I was wasting my time battling the Swing API so I just cheated and made the panels display on screen as they are being printed; now I have a new "feature" that shows you the page being printed.
I'll leave the question open incase someone knows how to do this as I would prefer not to shove all the pages in the user's face.
Update
Turns out the problem was with components that had extended java.awt.Container, the Swing components must override certain AWT methods that deal with this sort of rendering.

How can I change colors of components when the mouse is pressed in a JFrame in Java?

I am coding a piano in java using rectangles from the java.awt.graphics library. I am using a mouselistener to play the sound of each individual key when the mouse clicks a certain area on the JFrame.
How would I add a shape to the panel upon clicking, repaint, then repaint the keyboard back over top when the user releases the mouse?
Consider adding JLabels to a JPanel that uses GridLayout. Give each JLabel a MouseListener and either swap ImageIcons on mousePress/mouseRelease or change the JLabel's background with press and release. If you go the latter route, you'll want to make sure that the JLabels opaque property is set to true so that the background colors show.
Then for the black keys, you can add the above JPanel to a JLayeredPane and on top of this, add another JPanel that holds the black keys that function in the same way.
Also, you'll want to take care to "play" any notes in a background thread, such as can be obtained with a SwingWorker so as not to tie up the Swing event thread and completely freeze your program.
Consider solution: source
It might not be exactly what you're after, but it might give you an idea of how to approach your problem. It took me a long time to figure out how to use JLayeredPane without setting a null layout, but in the end this was the best I could come up with. Also, assumed some naming conventions for your sound files. :p

JAVA: How to use paint() method to update the previously drawn object?

How to use paint() such that when repaint() is called the previously drawn object should not get deleted when drawing the new object. That is the drawing area must get UPDATED only and not REDRAWN.
In my code when one of many button is clicked, some aplhabet get displayed. I want to have functionality such that when other buttons are clicked the previously drawn alhabets must be present.Take is as if a string of alphabets getting created as the buttons are clicked.
Im using Java Swing for coding.
Some piece of my code:
if(source == btnAlpha[i] )
bollyDraw.repaint(); //bollydraw is an object of a JPanel extended class having implemented the paintComponent(Graphics g) method
In the paint() method:
if (word[i] == key) {
g.drawChars(word, i, 1, x, y);
}
In a project I worked on I used a List to store the objects that were to be drawn as a member of a class. Then as the user interacted with my UI I added/removed items from this list. The JPanel that rendered the items painted the items that were in this list. It's helps separate the UI logic from the paint logic as you can determine what goes into the paint list when an event is fired rather than in the paint method ( which should be as clean as possible ). However this will force you to repaint everything on every paint call.
In conjunction with this Kim's RepaintManager is a great way to limit what gets repainted. It is region based so there is some complexity in determining what region of the screen has changed. If you have the time it is better to use something like this otherwise it could be difficult to add this functionality down the road.
Your app must be prepared to re-paint anything it has painted. From your description, I'm afraid that means you have to keep track of everything you've painted.
The Swing behavior is partially dictated by the underlying window manager and graphical system, which at any time may chose to paint over an area where your application is present. You can override update() to control repaints initiated by your own app, and might be able to improve performance by implementing your own RepaintManager.
This tutorial explains Swing painting in more detail: http://java.sun.com/products/jfc/tsc/articles/painting/
Custom Painting Approaches shows a couple of ways to do this depending on your exact requirement.

PaintComponent Takes a Long Time, Ties up the Swing Event Dispatch Thread

I've customized a JPanel that displays a large, complicated diagram. Depending on the size of the data, it can take a few minutes to render in paintComponent(). I'm looking for a strategy to:
draw the component without tying up the event dispatch thread.
draw something in the JPanel to let the user know the image is being rendered.
periodically update another container's label to show the progress
I've researched this a bit, and I'm wondering if the right strategy is to use a SwingWorker to create a background thread and draw to a BufferedImage. Timers would handle the status updates. Class member variables would hold the status.
Am I on the right track?
You need to look into using a SwingWorker. You should do the rendering of the diagram in a separate thread. The SwingWorker will help accomplish that.
To get started with multi-threading in concurrency, sun has a great tutorial that should prove very helpful.
Use background image which is updated by special working thread. Then in JPanel's paintComponent() method just paint this image. The strategy is called double-buffering. You have background and foreground image. If separate thread finish the painting of data then set this image as foreground and foreground load as background. Invalidate JPanel and continue painting on back image if necessary.

Categories