单击后禁用JButton并在完成任务后启用它

Jay*_*cee 1 java swing

我有一个带有actionListener的JButton,当我多次点击它时,它会像我点击一样多次完成它的工作,下面是我的代码:

   mouseListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
                JButton source = (JButton) e.getSource();
                source.setEnabled(false);
                try {
                    RequestCommon.ctbCookie = jtf.getText();
                    System.out.println( RequestCommon.ctbCookie );
                    HttpURLConnection connection = HttpURLConnectionBuilder.getConnection(RequestCommon.login, RequestCommon.getCtb888Headers());
                    String connectionOuput = HttpURLConnectionBuilder.getConnectionOuput(connection);
                    System.out.println(connectionOuput);
                    new Player(new BufferedInputStream(new FileInputStream(new File("sounds/8.mp3")))).play();
                } catch (IOException e1) {
                    e1.printStackTrace();
                } catch (JavaLayerException e1) {
                    e1.printStackTrace();
                }
                source.setEnabled(true);
        }
    };
    jb1.addActionListener(mouseListener);
Run Code Online (Sandbox Code Playgroud)

我希望无论我在作业运行期间点击多少次,它都不会再次执行.当工作完成后,如果我再次点击,工作将再次运行.我不知道该怎么做,请告诉我你是否知道,谢谢!

cam*_*ckr 5

长时间运行的代码不应该在事件调度线程(EDT)上执行.您需要启动一个单独的线程来处理HTTP请求.

最简单的方法是使用a SwingWorker.您可以在启动worker之前禁用该按钮,然后该worker具有一个done()被调用的方法,您可以启用该按钮.

阅读从秋千上的教程部分在Swing并发有关EDT和更多信息Swing的工人的工作示例.

编辑:

人们似乎对事件处理感到困惑.在处理下一个事件之前调用事件的侦听器.所以在按钮上"双击"的情况下.第一次单击时禁用该按钮,并启动长时间运行的任务.然后在禁用按钮上接收第二次单击,因此不会调用ActionListener.

这是我在SwingWorker存在之前编写的一些旧代码."在新线程中启动"按钮的基本逻辑是:

  1. 禁用该按钮,以便在处理过程中无法单击
  2. 通过循环10次并睡眠来模拟长时间运行的任务
  3. 启用按钮,以便再次完成任务

这是代码:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/*
* A couple of notes about long running tasks and GUI updates:
*
* 1) all GUI painting should be done in the event thread
* 2) GUI painting is not done until the event thread processing is done
*
* This means that long running code (database access, file processing ...)
* should not be done in the event thread. A new thread can be created for
* these tasks.
*
* Most Swing methods are not thread safe. If the long running task needs
* to update the GUI for any reason then the SwingUtilities class
* should be used to add code to the event thread.
*
* See the Swing tutorial on "Using Threads" for more information
* http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
*/
public class InvokeLaterTest extends JFrame
    implements ActionListener, Runnable
{
    JLabel status;
    JButton eventThread;
    JButton newThread;
    JButton stop;
    Thread thread;
    int i;
    boolean stopProcessing;

    public InvokeLaterTest()
    {
        status = new JLabel( "Ready to Process:" );
        status.setHorizontalAlignment( JLabel.CENTER );
        getContentPane().add(status, BorderLayout.NORTH);

        eventThread = new JButton( "Start in Event Thread" );
        eventThread.addActionListener( this );
        getContentPane().add(eventThread, BorderLayout.WEST);

        newThread = new JButton( "Start in New Thread" );
        newThread.addActionListener( this );
        getContentPane().add(newThread, BorderLayout.EAST);

        stop = new JButton( "Stop Processing" );
        stop.addActionListener( this );
        getContentPane().add(stop, BorderLayout.SOUTH);
    }

    public void actionPerformed(ActionEvent e)
    {
        //  Code is executing in Event thread so label will not be updated
        //  and the Stop button will not be enabled.

        if (e.getSource() == eventThread)
        {
            stopProcessing = false;
            run();
        }

        //  Code is executing in a new thread so label will be updated

        else if (e.getSource() == newThread)
        {
            stopProcessing = false;
            thread = new Thread( this );
            thread.start();
        }
        else
        {
            stopProcessing = true;
            status.setText("Processing Stopped");
            setButtons( true );
        }
    }

    public void run()
    {
        setButtons( false );

        for (i = 1; i < 10; i++)
        {
            if ( stopProcessing ) return;

            System.out.println("ProcessingFile: " + i);

            // SwingUtilities makes sure code is executed in the event thread.

            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    status.setText("Processing File: " + i);
                    status.paintImmediately(status.getBounds());
                }
            });

            // simulate log running task

            try { Thread.sleep(1000); }
            catch (Exception e) {}
        }

        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                status.setText("Finished Processing");
                setButtons( true );
            }
        });
    }

    private void setButtons(boolean value)
    {
        eventThread.setEnabled( value );
        newThread.setEnabled( value );
    }

    public static void main(String[] args)
    {
        JFrame frame = new InvokeLaterTest();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.show();
    }
}
Run Code Online (Sandbox Code Playgroud)

SwingWorker类似于上面的逻辑,但是:

  1. 您需要禁用SwingWorker外部的按钮
  2. worker将为您创建Thread并执行代码
  3. 当worker完成时,done()调用worker 的方法,以便启用该按钮.