Strange behavior with jButtons
Hey folks, i created a softkeyboard cosisting of jButtons. The buttons are colored with a transparent bright-red. So far so good, everything works. But when i do a mouseover over the buttons, I get very strange graphic errors.
Here are screenshots:
before mouseover:
http://img111.imagevenue.com/img.php?image=48593_vorher_122_622lo.JPG
after mouseover:
http://img150.imagevenue.com/img.php?image=48598_nachher_122_882lo.JPG
And here is a reduced code-sample:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
publicclass JButtonsextends JFrame{
publicstaticvoid main(String[] args){
new JButtons();
}
public JButtons(){
super("-");
Container content = getContentPane();
content.setBackground(Color.white);
content.setLayout(new FlowLayout());
JButton button1 =new JButton("Java");
button1.setFont(new Font("Arial", Font.BOLD, 44));
button1.setBackground(new Color(255,64,64,50));
button1.setBorder(new LineBorder(Color.black, 1));
button1.setForeground(Color.white);
button1.setText("abc");
content.add(button1);
JButton button2 =new JButton("Java");
button2.setFont(new Font("Arial", Font.BOLD, 44));
button2.setBackground(new Color(255,64,64,50));
button2.setBorder(new LineBorder(Color.black, 1));
button2.setForeground(Color.white);
button2.setText("def");
content.add(button2);
JButton button3 =new JButton("Java");
button3.setFont(new Font("Arial", Font.BOLD, 44));
button3.setBackground(new Color(255,64,64,50));
button3.setBorder(new LineBorder(Color.black, 1));
button3.setForeground(Color.white);
button3.setText("ghi");
content.add(button3);
pack();
setVisible(true);
}
PS: This behavior just occures on Windows, everything works fine on my macbook
[3216 byte] By [
BastiMa] at [2007-11-27 11:20:26]

# 1
Hi, I don't get those deformed buttons when I run om my Windows. (JRE 1.6.0_01-b06)
With every mouseover I make over a Button, it is less transparent - is that your intention or a problem?
good luck, hope you will solve this interesting problem!
# 2
I don't have a problem with the mouse over, but I do have a problem with repainting when the button is clicked.
Anyway the basic problem is that when you have an opaque component, then the painting sub system assumes the component is responsible for painting the background of the component and therefore doesn't paint the parent component.
However, because your background is transparent, you need to make sure the parent is painted first. This is done by making the button non-opaque. But when you do this the background doesn't get painted at all, so you need to customize the component and paint the background yourself. Something like this:
JButton button1 = new JButton("Java")
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
button1.setOpaque( false );
# 3
Dang, while camikr was posting, I was typing:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class JButtons extends JPanel
{
Color myBckgrnd = new Color(255, 64, 64, 50);
public static void main(String[] args)
{
JButtons myJBtns = new JButtons();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(myJBtns);
frame.pack();
frame.setVisible(true);
}
class MyButton extends JButton
{
public MyButton()
{
super();
setAppearance();
}
public MyButton(String text)
{
super(text);
setAppearance();
}
private void setAppearance()
{
setOpaque(false);
setFont(new Font("Arial", Font.BOLD, 44));
setBackground(myBckgrnd);
setBorder(new LineBorder(Color.black, 1));
setForeground(Color.white);
}
@Override
public void paintComponent(Graphics g)
{
g.setColor(myBckgrnd);
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
}
public JButtons() {
super();
setBackground(Color.white);
setLayout(new FlowLayout());
for (int i = 0; i < 3; i++)
{
MyButton myButton = new MyButton();
StringBuffer sb = new StringBuffer();
for (int j = 0; j < 3; j++)
{
int charInt = (int) 'a';
charInt += i * 3 + j;
sb.append((char) charInt);
}
myButton.setText(sb.toString());
add(myButton);
}
}
}
# 4
Mark control as non-opaque if you set the background color that is non-opaque (alpha channel < 255).
# 5
Thank you very much, your solution works!
In the meantime, i changed the code myself, and it also works. Here is my solution:
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class JButtons extends JFrame {
static final long serialVersionUID = 1;
public static void main(String[] args) {
new JButtons();
}
public JButtons() {
super("-");
Container content = getContentPane();
content.setBackground(Color.white);
content.setLayout(new FlowLayout());
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
content.add(new MyJButton("abc"));
content.add(new MyJButton("def"));
content.add(new MyJButton("ghi"));
pack();
setVisible(true);
}
}
import java.awt.Color;
import java.awt.Font;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.border.LineBorder;
public class MyJButton extends JButton {
static final long serialVersionUID = 1;
public MyJButton() {
super();
// TODO Auto-generated constructor stub
myConstructor();
}
public MyJButton(Action a) {
super(a);
// TODO Auto-generated constructor stub
}
public MyJButton(Icon icon) {
super(icon);
// TODO Auto-generated constructor stub
myConstructor();
}
public MyJButton(String text, Icon icon) {
super(text, icon);
// TODO Auto-generated constructor stub
myConstructor();
}
public MyJButton(String text) {
super(text);
// TODO Auto-generated constructor stub
myConstructor();
}
private void myConstructor() {
setFont(new Font("Arial", Font.BOLD, 44));
setOpaque(true);
setBackground(new Color(255, 64, 64, 50));
setBorder(new LineBorder(Color.black, 1));
setForeground(Color.white);
addMouseListener(new MyMouseListener());
setFocusable(false);
}
}
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class MyMouseListener implements MouseListener {
static final long serialVersionUID = 1;
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
e.getComponent().getParent().repaint();
}
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
e.getComponent().getParent().repaint();
}
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
e.getComponent().getParent().repaint();
}
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
e.getComponent().getParent().repaint();
}
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
e.getComponent().getParent().repaint();
}
}
null
# 6
> Here is my solution:
Why would you do a soluton like that?
You are already extending the button so just override the paint component method.
Why would you add a MouseListener simply to invoke the parent.repaint()? When you repaint the panel you repaint the entire panel and all the components on the panel. Which is not very efficient given that you only mouse over a single component.
So much for simple solutions.
# 7
thx for your tip!
I'm quite new to java and programming in general, so I'm still learning :)
btw, i was quite proud to solve the problem on my own :)
bye