Java 如何在JButton';什么是滚动效应?
通过与setDismissDelay(int毫秒)方法类似,我想为JButton上的滚动效果实现一个dismise延迟 在我的swing应用程序中,我为我的JButton设置了不同的图标(setIcon、setPressedIcon和setRolloverIcon方法),但我试图解决当按下某个特定JButton时出现的问题,它应该会打开一个模式对话框。 当按下按钮并显示模式对话框时,jbutton仍然显示滚动图标,即使我将“正常”图标传递给setPressedIcon方法。 此外,在光标返回到主框架之前,滚动图标不会消失,如果jdialog已关闭,也是如此 我举了个例子来说明我的意思。我只在主框架中放置了两个按钮,每个按钮都有一个绿色的方形图标作为“正常”图标,还有一个红色图标作为滚动效果。 正如我所说,我希望按钮在按下时再次显示绿色图标。第一个按钮的行为将是“错误的”,因为红色图标在jdialog创建之后可见。 对于第二个按钮,我通过在按下按钮时调用setRollover(false),通过覆盖isPressed()方法(在其DefaultButtonModel中)解决了这个问题 我不认为这是最好的解决方案,我宁愿不直接对ButtonModel执行操作。 所以我想知道你们是否有更好的想法,也许是类似于setDismissDelay方法的东西,就像我之前说过的。谢谢 这里有一个SSCE:Java 如何在JButton';什么是滚动效应?,java,swing,jbutton,rollover,Java,Swing,Jbutton,Rollover,通过与setDismissDelay(int毫秒)方法类似,我想为JButton上的滚动效果实现一个dismise延迟 在我的swing应用程序中,我为我的JButton设置了不同的图标(setIcon、setPressedIcon和setRolloverIcon方法),但我试图解决当按下某个特定JButton时出现的问题,它应该会打开一个模式对话框。 当按下按钮并显示模式对话框时,jbutton仍然显示滚动图标,即使我将“正常”图标传递给setPressedIcon方法。 此外,在光标返回到主
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调用另一个操作,但我希望有一个“干净”的解决方案。侦听器中的所有代码都在
事件调度线程(EDT)
上执行
问题是在调用ActionListener代码之前,按钮的状态没有改变。显示模式对话框后,直到对话框关闭,按钮状态更改代码才会执行
将ActionListener
中的代码包装到SwingUtilities.invokeLater()
中。此代码将添加到EDT
的末尾,以便在显示对话框之前完成正常按钮处理
阅读Swing教程中关于Swing中并发性的部分,了解有关EDT
的更多信息
编辑:
我宁愿不直接对ButtonModel执行操作
花更多的时间玩代码。问题是显示对话框时没有生成mouseExited
,因此ButtonModel的状态永远不会更新
另一个选项可能是为mouseExited
事件手动生成MouseEvent
,并在显示对话框之前将事件分派到按钮
尽管这种方法也会被认为是一种黑客行为
我怎么能用定时器呢
同样,问题是按钮的状态。即使使用计时器,也需要手动重置模型的状态
您当前的解决方案似乎合理,因为所有逻辑都位于自定义行为的类中。侦听器中的所有代码都在
事件调度线程(EDT)
上执行
问题是在调用ActionListener代码之前,按钮的状态没有改变。显示模式对话框后,直到对话框关闭,按钮状态更改代码才会执行
将ActionListener
中的代码包装到SwingUtilities.invokeLater()
中。此代码将添加到EDT
的末尾,以便在显示对话框之前完成正常按钮处理
阅读Swing教程中关于Swing中并发性的部分,了解有关EDT
的更多信息
编辑:
我宁愿不直接对ButtonModel执行操作
花更多的时间玩代码。问题是显示对话框时没有生成mouseExited
,因此ButtonModel的状态永远不会更新
另一个选项可能是为mouseExited
事件手动生成MouseEvent
,并在显示对话框之前将事件分派到按钮
尽管这种方法也会被认为是一种黑客行为
我怎么能用定时器呢
同样,问题是按钮的状态。即使使用计时器,也需要手动重置模型的状态
您当前的解决方案似乎是合理的,因为所有逻辑都位于一个自定义行为的类中。尝试使用SwingWorker实现该功能或任何SwingUtilities。invokeLater()javax.swing.Timer也可以。您甚至可以设置初始延迟,然后使用SwingWorker来实现该功能或任何SwingUtilities。您甚至可以设置初始延迟。感谢您的回答,但目前它仍然不起作用(我编辑了我的问题)。@Ansharja您当前的解决方案对我来说似乎是最好的,请参阅编辑。感谢您的回答,但目前它仍然不起作用(我编辑了我的问题)。@Ansharja您当前的解决方案对我来说似乎是最好的,请参阅编辑。