秒表取消暂停不起作用

2024-02-27

我正在尝试创建一个秒表。这start and pause按钮工作正常,但unpause按钮无法正常工作。timer是我的 JLabel,我想在其中展示我的秒表(它引用timer来自 JFrame)。我无法发布 MCVE,因为代码太多。

这是我的跑表 class:

public class Stopwatch extends Thread {

    private boolean finishedFlag = false;
    private boolean pauseFlag = false;
    private boolean sortFlag = false;
    private long summedTime = 0;
    private JLabel timer;

    public Stopwatch(){}

    public Stopwatch(boolean finished, boolean pause, boolean sort, JLabel timer){
        this.finishedFlag = finished;
        this.pauseFlag = pause;
        this.sortFlag = sort;
        this.timer = timer;
    }

    @Override
    public void run() {
        long startTime = System.currentTimeMillis();
        while(sortFlag && !pauseFlag && !finishedFlag) {
            update(summedTime + (System.currentTimeMillis() - startTime));
        }
        if(pauseFlag)
            summedTime += System.currentTimeMillis() - startTime;
        else 
            summedTime = 0;
    }

    private void update(long dT){
        long x = (dT/1000)%60;
        long y = (dT/60000)%1000;
        if(x>=0 && x<=9 && y>=0 && y<=9)
            timer.setText("0"+String.valueOf((dT/60000)%1000)+":0"+String.valueOf((dT/1000)%60)+","+String.valueOf((dT)%1000));
        else if(x>9 && y>=0 && y<=9)
            timer.setText("0"+String.valueOf((dT/60000)%1000)+":"+String.valueOf((dT/1000)%60)+","+String.valueOf((dT)%1000));
        else if(x>=0 && x<=9 && y>9)
            timer.setText(String.valueOf((dT/60000)%1000)+":0"+String.valueOf((dT/1000)%60)+","+String.valueOf((dT)%1000));
        else if(x>9 && y>9)
            timer.setText(String.valueOf((dT/60000)%1000)+":"+String.valueOf((dT/1000)%60)+","+String.valueOf((dT)%1000));
    }
}

这是我用于按钮的监听器:

ActionListener sortListener = new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            if(sortFlag == false && pauseFlag == false)
            {
                sortFlag = true;
                System.out.println("sort");
                stopwatch1 = new Stopwatch(finishedFlag,pauseFlag,sortFlag,timer1);
                stopwatch1.start();
                appFrame.validate();
                appFrame.repaint();
            }
        }
    };
    sortButton.addActionListener(sortListener);

    ActionListener pauseListener = new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            if(sortFlag && pauseFlag == false)
            {
                pauseFlag = true;
                timeSpent = stopwatch1.getSummedTime();
                stopwatch1.setPauseFlag(true);
                System.out.println("pause");
            }
        }
    };
    pauseButton.addActionListener(pauseListener);

    ActionListener unpauseListener = new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            if(sortFlag && pauseFlag)
            {
                pauseFlag = false;
                stopwatch1.setPauseFlag(false);
                stopwatch1.run();
                System.out.println("unpause");
            }
        }
    };
    unpauseButton.addActionListener(unpauseListener);

你需要以某种方式暂停Thread并停止更新的发生。你可以用if你里面的声明run循环,但是有一种更有效的方法,通过使用监视器锁

public class Stopwatch extends Thread {
    //...
    private final Object pauseLock;

    public Stopwatch() {
        pauseLock = new Object();
    }

    public Stopwatch(boolean finished, boolean pause, boolean sort, JLabel timer) {
        this();
        //...
    }

    @Override
    public void run() {
        long startTime = System.currentTimeMillis();
        while (sortFlag && !finishedFlag) {
            while (pauseFlag) {
                synchronized (pauseLock) {
                    try {
                        pauseLock.wait();
                    } catch (InterruptedException ex) {
                    }
                }
            }
            update(summedTime + (System.currentTimeMillis() - startTime));
        }
        if (pauseFlag) {
            summedTime += System.currentTimeMillis() - startTime;
        } else {
            summedTime = 0;
        }
    }

现在,您需要某种方法来暂停和恢复run loop

public void setPaused(boolean paused) {
    if (paused && !pauseFlag) {
        pauseFlag = paused;
    } else if (!paused && pauseFlag) {
        pauseFlag = paused;
        synchronized (pauseLock) {
            pauseLock.notifyAll();
        }
    }
}

然而,现在我们有更大的问题,Swing 不是线程安全的。这意味着您的update方法违反了 Swing 的单线程规则,可能会导致无穷无尽的问题......

一个更简单的解决方案是只使用 SwingTimer

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel label;
        private StopWatch sw;

        public TestPane() {

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            label = new JLabel("...");
            add(label, gbc);

            sw = new StopWatch(label);

            JButton btn = new JButton("Resume");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    sw.setPaused(!sw.isPaused());
                    btn.setText(sw.isPaused() ? "Resume" : "Pause");
                }
            });
            add(btn, gbc);
        }

    }

    public class StopWatch {

        private Timer timer;
        private JLabel label;

        private int runningTime;
        private long tickTime;

        public StopWatch(JLabel label) {
            this.label = label;
            timer = new Timer(10, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    runningTime += (System.currentTimeMillis() - tickTime);
                    System.out.println(runningTime);
                    update(runningTime);
                    tickTime = System.currentTimeMillis();
                }
            });
        }

        public void setPaused(boolean paused) {
            if (paused && timer.isRunning()) {
                timer.stop();
            } else if (!paused && !timer.isRunning()) {
                tickTime = System.currentTimeMillis();
                timer.start();
            }
        }

        public boolean isPaused()  {
            return !timer.isRunning();
        }

        private void update(long dT) {
            long x = (dT / 1000) % 60;
            long y = (dT / 60000) % 1000;
            if (x >= 0 && x <= 9 && y >= 0 && y <= 9) {
                label.setText("0" + String.valueOf((dT / 60000) % 1000) + ":0" + String.valueOf((dT / 1000) % 60) + "," + String.valueOf((dT) % 1000));
            } else if (x > 9 && y >= 0 && y <= 9) {
                label.setText("0" + String.valueOf((dT / 60000) % 1000) + ":" + String.valueOf((dT / 1000) % 60) + "," + String.valueOf((dT) % 1000));
            } else if (x >= 0 && x <= 9 && y > 9) {
                label.setText(String.valueOf((dT / 60000) % 1000) + ":0" + String.valueOf((dT / 1000) % 60) + "," + String.valueOf((dT) % 1000));
            } else if (x > 9 && y > 9) {
                label.setText(String.valueOf((dT / 60000) % 1000) + ":" + String.valueOf((dT / 1000) % 60) + "," + String.valueOf((dT) % 1000));
            }
        }

    }
}

See 如何使用 Swing 定时器 http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html更多细节

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

秒表取消暂停不起作用 的相关文章

  • 如何调试使用maven构建的android应用程序

    我目前正在尝试从 Eclipse 调试我的设备上的 Android 应用程序 设备已添加 我可以在控制台和 Eclipse 中看到它 控制台 Windows adb devices List of devices attached 0019
  • 为什么 hibernate 在一张表中保存两个 @OneToMany 列表?

    想象一下使用 Hibernate 和 JPA 的简化代码如下 Entity class C Id GeneratedValue public long id MappedSuperclass abstract class A Id Gene
  • IntelliJ Ultimate 在 Play 2.3 (Java) 项目测试中找不到路由

    虽然我的测试运行得很好 但 IntelliJ 抱怨它找不到路由对象 并且代码自动完成无法工作 我已经查看了所有文档 这应该可以工作 这是 IntelliJ 的报告内容 关于我的项目配置可能有什么问题有什么想法吗 这很可能与以下事实有关 ro
  • Java 相当于 Perl 的 s/// 运算符?

    我有一些代码正在从 Perl 转换为 Java 它大量使用了正则表达式 包括s 操作员 我已经使用 Perl 很长时间了 但仍然习惯 Java 的做事方式 特别是 字符串似乎更难使用 有谁知道或有一个完全实现的Java函数s 这样它就可以处
  • 如何显示/隐藏jsf组件

    在我的一个 JSF 应用程序中 顶部的标题部分包含 selectOneMenu 底部的内容部分显示过滤器组件 默认情况下 应用程序首先在顶部显示 selectOneMenu 数据 在底部显示相应的 Filter 信息 如果用户选择不同的se
  • 到底什么是哈希冲突

    HashMap 中的哈希冲突或哈希冲突并不是一个新主题 我遇到过几个博客和讨论板 以模糊且详细的方式解释如何产生哈希冲突或如何避免它 我最近在一次采访中遇到了这个问题 我有很多事情要解释 但我认为很难准确地给出正确的解释 抱歉 如果我的问题
  • 在 SWT 中单击鼠标触发事件?

    在SWT中 对于MouseListener接口 可用的方法有mouseUp mouseDown and mouseDoubleClick 如何根据用户点击触发事件 我们可以通过结合来做到这一点mouseUp and mouseDown 但没
  • FXML 文件中的 getHostServices().showDocument()

    有没有简单的方法可以将 getHostServices showDocument 命令放入 toHomepage 方法中 而不是执行一行又一行的代码 这样代码应该看起来干净简单 package sample import javafx ap
  • 解密 TLS 1.2 AES-GCM 数据包

    我正在开发一个 Java 程序来解密TLS 1 2正在使用的会话TLS RSA WITH AES 128 GCM SHA256密码 我使用wireshark 录制了一个测试会话 这大师秘密是已知的 No Time Protocol Leng
  • Tomcat - 多个 webapps 文件夹

    是否可以有多个文件夹来放置要部署的应用程序 这些是如何定义的 是否可以将一个文件夹限制为仅是 domain com 的应用程序 而不是其他域 Thanks 看一眼conf server xml
  • 处理 ANTLR 4 中的错误

    遵循后接受的答案 https stackoverflow com a 18137301 2279200的指示处理 ANTLR4 中的错误 https stackoverflow com q 18132078 2279200问题 我遇到了以下
  • Spring Boot 多部分文件始终为 null

    我正在使用 Spring Boot version 1 4 0 RC1 和 Spring Boot Stormpath 1 0 2 我正在尝试使用分段文件上传 但控制器中的 MultipartFile 始终为空 当我使用 RequestPa
  • 如何使用键盘上的“删除”按钮作为从 JTable 中删除行的快捷方式[重复]

    这个问题在这里已经有答案了 可能的重复 如何制作删除按钮来删除JTable中的行 https stackoverflow com questions 13236206 how to make delete button to delete
  • 有界通配符相关的编译器错误

    我想知道这段代码有什么问题 Map 但我试图说得更具体 这个问题在这个旧的 Apache 线程 ht
  • Elasticsearch NodeBuilder 与 TransportClient

    对于其他 Elasticsearch 开发人员来说 这可能是一个非常简单 而且愚蠢 的问题 这两者之间有什么区别 我正在从 Java Web 应用程序连接到远程 Elasticsearch 服务器 到目前为止我一直在使用 Transport
  • 将 XML 从网站解析到 Android 设备

    我正在启动一个 Android 应用程序 它将解析来自网络的 XML 我创建了一些 Android 应用程序 但它们从未涉及解析 XML 我想知道是否有人对最佳方法有任何建议 这是一个例子 try URL url new URL your
  • iText7 将 SVG 添加到 PdfDocument 中以及可能出现的问题

    关于问题的答案 如何使用 iText7 将 SVG 添加到 PDF 这是一个链接点击这里 https stackoverflow com questions 50059456 how to add an svg to a pdf using
  • 将字符串转换为字符并按降序排序(ascii)

    我正在创建一个程序 该程序将使用户输入整数 一个接一个 存储在数组中并按降序显示整数 该程序还要求用户输入一个字符串 使用以下命令将其转换为字符string toCharArray 我已经正确地按降序显示整数 问题是我不知道如何按降序显示字
  • Java XML 解析器添加不必要的 xmlns 和 xml:space 属性

    我在 Windows 10 上使用 Java 11 AdoptOpenJDK 11 0 5 2019 10 15 我正在解析一些旧版 XHTML 1 1 文件 这些文件采用以下一般形式
  • 文档过滤器在 Java 中不起作用?

    在超过 10 个字符的文本字段中 它必须显示错误 为此 我使用了文档过滤器 JTextField field JTextField txtFld AbstractDocument document AbstractDocument fiel

随机推荐

  • 在 Selenium IDE 中,如何通过下拉菜单中的索引选择选项?

    问题是选项标签发生变化 所以我无法按标签抓取 我需要通过说选项 0 来抓取 任何想法 我正在使用 Selenium IDE Firefox 这是我要问的部分 tr td select td td dateRangeString td td
  • 什么是 PDO?为什么要使用它?

    人们不断提到我在处理 MySQL 时应该在 PHP 中使用 PDO 我以前从未听说过这一点 什么是PDO 它是如何使用的以及有哪些优点和缺点 Thanks 将 PDO 视为与 PHP 一起打包的内置类 使您可以更轻松地与数据库进行交互 在开
  • 当字符串为空时将字符串值替换为“0”

    我从文本框中获取一个值并将其转换为十进制 但是 文本框值可能为空 那么 我该如何处理文本框中的空字符串呢 不幸的是 我有大约 50 个文本框需要处理 所以像 用 IF 条件检查 null 这样的答案对我没有帮助 如果我使用所有这些 IF 条
  • 从 GNU 到Solaris 的等效日期

    In GNU使用命令 date 我可以做到这一点 date d 4 day datei 20130101 i 5 date d datei i day 但我喜欢知道 我怎样才能在 Solaris 中做到这一点 使用日期命令 Tcl 有一个很
  • Pylance - pandas 方法的类型部分未知

    如果我尝试在严格模式下验证使用 pandas 方法和 pylance 的代码 则会收到验证错误 import pandas as pd ser pd Series float pd Series 1 2 5 3 print ser max
  • 如何使用管道将数据帧列作为函数中的参数传递?

    我正在摆弄内置数据集economics在 R 中 我试图将数据帧列作为参数传递到使用管道的函数中 dplyr https genomicsclass github io book pages dplyr tutorial html gt 但
  • 如何禁用 Android 的 Facebook 单点登录 - Facebook-android-sdk

    facebook android 的 SSO 每次都会给我 invalid key 我尝试用各种方法进行调试 但它不起作用 那么 即使设备上安装了 Facebook 应用程序 是否有任何方法 黑客可以禁用单点登录并使用 Web 视图身份验证
  • Phonegap 插件:如何在 Android 中将 Base64 字符串转换为 PNG 图像

    Android 不允许本机应用程序 例如基于 Phonegap 的应用程序 写入二进制文件 一个常见的应用是将 Base64 字符串转换为图像 那么 您如何解决这个问题呢 解决方案 该插件可转换 Base64 PNG 字符串并生成图像到 s
  • 如何将 ubuntu 命令提示符下的 jar 输出重定向到文本文件

    我创建了 jar 文件并使用以下命令运行它 java jar niidle jar arguments 它显示正确的输出 但我看不到整个输出 我想看到整个输出 那么当我运行以下命令时 如何将整个事情重定向到文本文件 java jar nii
  • 如何在 PHP 中复制 Excel FV 函数?

    我正在将一些相当复杂的计算从 Excel 电子表格转换为 PHP 我被困在 Excel 的 FV 函数的转换上 它的定义如下 FV interest rate number payments payment PV Type 我已经为此工作了
  • 更改源文件后,Visual Studio 2010 提示“构建失败,但没有错误”

    我有一个包含几个项目的 Visual Studio 2010 解决方案 我可以使用 构建 gt 构建解决方案 或 构建 gt 构建 MyCompany MyProduct MyProject 成功构建 构建后 我按 CTRL F5 并成功运
  • ASP.NET MVC 模型状态

    ModelState IsValid 在我的控制器中为我返回 false 我知道这意味着模型绑定时发现一个或多个模型错误 我的问题是如何查看错误 我注意到我的特定 ModelState 有 6 个项目 如果我尝试做其中任何一个 ModelS
  • 绕过 try/catch 块以检查异常的 Lambda 表达式

    由于我尝试提取一些在大多数项目中使用的常见包装 lambda 例程 我已经能够创建CheckedFunction 子类为PermeableFunction绕过 try catch 块的功能接口 我已经在 Windows v1 8 0 251
  • Python requests lib 花费的时间比执行 get 请求的时间要长

    所以我有这个代码 每当我运行代码并到达第 3 行时 执行 get 请求大约需要 20 秒 没有理由花这么长时间 而且每次都花很长时间 有什么帮助吗 def get balance addr try r requests get http b
  • 如何在 Java 中固定字节数组?

    有没有办法在java中固定字节数组 这样它就不会被移动 压缩 我正在开发一个应用程序 该应用程序旨在在运行时具有零 GC 并且我想使用固定到内存映射区域的原始字节数组 有什么办法可以做到这一点或者破解我的方法吗 您可以使用 ByteBuff
  • .NET Core 3 预览版 4:“AddNewtonsoftJson”未定义

    使用 NET Core 3 预览版 4 F ASP NET MVC 项目的 API 模板无法构建 这没有对模板进行任何更改 这是失败的代码 type Startup private member this ConfigureServices
  • 将 DatePicker 添加到模态时出现问题 - 在背景中显示

    我正在尝试插入我在这里找到的 DatePicker http www eyecon ro bootstrap datepicker http www eyecon ro bootstrap datepicker 但我无法让它显示在我的模态前
  • Python 从磁盘刷新文件

    我有一个 python 脚本 它调用系统程序并从文件读取输出out txt 作用于该输出并循环 然而 它不起作用 仔细调查发现 python脚本只是打开out txt一次 然后继续阅读旧版本 如何让 python 脚本在每次迭代时重新读取文
  • Log10 x 轴位于顶部,y 轴位于 geom_line

    我在 ggplot2 中创建了一个图表 如下所示 depth c 1 6 2 6 3 6 4 6 5 6 6 6 7 6 8 6 ri lt c 0 790143779 1 485888068 2 682375391 1 728120227
  • 秒表取消暂停不起作用

    我正在尝试创建一个秒表 这start and pause按钮工作正常 但unpause按钮无法正常工作 timer是我的 JLabel 我想在其中展示我的秒表 它引用timer来自 JFrame 我无法发布 MCVE 因为代码太多 这是我的