Writing to set number of progress bars with set number of threads

73 views Asked by At

I posted yesterday, when I had absolutely no knowledge of how progress bar works. After getting some help and working on it I have a lot more done, but I'm getting stuck at updating the bars with progress.

I was trying to use my setProgress method and sending updates everytime there was a rotation, but that doesn't seem to be working

Many people told me to use a swing timer to send the progress, but I don't seem to get how to implement it. If somebody could show me how they would do it I would learn a great deal from that.

Edit: The important places to look at would most likely be my run method in Robot and the entirety of my progressbar class.

The problem with the code currently is no progress is updated.

Robot Class

public class Robot implements Runnable{
public static final int on = 0x0001;
public static final int clockwise = 0x0002;
public static final int counter = 0x0004;
int  opcode;
int moveCount = 0;
int rotation, increment, progress = 0;
boolean CW;

ProgressBar prgBar;
CyclicBarrier cyclicBarrier;
Controller c;
Motor m;

public Robot(CyclicBarrier cyclicBarrier, Motor m)
{
    opcode = 0;
    this.cyclicBarrier = cyclicBarrier;
    this.m = m;
}


public Boolean Set(int value)
{
    boolean bvalue = false;
    switch (value)
    {
    case on : 
        bvalue = true;
        break;
    case clockwise :
        if ( (opcode & counter) == 0 )
            bvalue = true;
        break;
    case counter :
        if ( (opcode & clockwise) == 0 )
            bvalue = true;
        break;
    }
    if (bvalue == true)
        opcode += value;
    return bvalue;
}

private String Validate()
{
    String sresult = "Executing: ";
    boolean bvalue = false;
    if ((opcode & on) > 0)
    {
        bvalue = true;
        sresult = "On";
        if ((opcode & (clockwise+counter)) == (clockwise+counter))
            bvalue = false;
        if (bvalue == true)
        {   
            if ((opcode & clockwise) > 0)
                sresult +="+Clockwise";
            if ((opcode & counter) > 0)
                sresult += "+Counter";
        }
        if (bvalue == false)
            sresult = "Invalid opcode";
    }
    return sresult;
}

public void robotExecute()
{
    String svalue = Validate();
    System.out.println(svalue);
    opcode = 0;
}

public void setOn(ProgressBar prgBar){
    this.prgBar = prgBar;
    Set(1);
}


public void run(){
    System.out.println("Running: ");


    m.Engage(this);
    prgBar.setProgress(this, progress);
    try {
        System.out.println("Sleeping: ");
        Thread.sleep(3000);
        cyclicBarrier.await();

    } catch (Exception e){
        e.printStackTrace();
    }
    System.out.println("Engaging: ");
}

public void Rotate(){
        if ((opcode & clockwise) > 0){
            rotation++;
            if(rotation == 360){
                rotation = 0;
                moveCount++;
            }
        }
        if ((opcode & counter) > 0){
            rotation--;
            if(rotation == -360){
                rotation = 0;
                moveCount --;
            }
        }
        prgBar.setProgress(this, progress);
}
}

ProgressBar

public class ProgressBar implements ActionListener {

final int MAX = 100;
final JFrame frame = new JFrame("JProgress ");
final JProgressBar pbOne = new JProgressBar();
final JProgressBar pbTwo = new JProgressBar();
final JProgressBar pbThree = new JProgressBar();

private Map<Robot, JProgressBar> robotBars = new HashMap<>();

    public ProgressBar(){ 

        pbOne.setMinimum(0);
        pbOne.setMaximum(MAX);
        pbOne.setStringPainted(true);

        pbTwo.setMinimum(0);
        pbTwo.setMaximum(MAX);
        pbTwo.setStringPainted(true);

        pbThree.setMinimum(0);
        pbThree.setMaximum(MAX);
        pbThree.setStringPainted(true);

        frame.setLayout(new FlowLayout());
        frame.getContentPane().add(pbOne);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        frame.setVisible(true);
    }

    public ProgressBar(Robot[] robots){
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        frame.setVisible(true);

        for(Robot r: robots) {
            JProgressBar bar = new JProgressBar();
            robotBars.put(r, bar);
            bar.setMinimum(0);
            bar.setMaximum(MAX);
            frame.setLayout(new FlowLayout());
            frame.add(bar);
        }

        /*Timer timer = new Timer(1000, new ActionListener(){
            public void actionPerformed(ActionEvent evt){
                bar.setValue(progress);
            }
        });*/
    }


    public void setProgress(Robot r, int progress){

        final JProgressBar bar = robotBars.get(r);
        if(bar == null) { return;}
        try{
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    bar.setValue(progress);
                }
            });
            java.lang.Thread.sleep(100);
        } catch (InterruptedException e) {
        JOptionPane.showMessageDialog(frame, e.getMessage());
        }
    }
}

My Motor class public class Motor { boolean CW;

public void setMotor(Boolean CW, int increment, Robot r){
    if(CW == true){
        r.Set(1<<1);
    }
    else if (CW == false)
        ((Robot)r).Set(1<<2);

    r.increment = increment;
}

public void Engage(Robot r){
    System.out.println("Rotating: ");
    for(int i = 1; i <= r.increment; i++){
        r.Rotate(); 
    }   

    r.robotExecute();
    System.out.println("Finished");
}

}

and last my Main Class

public class Controller {

public static void main(String[] args){
    CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
    Motor m = new Motor();


    Robot xRob = new Robot(cyclicBarrier, m);
    Robot yRob = new Robot(cyclicBarrier, m);
    Robot zRob = new Robot(cyclicBarrier, m);

    Robot[] robotList = new Robot[]{xRob, yRob, zRob};

    Thread xRobThread = new Thread(xRob);
    Thread yRobThread = new Thread(yRob);
    Thread zRobThread = new Thread(zRob);

    ProgressBar prgBar = new ProgressBar(robotList);

    xRob.setOn(prgBar);
    yRob.setOn(prgBar);
    zRob.setOn(prgBar);

    boolean clockwise = true, counterClockwise = false;




    m.setMotor(clockwise, 14400000, xRob);
    m.setMotor(clockwise, 0, yRob);
    m.setMotor(counterClockwise, 36000000, zRob);

    xRobThread.start();
    yRobThread.start();
    zRobThread.start();

    try {
        xRobThread.join();
        yRobThread.join();
        zRobThread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }


    System.out.printf("x = %d y = %d z = %d\n\n", xRob.moveCount, yRob.moveCount, zRob.moveCount);

    /*m.setMotor(counterClockwise,  360000000, xRob);
    m.setMotor(clockwise, 1440000000, yRob);
    m.setMotor(clockwise, 1440000000, zRob);*/

}
}
1

There are 1 answers

2
Radiodef On BEST ANSWER

On investigation, you have a couple of problems.

The way you are creating your GUI is incorrect, so it is causing your JProgressBars to not appear in the frame.

Basically in ProgressBar(Robot[]) you are doing

frame.setSize(300, 200);
frame.setVisible(true);

before adding your progress bars and it is a problem. Calling setSize(...)...setVisible(true) before the children are added leads to unpredictable behavior. If you just move these two lines to after you add the progress bars, they should appear in the frame; however, what you are doing is not a good style.

I would recommend something like

Container pane = frame.getContentPane();
pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));

for(Robot r: robots) {
    JProgressBar bar = new JProgressBar();
    robotBars.put(r, bar);
    bar.setMinimum(0);
    bar.setMaximum(MAX);
    pane.add(bar);
}

frame.pack();
frame.setVisible(true);

Using a proper layout and calling pack to size the frame automatically.

You are also not creating your GUI on the EDT, basically your main logic needs to be wrapped in a call to invokeLater. This is complicated by your calls to join. Maybe a quick fix is something like:

public static void main(String[] args){
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            // ... create GUI ... create Threads ...

            new Thread(new Runnable() {
                @Override
                public void run() {
                    // ... start Threads ... join Threads ...
                }
            }).start();
        }
    }
}

You are not updating progress so progress is always 0.

I am not sure how you actually want to update the progress. For the purpose of testing I changed it to this:

//                               vv
prgBar.setProgress(this, progress++);

Once I did those things, I see the JProgressBars in the frame and I see them updating:

updating


Other things:

  • javax.swing.Timer would be a replacement for Threads. Maybe your Motor would create a Timer that did a rotation inside the timer event. This would be instead of calling sleep to manage your rotation increments.
  • Method names in Java start with a lowercase letter by convention. Your Set, Rotate, Engage, etc should be set, rotate, engage, etc.