Can a Progress Bar Be Used in a Class Outside Main

Can a progress bar be used in a class outside main?

SwingWorker is ideal for this. The example below performs a simple iteration in the background, while reporting progress and intermediate results in a window. You can pass whatever parameters you need in a suitable SwingWorker constructor.

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.DecimalFormat;
import java.util.List;
import javax.swing.*;

/** @see http://stackoverflow.com/questions/4637215 */
public class TwoRoot extends JFrame {

private static final String s = "0.000000000000000";
private JProgressBar progressBar = new JProgressBar(0, 100);
private JLabel label = new JLabel(s, JLabel.CENTER);

public TwoRoot() {
this.setLayout(new GridLayout(0, 1));
this.setTitle("√2");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(progressBar);
this.add(label);
this.setSize(161, 100);
this.setLocationRelativeTo(null);
this.setVisible(true);
}

public void runCalc() {
progressBar.setIndeterminate(true);
TwoWorker task = new TwoWorker();
task.addPropertyChangeListener(new PropertyChangeListener() {

@Override
public void propertyChange(PropertyChangeEvent e) {
if ("progress".equals(e.getPropertyName())) {
progressBar.setIndeterminate(false);
progressBar.setValue((Integer) e.getNewValue());
}
}
});
task.execute();
}

private class TwoWorker extends SwingWorker<Double, Double> {

private static final int N = 5;
private final DecimalFormat df = new DecimalFormat(s);
double x = 1;

@Override
protected Double doInBackground() throws Exception {
for (int i = 1; i <= N; i++) {
x = x - (((x * x - 2) / (2 * x)));
setProgress(i * (100 / N));
publish(Double.valueOf(x));
Thread.sleep(1000); // simulate latency
}
return Double.valueOf(x);
}

@Override
protected void process(List<Double> chunks) {
for (double d : chunks) {
label.setText(df.format(d));
}
}
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {

@Override
public void run() {
TwoRoot t = new TwoRoot();
t.runCalc();
}
});
}
}

Update progress bar from function outside the main class in Python Tkinter

You have used OOP.You could make the most of the class.I have reconstitute your code(Also,there is an error in your code):

from tkinter import ttk
import time
import tkinter as tk

class Main(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.buttonFrame = tk.Label(text="Progress Bar")
self.buttonFrame.grid(column=0,row=0)

self.progressBar = ttk.Progressbar(self, orient="horizontal", length=286,mode="determinate")
self.progressBar.grid(column = 0, row = 3, pady=10)

# this shouldn't be run() or self.run().No "()" there(Or you can use lambda if you need to pass arguments).
self.button1 = tk.Button(self.buttonFrame, text="Run Progress Bar" ,command = self.run)
self.button1.grid(column = 0, row = 0)

def run(self):
self.progressBar['maximum'] = 100
for i in range(0, 100, 25):
time.sleep(0.05)
self.progressBar["value"] = i
self.progressBar.update()
self.progressBar["value"] = 0
self.progressBar["value"] = 100


app = Main()
app.mainloop()

java - Progress Bar - Is it possible to use setProgess() of Progress Bar outside the doInBackground() method?

You state:

but when I put setProgess() inside the method of another class it tells me that I need to make that method.

This has nothing to do with SwingWorker and all to do with basic Java. No class can call another classes instance (non-static) methods without doing so on a valid instance of the class. For your code to work, the "other" method must call setProgress(...) on an instance of the SwingWorker, and so you must pass a reference of the SwingWorker to that other class. So pass the SwingWorker (this inside of the SwingWorker) into the other class, and then you can happily call its methods. Again, this has nothing to do with threading, Swing, or SwingWorkers, but rather is basic bread and butter Java.

Edit: since setProgress is protected and final, your SwingWorker will have to have a public method that the other class can call, and in this method the SwingWorker will need to call its own setProgress(...) method.

e.g.,

MyWorker class

public class MyWorker extends SwingWorker<Integer, Integer> {
private OtherClass otherClass;

public MyWorker() {
otherClass = new OtherClass(this);
}

@Override
protected Integer doInBackground() throws Exception {
otherClass.otherMethod();
return null;
}

// public method that exposes setProgress
public void publicSetProgress(int prog) {
setProgress(prog);
}

}

OtherClass:

class OtherClass {
MyWorker myWorker;

public OtherClass(MyWorker myWorker) {
this.myWorker = myWorker;
}

public void otherMethod() {
for (int i = 0; i < 100; i++) {
myWorker.publicSetProgress(i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {}
}
}
}

Updating the main form's progress bar from an external class?

Here's a loosely coupled approach, with the Logic() class raising a custom event instead of directly referencing the Form:

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
Logic logic = new Logic();
logic.Progress += new Logic.ProgressDelegate(DisplayProgess);
logic.Start();
}

public void DisplayProgess(string message, int percent)
{
if (this.InvokeRequired)
{
this.Invoke(new Logic.ProgressDelegate(DisplayProgess), new Object[] { message, percent });
}
else
{
this.label1.Text = message;
this.progressBar1.Value = percent;
}
}

}

public class Logic
{

private System.Threading.Thread T = null;

public delegate void ProgressDelegate(string message, int percent);
public event ProgressDelegate Progress;

public void Start()
{
if (T == null)
{
T = new System.Threading.Thread(new System.Threading.ThreadStart(Worker));
T.Start();
}
}

private void Worker()
{
RaiseProgress("Initializing...", 0);
System.Threading.Thread.Sleep(1000); // simulated work

RaiseProgress("Loading Map...", 25);
System.Threading.Thread.Sleep(1500); // simulated work

RaiseProgress("Loading Sprites...", 50);
System.Threading.Thread.Sleep(1200); // simulated work

RaiseProgress("Loading Sound Effects...", 75);
System.Threading.Thread.Sleep(1700);

RaiseProgress("Loading Music...", 85);
System.Threading.Thread.Sleep(1100); // simulated work

RaiseProgress("Done!", 100);
}

private void RaiseProgress(string message, int percent)
{
if (Progress != null)
{
Progress(message, percent);
}
}

}

Progress bar for loading out another JFrame class

Let your top-level container have a SwingWorker that loads it's content, as shown here, and a PropertyChangeListener, as shown here. When doInBackground() calls setProgress(), the listener will see the event.

Addendum: How do we know how much time left for the GUI to be completely loaded? …in examples, the progress bar is run with random number as simulated latency.

Correct; the simulated latency represents the granularity of your loading. Displaying the fraction of total bytes loaded would be ideal, but you may have to settle for a coarser frequency. Note that models may be constructed in the background, before any components are listening. GUI components should be constructed and manipulated only on the EDT, possibly in the worker's process() implementation.

Multi-threaded progress bar concurrency issue outside the main view controller

First, you are abusing NSUserDefaults in horrible ways. The documentation describes it as this...

The NSUserDefaults class provides a programmatic interface for
interacting with the defaults system. The defaults system allows an
application to customize its behavior to match a user’s preferences.
For example, you can allow users to determine what units of
measurement your application displays or how often documents are
automatically saved. Applications record such preferences by assigning
values to a set of parameters in a user’s defaults database. The
parameters are referred to as defaults since they’re commonly used to
determine an application’s default state at startup or the way it acts
by default.

You are using it to store a global variable.

Furthermore, you are completely abusing the user's CPU in your loop where you continuously are checking the value in the user defaults, and clipping off a selector to the main thread. "Abuse of the CPU" doesn't even come close to describing what this code is doing.

You should use NSProgress for reporting progress. There is a WWDC 2015 presentation dedicated exclusively to using NSProgress.


On to your core data usage.

Unfortunately, since you intentionally redacted all of the core data code, it's impossible to say what is going wrong.

However, based on what I see, you are probably trying to use that managed object context from your app delegate (which is probably still created with the deprecated confinement policy) from a background thread, which is a cardinal sin of the highest order as far as core data is concerned.

If you want to import data as a long running operation, use a private context, and execute the operations in the background. Use NSProgress to communicate progress to anyone wanting to listen.


EDIT

Thanks for the advice on my core data context usage. I digged into all
the contexts in my code and re-organized the contexts inside, the
conflict problem does not happen anymore. As for NSProgress , it's a
pity that the WWDC presentation focus on the feature on iOS 9 (while
my app must compact on iOS 8 devices). However, even though I use
NSProgress, I should still tell the main thread how many data the core
data (on another thread) already has, right? How does the thread on
NSProgress know the loading progress on my core data thread? –
whitney13625

You can still use NSProgress for iOS8, then only real difference is that you can't explicitly add children, but the implicit way still works, and that video explains it as well.

You really should watch the whole video and forget about the iOS9 part, except to know that you must add children implicitly instead of explicitly.

Also, this pre-iOS9 blog post should clear up any questions you have about it.



Related Topics



Leave a reply



Submit