Overriding the paint() method in JButton - java

I have a class that extends JButton because the custom look and feel I'm using ignores the isOpaque() call. What I mean is, the background of the button is rendered even though I have called setOpaque (false) on it and all parent panels. I have confirmed that this is an issue with the LAF from the companies design people so there is nothing I can do but extend the class.
So my question is, how can I implement the paint() method to not render the background and just the button icon?
Cheers
SOLVED: The answer I was after in case anyone is interested was to use button.setContentAreaFilled(false);

Painting is done by three methods: paintComponent, paintBorder, and paintChildren. They're called in that order and it's the first that paints the component's background. If you overload that one and leave the other two, you should be fine.

Related

isShowing() vs isDisplayable()

What is better to use:
.isDisplayable()
or:
isShowing()
to check if JButtons are visible, but also for other things? Also what is the difference between them? At this moment they look like same thing to me, but i'm a beginner.
they are giving same results, even when button was set to Opaque(false)
Don't confuse opaqueness of a component with visibility of a component.
Opaqueness is for painting the background of the component.
The component can still be visible even if the background is transparent.
Try using setVisible(false) to see the difference between the two methods.
A component can only be showing if it is:
displayable
visible

Why do I have to use setvisible() on my JFrame when I change components?

So for the sake of simplicity I set up a little test code just to figure out this problem. Basically I have a JFrame and I added 'this' to it (I just extended my main class from JComponent to save time). this component fills in a red background. Then I have it sleep for 2 seconds and then type this.
f.remove(this);
thing t = new thing();
f.add(t);
f.setVisible(true);
f being my JFrame object and 'thing' is just another class extending JComponent that paints a blue background..
when I comment out setvisible() it no longer changes to blue.. I've tried using t.setVisible(true) but it seems I have to make the frame visible again, not the component
does anyone know why I have to call that... or if there is another way to change components within a single frame?
"Basically I have a JFrame and I added 'this' to it (I just extended my main class from JComponent to save time). this component fills in a red background. Then I have it sleep for 2 seconds and then type this."
Don't "sleep" your program. Instead use a java.swing.Timer to perform repeated tasks on the GUI or for animation. See more at How to Use Swing Timers. You can see a bunch of Timer examples here and here and here and here and here
Instead of trying to add and remove panels look into using a CardLayout which allows you to switch between views. It will help you avoid a lot of problems that come with with adding and removing components/containers. See more at How to Use CardLayout. Also see a simple example here.
To answer your main question, whenever you remove and add components from your frame, you need to revalidate() it. setVisible() takes care of that for you.
Side Note
Seems like a lot adding an removing background panels) just to change the background. Why not just setBackround()? You can switch colors with the use of the Timer
Calling setVisible(true) makes the frame appear onscreen. Sometimes you might see the show method used instead. The two usages are equivalent, but we use setVisible(true) for consistency's sake.

Manage multiple Jlabel's events

I have a left Panel with multiples Jlabels which i use them as buttons to change a Main Panel's content which is layouted with a CardLayout.
I cant work perfectly with these events:
mouseEntered : to make highlight effect to the jlabel
mouseExited : to take off the highlight effect.
mouseClicked : to change the content of the main Panel and start some threads
The problem here that can't found an event or a method tell me that another Jlabel has been clicked so i can stop my threads started in the mouseClicked event,
OR
an event or method tell me that a JPanel in the CardLayout has been displayed or hidden.
Your problem is not finding an appropriate event. I think you are doing this using a visual GUI builder and expect to solve everything out-of-the-box. It's not going to work that way, you will need to write some real code. For example, write a method that you will call from the mouse click listener of each of the three JLabels. Thus you will have arranged for this method to be called for each JLabel click. Then in the method do the appropriate handling. This is just a rough outline, you haven't provided much detail to give any further advice.
It sounds like you need FocusEvents and FocusListeners. These are supported by all JComponents like JPanel, JLabel, and JButton, such as by calling addFocusListener();
Basically a FocusListener can tell you when a JComponent gains focus (such as by clicking on the JComponent) and when it looses focus (such as by clicking on a different JComponent).
Refer to http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/event/FocusListener.html for further information

Limit JButton repaint to state changes?

After what I learned from my previous question, I would like to use a texture to paint the text on an extended JButton while it's being pressed. The first step was setting up the button's ChangeListener and stateChanged method; I have these working and can set the foreground color in the method, so that the text will be one color while the button's pressed and another while not.
Building on this, I replaced the setForeground call with the drawString code I used for my toggleButtons. It works, but immediately after the text is drawn it's overwritten by the button being automatically repainted. I tried throwing the code in a "while (model.isPressed())" loop, but that had some pretty terrible results (system hang). How would I go about manually repainting my button, so that it's only redrawn during the stateChanged method?
It seems to me that you are going the wrong way to change the look of your button. I think it would be easier for you to create a class that would handle the look and feel of your button, instead of manually handling the drawing parameters of your button inside the button's code. Blocking the repaint() calls isn't really the way to go I believe in your case.
I would personally create my own ButtonUI implementation that would handle all the paint rules (foreground color based on button state for instance), then I would call the setUI on the button, specifying an instance of this new ButtonUI as a parameter. If you don't want to handle all the drawing stuff, you can always use your new class as a proxy to the button's already existing UI handler (through JButton's getUI() method), and make changes only where you need them (I haven't tested it myself, but I'm pretty sure it would work just fine).
Of course, this represents more coding for you, but it would localize your look and feel handling in a single class, and it would fit in Swing's way of working. There are a few resources on the web to get you started (here, here and here).

Who is calling paintComponent?

For some reason, my paintComponent(Graphics g) method is being called infinitely. I can't seem to tell who is calling it, even if I dump a StackTrace in the call (it's an event that's dispatched and handled).
Are there any easy ways to find out who's triggering the event?
Update: I've found the cause and I now understand the reason. Whoever answers it correctly will get the answer to the question.
Here is the code that's causing the issue:
#Override
public void paintComponent(Graphics g)
{
myJButton.setIcon(ResourceLoader.getImageIconWithLocale(MY_BUTTON_IMAGE));
super.paintComponent(g);
}
FYI: It's a really tricky one!! It's not obvious by looking at the code. I made an assumption that was wrong.
I don't know which component this is, but setting an icon on a button from within a paint routine is a bad idea. It will definitely cause the button to be repainted. If the button is a child of your component then setting the button invalidate the component too causing an infinite loop.
Set the icon somewhere else such as where the dialog / window is set up initially.
The setIcon(ImageIcon) will revalidate and repaint itself ONLY if the ImageIcon is another instance.
When working with Locales, most people are use to the ResourceBundle, which returns Strings, which in turn are immutable. Therefore setting the text over and over doesn't matter.
However, in this case, the ResourceLoader (custom class) returned a new instance of an ImageIcon. Sure it was the same Image, but it was another instance. And if you decompile the code, you'll see that setIcon (at least for JButtons), it will repaint and revalidate if newIcon != oldIcon.
The solution was to use a HashMap in the ResourceLoader, this way it saves from loading the images more than once since most of the images are used very frequently (might as well reuse the instances if you can). Turns out that overall this quick adjustment also saved a decent amount of overall memory consumption as an added bonus.
Are you calling repaint() anywhere? Also, when a window becomes visible (uncovered or deminimized) or is resized, the "system" automatically calls the paintComponent() method for all areas of the screen that have to be redrawn.
The problem is that you are setting the icon in the paintComponent() method. You should never set a property in this method.
Swing components are smart enough to repaint themselves whenever a property changes. In this case you have the problem of the component repainting itself because the Icon changes, but you are also rereading the Icon every time the component repaints itself which is also not very efficient.

Categories

Resources