0

我创建了一个按钮..我希望每当我单击该按钮时,它首先禁用其他两个按钮,然后执行我编写的其他任务..但它最后禁用了按钮

Extract.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

Button1.setEnabled(false);

Button2.setEnabled(false);

obj.showData(); 

obj.extractClassesPackagesImports();

obj.inheritanceRelation();

obj.doubleinheritanceRelation();

JOptionPane.showMessageDialog(null, "Done");

}

});

现在上面的程序在显示消息框后禁用按钮..谁能弄清楚这里出了什么问题...提前谢谢

4

3 回答 3

1

正如@vikingsteve 所说,您很可能不允许 GUI 线程有时间更新对话框。

如果您添加Thread.Sleep(1000);,您肯定会在禁用和消息框之间看到延迟。

我不明白为什么在对话框之前或之后禁用按钮会有所不同的实用程序。

更新

我添加了一个额外的线程,以便能够使用 Thread.sleep(5000) ,而不会完全冻结事件调度线程 (GUI)。

但是,由于现在我的代码正在从一个新线程调用 showMessageDialog,我应该使用 invokeLater。

此外,由于原始代码将允许用户单击按钮,即使我们正在等待活动完成,我相信所有操作都应该移动到一个单独的线程,如下所示:

Extract.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {

                //Disable Buttons since we are in Event Dispatching Thread
                Button1.setEnabled(false);
                Button2.setEnabled(false);

                //Tasks moved to separate Thread
                 new Thread(new Runnable() {
                        public void run() {
                            try {
                                //Perform Tasks
                                obj.showData();
                                obj.extractClassesPackagesImports();
                                obj.inheritanceRelation();
                                obj.doubleinheritanceRelation();

                                //Delay before calling message (we are delaying in separate thread to not freeze GUI completely)
                                Thread.sleep(5000); 
                                //Wait 5 seconds before showing dialog

                                //Show the GUI - since GUI interaction from new Thread using invokeLater
                                SwingUtilities.invokeLater(new Runnable() {
                                    public void run() {
                                        JOptionPane.showMessageDialog(null, "Done");
                                    }
                                });

                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }                         
                        }
                    }).start();     

            }
        });

上面的代码在显示消息之前添加了延迟,同时也没有冻结 GUI。

于 2013-09-11T13:24:20.370 回答
1

你可以试试这个:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        JOptionPane.showMessageDialog(null, "Done");
    }
});
于 2013-09-11T13:25:06.387 回答
0

查看、 和中的代码AbstractButton,我得出结论,在事件队列上发布了一个新事件,以显示禁用的按钮。 因此,查看您的代码,会发生以下事件,正如您所描述的:JComponentRepaintManagersetEnabled()

EventQueue:
    Event1: {
        setEnabled(false) // queues Event2
        showMessageDialog(null, "Done")
    },
    Event2: {
        repaint() // to display the disabled button
    }

相关代码如下:

抽象按钮

public void setEnabled(boolean b) {
    // ...
    super.setEnabled(b);
    // ...
}

组件

public void setEnabled(boolean enabled) {
    // ...
    if (enabled != oldEnabled) {
        repaint();
    }
}

public void repaint(long tm, int x, int y, int width, int height) {
    RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height);
}

重绘管理器

public void addDirtyRegion(JComponent c, int x, int y, int w, int h)
{
    // ...
    addDirtyRegion0(c, x, y, w, h);
}

private void addDirtyRegion0(Container c, int x, int y, int w, int h) {
    // ...

    // Queue a Runnable to invoke paintDirtyRegions and
    // validateInvalidComponents.
    scheduleProcessingRunnable();
}

如果您希望在显示对话框之前将按钮显示为禁用,则正如@vikingsteve 指出的那样,解决方案是使用SwingUtilities.invokeLater().

extract.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        button1.setEnabled(false);
        button2.setEnabled(false);
        obj.showData(); 
        obj.extractClassesPackagesImports();
        obj.inheritanceRelation();
        obj.doubleinheritanceRelation();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JOptionPane.showMessageDialog(null, "Done");
            }
        });
    }
});
于 2013-09-11T13:53:11.537 回答