通过类比ToolTipManager setDismissDelay(int milliseconds)方法,我想对JButton上的翻转效果实现一个消除延迟。
在我的swing应用程序中,我为我的JButtons设置了不同的图标(setIcon,setPressedIcon和setRolloverIcon方法),但是我试图解决当应该打开模态对话框的特定JButton被按下时出现的问题。 当按下按钮并显示模态对话框时,即使我通过"正常"按钮仍然显示翻转图标。图标到setPressedIcon方法。 此外,翻转图标不会消失,直到光标返回到主框架,如果jdialog已关闭,也会消失。
我做了一个例子来说明我的意思。我只在主框架中放置了两个按钮,每个按钮都有一个绿色正方形图标为"正常"图标和翻转效果的红色图标。 正如我所说,我希望按钮在按下时再次显示绿色图标。第一个按钮将表现错误",因为在jdialog创建后可见红色图标。 对于第二个按钮,我通过在按下按钮时调用setRollover(false)来解决此问题,重写isPressed()方法(在其DefaultButtonModel中)。
我不认为这是最好的解决方案,我宁愿不直接在ButtonModel上行动。 所以我想知道你是否有更好的想法,也许类似于setDismissDelay方法,就像我之前说的那样。谢谢!
这里有一个SSCE:
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.DefaultButtonModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class SSCE
{
public static void main (String[] a) {
SwingUtilities.invokeLater (new Runnable () {
public void run () {
JFrame frame = new JFrame ("Icon Test");
frame.setContentPane (new MainPanel (frame));
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setResizable (false);
frame.pack ();
frame.setLocationRelativeTo (null);
frame.setVisible (true);
}
});
}
}
class MainPanel extends JPanel
{
public MainPanel (JFrame parent) {
JButton firstButton = createButton (createButtonImage (Color.GREEN), createButtonImage (Color.RED), parent);
JButton secondButton = createButton (createButtonImage (Color.GREEN), createButtonImage (Color.RED), parent);
secondButton.setModel (new DefaultButtonModel () {
@Override public boolean isPressed () {
boolean isPressed = super.isPressed ();
if (isPressed) setRollover (false);
return isPressed;
}
});
add (firstButton);
add (secondButton);
}
private JButton createButton (BufferedImage normalImage, BufferedImage rolloverImage, final JFrame parent) {
ImageIcon normalIcon = new ImageIcon (normalImage), rolloverIcon = new ImageIcon (rolloverImage);
JButton button = new JButton (new AbstractAction () {
public void actionPerformed (ActionEvent e) {
JDialog dialog = new JDialog (parent, "Test Dialog",true);
dialog.setSize (400, 400);
dialog.setLocationRelativeTo (parent);
dialog.setVisible (true);
}
});
button.setBorderPainted (false);
button.setCursor (Cursor.getPredefinedCursor (Cursor.HAND_CURSOR));
button.setFocusPainted (false);
button.setContentAreaFilled (false);
button.setIcon (normalIcon);
button.setPressedIcon (normalIcon);
button.setRolloverEnabled (true);
button.setRolloverIcon (rolloverIcon);
return button;
}
private BufferedImage createButtonImage (Color color) {
BufferedImage image = new BufferedImage (20, 20, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics ();
g.setColor (color);
g.fillRect (0, 0, 20, 20);
g.dispose ();
return image;
}
}
编辑:
正如@camickr建议的那样,我试图将ActionListener代码包装在SwingUtilities.invokeLater()中。
我不会重新发布完整的代码,我只替换了这些代码:
JButton button = new JButton (new AbstractAction () {
public void actionPerformed (ActionEvent e) {
JDialog dialog = new JDialog (parent, "Test Dialog",true);
dialog.setSize (400, 400);
dialog.setLocationRelativeTo (parent);
dialog.setVisible (true);
}
});
with:
JButton button = new JButton ();
button.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent e) {
SwingUtilities.invokeLater (new Runnable () {
public void run () {
JDialog dialog = new JDialog (parent, "Test Dialog",true);
dialog.setSize (400, 400);
dialog.setLocationRelativeTo (parent);
dialog.setVisible (true);
}
});
}
});
但是,这并没有解决我的问题,创建对话框时仍然可以看到红色图标。 我尝试了一些小调整,使用addActionListener或setAction,也只调用setVisible进入invokeLater调用,但它仍然无法正常工作。
另外,如何在不使用我现在使用的ButtonModel上使用相同代码的情况下使用Timer? 我已经尝试了一些" hacks"通过设置"正常图标"在actionPerformed中,然后使用" custom"调用另一个Action。 ActionEvent,但我希望有一个" clean"溶液
答案 0 :(得分:2)
侦听器中的所有代码都在Event Dispatch Thread (EDT)
上执行。
问题是在调用ActionListener代码之前不会更改按钮的状态。显示模态对话框后,按钮状态更改代码不会执行,直到对话框关闭。
将ActionListener
中的代码包裹在SwingUtilities.invokeLater()
中。此代码将添加到EDT
的末尾,允许在显示对话框之前完成正常按钮处理。
有关EDT
的详细信息,请阅读Swing中Swutch并行教程中的部分。
编辑:
我不想直接在ButtonModel上行动
花更多时间玩代码。问题是在显示对话框时没有生成mouseExited
因此ButtonModel的状态永远不会更新。
另一种选择可能是为MouseEvent
事件手动生成mouseExited
,并在显示对话框之前将事件发送到按钮。
虽然这种方法也被视为黑客攻击。
我怎么能使用计时器
同样,问题是按钮的状态。即使您使用计时器,您也需要手动重置模型的状态。
您当前的解决方案似乎是合理的,因为所有逻辑都位于自定义行为的类中。