每x次调用一次函数,而不会阻塞GUI Java [英] Call function every x time without blocking the GUI Java

查看:61
本文介绍了每x次调用一次函数,而不会阻塞GUI Java的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个分类为ItemGUI的类,该类可以处理与用户界面有关的所有内容.用户能够添加一些链接,这些链接是项,因此,当他插入链接并单击ADD按钮时,它应创建Item类的新对象并开始运行名为getPrice()的函数,例如

I have a class caled ItemGUI which is handling everything related with the user interface. The user, is able to add some links, which are the items, so when he inserts a link and clicks on the ADD button, it should create a new object of the class Item and start running a function called getPrice(), something like that:

Item newItem = new Item(newItemField.getText());
// should also be added to a list of items which should be in the ItemGUI class
newItem.getPrice()

这应该在单击添加按钮之后完成.然后,我将物品打印到桌子上.问题在于方法getPrice()应该每5秒运行一次而不会阻塞我的GUI,因此我应该实现线程.

This should be done after clicking the add button. Then I print the item to the table. The problem is that the method getPrice() should run every 5 seconds without blocking my GUI, so I should implement Threads.

我的问题是:如何才能实现一个每5秒钟运行一次该功能(针对列表中的每个项目)的线程,直到我单击停止按钮?我正在考虑使用观察者可观察的类,并带有一个每5秒通知其观察者的时钟.这将是最好的选择吗? 另外,我是否能够从ItemGUI类检索项目变量?

My question is: how can I be able to implement a thread that runs that function (for each item in the list) every 5 seconds until I click on a stop button? I was thinking about using the observer-observable classes with a clock that notifies its observers every 5 seconds. Will this be the best option? Also, will I be able to retrieve the item variables from the ItemGUI class?

谢谢!

推荐答案

更新

MadProgrammer建议的最清晰的解决方案是使用 swing计时器,像这样:

The clearest solution by MadProgrammer's suggestion is to use swing Timers, like this:

protected javax.swing.Timer refresherTimer = null;
protected void stopRefreshing() {
    if (refresherTimer != null) {
        refresherTimer.stop();
        refresherTimer = null;
    }
}
protected void startRefreshing() {
    stopRefreshing();
    refresherTimer = new Timer(500, e -> {
        newItem.getPrice()
    });
    refresherTimer.start();
}
public void onStartButtonClicked() {
    Item newItem = new Item(newItemField.getText());
    // here newItem should be added to a list of items which should be in the ItemGUI class
    startRefreshing();
}
public void onStopButtonClicked() {
    stopRefreshing();
}

原始答案

最好有一些实用程序,例如GuiTimer可使您的任务变得简单:

It would be nice to have some utility named e.g. GuiTimer which would make your task as easy as:

protected GuiThread.Task refresherTask = null;
protected void cancelRefreshing() {
    if (refresherTask != null) {
        refresherTask.cancel();
        refresherTask = null;
    }
}
public void onStartButtonClicked() {
    Item newItem = new Item(newItemField.getText());
    // should also be added to a list of items which should be in the ItemGUI class
    cancelRefreshing();
    refresherTask = GuiThread.scheduleAtFixedRate(() -> {
        newItem.getPrice()
    }, 0, 5, TimeUnit.SECONDS);
}
public void onStopButtonClicked() {
    cancelRefreshing();
}

常规计时器的问题在于它们在自己的线程上而不是在gui线程上调用回调函数,因此要求开发人员确保正确的线程.不幸的是,内置的Java EventQueue不支持调度延迟的任务.

The problem with regular timers is that they invoke the callback function on their own thread, not on the gui thread, so it requires the developer to ensure proper threading. Unfortunately the builtin java EventQueue does not support dispatching delayed tasks.

由于这个原因,我喜欢使用以下名为GuiTimer的实用程序,它将用作纯gui线程计时器:

For this reason I like to have the following utility called GuiTimer, which will act as a pure gui-threaded timer:

public class GuiTimer {
    public static final ScheduledThreadPoolExecutor executor = 
            new ScheduledThreadPoolExecutor(1);

    public static interface Task {
        public void cancel();
    }

    private static class CancelStateTask implements Task {
        public volatile boolean canceled = false;

        @Override
        public void cancel() {
            this.canceled = true;
        }
    }

    public static Task schedule(final Runnable action) {
        CancelStateTask task = new CancelStateTask();
        EventQueue.invokeLater(() -> {
            if (!task.canceled)
                action.run();
        });
        return task;
    }

    public static Task schedule(final Runnable command, long delay,
            TimeUnit unit) {
        ScheduledFuture<?> future = executor.schedule(
                () -> EventQueue.invokeLater(command), delay, unit);
        return () -> future.cancel(false);
    }

    public static Task scheduleAtFixedRate(Runnable command,
            long initialDelay, long period, TimeUnit unit) {
        ScheduledFuture<?> future = executor.scheduleAtFixedRate(
                () -> EventQueue.invokeLater(command), initialDelay,
                period, unit);
        return () -> future.cancel(false);
    }

    public static Task scheduleWithFixedDelay(Runnable command,
            long initialDelay, long delay, TimeUnit unit) {
        ScheduledFuture<?> future = executor.scheduleAtFixedRate(
                () -> EventQueue.invokeLater(command), initialDelay, delay,
                unit);
        return () -> future.cancel(false);
    }

    public static void shutdown() {
        executor.shutdown();
    }
}

这篇关于每x次调用一次函数,而不会阻塞GUI Java的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆