Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java swing button does not repaint properly after dialog closed

I have a JButton and pressing it opens a modal dialog. When I close the dialog, the button still look like it is still in a pressed state until I move the mouse. I think this is happening because the JDialog is opened on top of an AWT component (it's a 3rd party component that uses an AWT Canvas, and I can't change that). If I open the dialog and close it over a swing component, then it works properly.

I've tried adding a window listener to the dialog and repainting the entire frame (using repaint and paintImmediately) when the dialog closes, but this doesn't work. Any suggestions on how to fix this?

Here is an SSCCE example. Press the button and then close the dialog. Notice the focus border is still around the button until moving the mouse over the green section.

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class DialogExample
{

    public static void main(String[] args) throws Exception
    {

        final JFrame jf = new JFrame("AWT/Swing Dialog Test");
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("show dialog");
        final Canvas canvas = new Canvas() {
            @Override
            public void paint(Graphics g)
            {
                g.setColor(Color.RED);
                g.fillRect(0, 0, getWidth(), getHeight());
            }
        };
        canvas.setPreferredSize(new Dimension(200,200));

        button.setAction(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                JDialog dlg = new JDialog(jf,"modal");
                dlg.add(new JLabel("hello"));
                dlg.setModal(true);
                dlg.pack();
                dlg.setLocationRelativeTo(canvas);
                dlg.setVisible(true);
            }            
        });
        button.setText("press me");
        button.setFocusable(false);
        JPanel panel = new JPanel();
        panel.setBackground(Color.GREEN);        
        panel.setPreferredSize(new Dimension(200, 200));
        jf.setLayout(new BorderLayout());
        panel.add(button);
        jf.add(panel, BorderLayout.NORTH);
        jf.add(canvas, BorderLayout.SOUTH);
        jf.setSize(new Dimension(400,400));
        jf.setVisible(true);
    }    
}
like image 371
Jeff Storey Avatar asked May 10 '12 22:05

Jeff Storey


1 Answers

As an expedient, you can clear the rollover state when the dialog returns in actionPerformed():

@Override
public void actionPerformed(ActionEvent e) {
    JDialog dlg = new JDialog(jf, "modal");
    dlg.add(new JLabel("hello"));
    dlg.setModal(true);
    dlg.pack();
    dlg.setLocationRelativeTo(canvas);
    dlg.setVisible(true);
    button.getModel().setRollover(false);
}
like image 96
trashgod Avatar answered Oct 11 '22 14:10

trashgod