Java 第二个变量忽略第一个

Java second variable dismisses first one

我要做的是制作一个小图形用户界面,当单击 button 时,它会开始显示 threads 的进度条;但是,我们必须使用实现 Runnable interface 的内部 class 来完成它,并且在 class 的构造函数中,它需要一个 String 和一个 JProgressBar 目的。然后在主构造函数中,我们应该实例化 2 个 JProgressBar 对象,然后使用这些 JProgressBars.

创建 2 个内部 class 对象

只有我的第二个 JProgressBar 使用 thread 更新。我知道我的第二个 JProgressBar 基本上覆盖了我的第一个,但我不知道我将如何解决这个问题,因为如果我尝试将内部 class 的构造函数更改为设置 2 JProgressBar 属性等于构造函数的参数,那么第一个 JProgessBar 就完全从 GUI 中消失了。这是我的代码,感谢任何可以提供帮助的人。

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

    public class Lab4Part2 {
    //Attributes
    private JFrame frame;
    private String progress;
    private JProgressBar jpb;

    //Constructor
    public Lab4Part2() {
      //Create frame with specified grid layout
      frame = new JFrame();
      GridLayout grid = new GridLayout(0,1);
      frame.setLayout(grid);
      JButton jbClick = new JButton("Let's start this show");
      frame.add(jbClick);

      //Add in JProgressBars and create Inner Class objects with them
      JProgressBar jpb1 = new JProgressBar();
      JProgressBar jpb2 = new JProgressBar();
      InnerProgress bar1 = new InnerProgress("Progress 1: ", jpb1);
      InnerProgress bar2 = new InnerProgress("Progress 2: ", jpb2);

      //Anonymous class for the button's action listener
      jbClick.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            Thread t1 = new Thread(bar1);
            Thread t2 = new Thread(bar2);
            t1.start();
            t2.start();
         }
      });

      //Adds inner object to frame
      frame.add(bar1);
      frame.add(bar2);

      //Packing and stuff
      frame.pack();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
    }

      //Inner class
      class InnerProgress extends JPanel implements Runnable {

      //Constructor
      public InnerProgress(String pbar, JProgressBar jpBar) {
         jpBar.setMinimum(0);
         jpBar.setMaximum(80);
         jpBar.setStringPainted(true);
         progress = pbar;
         jpb = jpBar;
         JLabel label = new JLabel(pbar);
         add(label);
         add(jpBar);
      }

      //Thread action
      public void run() {
         System.out.println("We are running " + Thread.currentThread().getName());
         for(int i = 1; i<= 80; i++) {
            try {
               Thread.currentThread().sleep((long)Math.random()*100);
               jpb.setValue(i);
            }
            catch(InterruptedException ie) {
               System.out.println(ie);
            }
         }
         System.out.println("Thread name: " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
      }
     }

      //Main
      public static void main(String[] args) {
      new Lab4Part2();
     }

    }

你的内部 class 应该维护它自己对它传递的 JProgressBar 的引用。

只需取...

private JProgressBar jpb;

然后把它移到你内心的class

class InnerProgress extends JPanel implements Runnable {

    private JProgressBar jpb;
    //...

那么,另外两个问题

一,(long)Math.random()*100 导致 Math.random() 的结果变为 int,这将导致它变成 0

您需要对运算结果进行强制转换,例如...

Thread.currentThread().sleep((int)(Math.random() * 500));

(注意:我测试了 500)

二、Swing不是线程安全的。这意味着您不应该从事件调度线程的上下文之外更新 UI。

所以,而不是...

jpb.setValue(i);

我写了一个新方法,它会相应地更新 UI

protected void updateProgress(int value) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            InnerProgress.this.jpb.setValue(value);
        }
    });
}

(总而言之,在匿名上下文中引用变量会带来问题)

然后简单地使用 updateProgress(i);

调用它

可运行示例...

import java.awt.GridLayout;
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.JProgressBar;
import javax.swing.SwingUtilities;

public class Lab4Part2 {
//Attributes

    private JFrame frame;
    private String progress;

//Constructor
    public Lab4Part2() {
        //Create frame with specified grid layout
        frame = new JFrame();
        GridLayout grid = new GridLayout(0, 1);
        frame.setLayout(grid);
        JButton jbClick = new JButton("Let's start this show");
        frame.add(jbClick);

        //Add in JProgressBars and create Inner Class objects with them
        JProgressBar jpb1 = new JProgressBar();
        JProgressBar jpb2 = new JProgressBar();
        InnerProgress bar1 = new InnerProgress("Progress 1: ", jpb1);
        InnerProgress bar2 = new InnerProgress("Progress 2: ", jpb2);

        //Anonymous class for the button's action listener
        jbClick.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                Thread t1 = new Thread(bar1);
                Thread t2 = new Thread(bar2);
                t1.start();
                t2.start();
            }
        });

        //Adds inner object to frame
        frame.add(bar1);
        frame.add(bar2);

        //Packing and stuff
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    //Inner class
    class InnerProgress extends JPanel implements Runnable {

        private JProgressBar jpb;

        //Constructor
        public InnerProgress(String pbar, JProgressBar jpBar) {
            jpBar.setMinimum(0);
            jpBar.setMaximum(80);
            jpBar.setStringPainted(true);
            progress = pbar;
            jpb = jpBar;
            JLabel label = new JLabel(pbar);
            add(label);
            add(jpBar);
        }

        //Thread action
        public void run() {
            System.out.println("We are running " + Thread.currentThread().getName());
            for (int i = 1; i <= 80; i++) {
                try {
                    Thread.currentThread().sleep((int)(Math.random() * 500));
                    updateProgress(i);
                } catch (InterruptedException ie) {
                    System.out.println(ie);
                }
            }
            System.out.println("Thread name: " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
        }

    protected void updateProgress(int value) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                InnerProgress.this.jpb.setValue(value);
            }
        });
    }
    }

    //Main
    public static void main(String[] args) {
        new Lab4Part2();
    }

}