Java Swing按钮在对话框关闭后无法正确重绘。

5

我有一个JButton,按下它会打开一个模态对话框。当我关闭对话框时,按钮仍然看起来像处于按下状态,直到我移动鼠标。我认为这是因为JDialog在AWT组件上打开(这是一个使用AWT Canvas的第三方组件,我无法更改)。如果我在Swing组件上打开对话框并关闭它,则可以正常工作。

我尝试添加窗口侦听器到对话框,并在对话框关闭时重绘整个框架(使用repaint和paintImmediately),但这并不起作用。您有什么建议如何解决这个问题吗?

这里是一个SSCCE示例。按下按钮然后关闭对话框。请注意,焦点边框仍然围绕按钮,在绿色部分上移动鼠标。

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);
    }    
}

1
我认为这是因为JDialog在AWT组件之上打开了。为什么不尝试在SSCCE中重现它呢? - Andrew Thompson
1
我已经很久很久没有使用AWT组件了。我记得的是,当你将它与Swing混合使用时会遇到麻烦。但我建议带上一个SSCCE - Guillaume Polet
1
@Guillaume 这是真的,但通常只适用于Swing浮动元素,例如JComboBox的下拉菜单或工具提示。我从未见过在一个窗口中使用AWT组件而在另一个窗口中使用Swing时发生这种情况。Java 7显然提供了一个标志,旨在允许自由混合使用AWT和Swing组件。 - Andrew Thompson
2
虽然我不想使用AWT,但是JOGL组件似乎在使用AWT版本时效果更好。我将努力隔离示例以供发布。谢谢。 - Jeff Storey
1
好的,似乎还有其他问题,因为我很难复现...一旦我有了更多线索,就会回复。 - Jeff Storey
显示剩余8条评论
1个回答

5

作为一种权宜之计,在actionPerformed()中返回对话框时,您可以清除rollover状态:

@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);
}

谢谢,我会尝试并在结果上回复。 - Jeff Storey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接