Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在JButton';什么是滚动效应?_Java_Swing_Jbutton_Rollover - Fatal编程技术网

Java 如何在JButton';什么是滚动效应?

Java 如何在JButton';什么是滚动效应?,java,swing,jbutton,rollover,Java,Swing,Jbutton,Rollover,通过与setDismissDelay(int毫秒)方法类似,我想为JButton上的滚动效果实现一个dismise延迟 在我的swing应用程序中,我为我的JButton设置了不同的图标(setIcon、setPressedIcon和setRolloverIcon方法),但我试图解决当按下某个特定JButton时出现的问题,它应该会打开一个模式对话框。 当按下按钮并显示模式对话框时,jbutton仍然显示滚动图标,即使我将“正常”图标传递给setPressedIcon方法。 此外,在光标返回到主

通过与setDismissDelay(int毫秒)方法类似,我想为JButton上的滚动效果实现一个dismise延迟

在我的swing应用程序中,我为我的JButton设置了不同的图标(setIcon、setPressedIcon和setRolloverIcon方法),但我试图解决当按下某个特定JButton时出现的问题,它应该会打开一个模式对话框。 当按下按钮并显示模式对话框时,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);
                }
            });
与:

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您当前的解决方案对我来说似乎是最好的,请参阅编辑。