类推 ToolTipManager setDismissDelay(int milliseconds) 方法,我想为 JButton 上的翻转效果实现解除延迟。
在我的 swing 应用程序中,我为 JButton 设置了不同的图标(setIcon、setPressedIcon 和 setRolloverIcon 方法),但我试图解决按下应打开模式对话框的特定 JButton 时发生的问题。 当按下按钮并显示模式对话框时,即使我将“普通”图标传递给 setPressedIcon 方法,jbutton 仍然显示翻转图标。 此外,鼠标悬停图标不会消失,直到光标返回主框架,即使 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);
}
});
与:
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,也只在 invokeLater 调用中调用 setVisible,但它仍然不起作用。
另外,如果不在我现在使用的 ButtonModel 上使用相同的代码,我如何使用计时器? 我已经尝试了一些“黑客”,通过在 actionPerformed 中设置“正常图标”,然后使用“自定义”ActionEvent 调用另一个 Action,但我希望有一个“干净”的解决方案。
最佳答案
监听器中的所有代码都在事件调度线程 (EDT)
上执行。
问题是在调用 ActionListener 代码之前按钮的状态没有更改。一旦显示模式对话框,按钮状态更改代码将不会执行,直到对话框关闭。
将 ActionListener
中的代码包装在 SwingUtilities.invokeLater()
中。此代码将添加到 EDT
的末尾,以便在显示对话框之前完成正常的按钮处理。
阅读 Swing 教程中有关 Swing 并发性的部分,了解有关 EDT
的更多信息。
编辑:
i would prefer not to act directly on ButtonModel
花更多时间玩代码。问题在于,显示对话框时不会生成 mouseExited
,因此 ButtonModel 的状态永远不会更新。
另一个选项可能是为 mouseExited
事件手动生成 MouseEvent
并在显示对话框之前将该事件分派(dispatch)给按钮。
尽管这种方法也被认为是一种黑客行为。
how could i use a Timer
同样,问题在于按钮的状态。即使您使用计时器,您也需要手动重置模型的状态。
您当前的解决方案似乎是合理的,因为所有逻辑都位于自定义行为的类中。
关于java - 如何设置JButton的翻转效果的关闭延迟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41830545/