Java Swing - Translucent Components causing Artifacts
I'm currently working on a group project for a college course, and I've hit a bit of a stumbling block. The program we have decided to implement is a Peer-to-Peer chat client with a central server for storing and sharing usernames, etc. I've been assigned to do the GUI.
A friend jokingly suggested that I include "a flaming background!" So I decided to do just that, but to have a user-chosen background image. As is, only bits and pieces of the background image would be visible with all the components over top of it, so I decided to try to implement translucency.
This is where my problem lies:
When sending information from the input box to the chat window, or when navigating the friends list, or scrolling the chat window, strange artifacts are left behind. These artifacts are sometimes translucent "ghosts" of the Send button, sometimes part of the menu, or old text. It looks to me like the whole f开发者_如何学编程rame is not getting redrawn properly, but I'm not sure of how that works.
For components that implement JTextComponent, I'm setting their selection color to be a translucent color. For other components, I'm setting the background to be translucent. I have a function, setTranslucency(Component com) that looks at a component, sets its translucency depending on what it is, then sees if it is a container of some sort and sets the translucency of each item recursively.
Now, the way that I've found to fix this problem is to drag the window out of sight (such as minimizing or dragging the window off-screen and back).
So,
1) Is there a way to force the entire window to update like it does when I drag it off of the screen or minimize it?
or,
2) Am I doing it wrong in the first place? If so, how would I fix it?
Here's a picture for reference:
http://i.stack.imgur.com/4J9GJ.png
You need to tell Swing that the components are translucent, so it does also paint the background when repainting the changed components. For this, your components have to return false
from the isOpaque()
method (this can be achieved by setOpaque(false)
when no subclass overwrites isOpaque
to do something else).
With this, it should work without any manual repainting of everything, as the other answers proposed. (I already did this once.)
Edit: The reason for this is that Swing uses an optimized repainting-algorithm, repainting only these components which really need repainting (for example, a JTextField after some input) or components in front of such ones, as long as they are opaque. When a component needing repainting is not opaque (= filling its whole space with non-translucent color), also repainting of the components behind them is necessary.
myComponent.revalidate();
myComponent.repaint();
Not sure if it "force" the redraw, but it ask it to do it when possible.
Try JFrame.repaint()
. That should work. If you want custom designing of your JFrame
then you will have to override paint()
method of JFrame. Additionally, if you want each component to be custom designed you will have to override the paint()
method of each of your GUI component. Couple of things to note:
- You do not have to call
paint()
for any GUI component. You only need to callrepaint()
. - In case you do the overriding of the other GUI components [
JButton
,JTextField
...], you do not have to call theirrepaint()
method. The parentContainer
's [JFrame
,JPanel
...]repaint()
will do the job.
精彩评论