Как я могу сделать прогрессивную полосу с помощью JProgressBar из Swing на Java?

Я новичок в параллельных вычислениях. Я работаю над Java в Apache Netbeans. Моя недавняя работа была посвящена семафорам с использованием Java-классов Semaphore и Thread. В этом смысле мне пришлось создать программу, которая с помощью индикаторов выполнения имитирует процесс доставки кредитной карты, который зависит от пяти подпроцессов (моделируемых с помощью потоков). Каждый подпроцесс имеет время, которое моделируется в программе, в данном случае с использованием метода сна из потоков. Реализация семафора заключается в постепенном увеличении общей панели в зависимости от других процессов. Если один из них завершен, его можно заполнить на общей панели. Еще следует добавить, что подпроцессы также имеют соответствующие индикаторы выполнения. Моя проблема возникает в классах BarraGeneral и SubProceso, они представляют собой общий процесс и один подпроцесс. В их переопределенных методах запуска я симулирую время и, конечно же, рисую, но этого не происходит. Я могу сказать, что это действительно работает, потому что на консоли вы можете проверить отпечатки, проблема, как я уже сказал, в том, что индикаторы не отражают этот прогресс, он просто меняется от 0% до 100%.

Я пытался решить эту проблему, уменьшив время симуляции сна, но проблема не в этом. Кроме того, я отладил, и столбцы фактически меняют свое значение на каждой итерации.

Код:

package espe.edu.ec.laboratorio1p2;

import java.util.ArrayList;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JProgressBar;

/**
 *
 * @author DARÍO BENAVIDES
 */
public class BarraGeneral extends Thread{
    
    private int id;
    private Semaphore aportes;
    private ArrayList<Integer> porcentajes;
    private int nHilos;
    private JProgressBar bar;
    
    BarraGeneral(int id, Semaphore aportes, ArrayList<Integer> porcentajes, int nHilos, JProgressBar bar){
        this.id = id;
        this.aportes = aportes;
        this.porcentajes = porcentajes;
        this.nHilos = nHilos;
        this.bar = bar;
    }
    
    @Override
    public void run(){
        int a;
        for(int i = 0; i < nHilos; i++){
            try {
                aportes.acquire();
                a = bar.getValue();
                bar.setValue(a + porcentajes.get(i));
                System.out.println(porcentajes.toString());
            } catch (InterruptedException ex) {
                Logger.getLogger(BarraGeneral.class.getName()).log(Level.SEVERE, null, ex);
            }
            
        }
    }
    
}

package espe.edu.ec.laboratorio1p2;

import java.util.ArrayList;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JProgressBar;
import javax.swing.event.ChangeListener;

/**
 *
 * @author DARÍO BENAVIDES
 */
public class SubProceso extends Thread{
    private Semaphore aportes;
    private int id;
    private int tiempo;
    private int porcentaje;
    private ArrayList<Integer> porcentajes;
    private JProgressBar bar;
    
    SubProceso(Semaphore aportes, int id, int tiempo, int porcentaje, ArrayList<Integer> porcentajes, JProgressBar bar){
        this.aportes = aportes;
        this.id = id;
        this.tiempo = tiempo;
        this.porcentaje = porcentaje;
        this.porcentajes = porcentajes;
        this.bar = bar;
    }
    
    @Override
    public void run(){
        for(int i = 1; i <= 100; i++){
            try{
                this.sleep(tiempo);
                bar.setValue(i);
            }catch(InterruptedException ex){
                Logger.getLogger(SubProceso.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        System.out.println(porcentaje);
        porcentajes.add(porcentaje);
        aportes.release();
    }
}

package espe.edu.ec.laboratorio1p2;

import java.util.ArrayList;
import java.util.concurrent.Semaphore;
import javax.swing.JProgressBar;

/**
 *
 * @author DARÍO BENAVIDES
 */
public class Laboratorio1P2 {

    public static void correr(JProgressBar barProgresoGeneral, 
            JProgressBar barProgreso1, JProgressBar barProgreso2, 
            JProgressBar barProgreso3, JProgressBar barProgreso4, 
            JProgressBar barProgreso5) {
        
        int nHilos = 5;
        Semaphore aportes = new Semaphore(0);
        ArrayList<Integer> porcentajes = new ArrayList<Integer>();
        ArrayList<SubProceso> subProcesos = new ArrayList<>();
        BarraGeneral barraGeneral = new BarraGeneral(1, aportes, porcentajes, nHilos, barProgresoGeneral);
        
        subProcesos.add(new SubProceso(aportes, 1, 50, 40, porcentajes, barProgreso1));
        subProcesos.add(new SubProceso(aportes,  2, 100, 10, porcentajes, barProgreso2));
        subProcesos.add(new SubProceso(aportes,  3, 100, 10, porcentajes, barProgreso3));
        subProcesos.add(new SubProceso(aportes, 4, 50, 5, porcentajes, barProgreso4));
        subProcesos.add(new SubProceso(aportes,  5, 100, 35, porcentajes, barProgreso5));
        
        barraGeneral.start();
        
        for(int i = 0; i < nHilos; i++){
            subProcesos.get(i).start();
        }
        
        while(barraGeneral.isAlive() || subProcesos.get(0).isAlive() || subProcesos.get(1).isAlive() || subProcesos.get(2).isAlive() ||
                subProcesos.get(3).isAlive() || subProcesos.get(4).isAlive()){
        }
    
    }
}


При нажатии на кнопку из JFrame я запускаю программу:

    private void iniciarActionPerformed(java.awt.event.ActionEvent evt) {                                        
        Laboratorio1P2.correr(barProgresoGeneral, barProceso1, barProceso2, 
                barProceso3, barProceso4, barProceso5);
        
    }    

Если вам нужна помощь, вам следует включить свой код в пример. Похоже, ты блокируешь EDT. Вероятно, вам понадобится SwingWorker, а затем вы сможете опубликовать его, чтобы обновить индикатор выполнения, не блокируя EDT.

matt 26.06.2024 22:23

Ваш код должен быть включен в тело вопроса в виде текста, а не ссылки или изображения. Кроме того, код должен представлять собой минимально воспроизводимый пример

Old Dog Programmer 26.06.2024 22:29

У Oracle есть полезное руководство Создание графического интерфейса с помощью Swing . Пропустите раздел «Обучение с использованием среды IDE NetBeans». Обратите особое внимание на Как использовать индикаторы выполнения. раздел. Добавьте в закладки и изучите остальную часть урока позже.

Gilbert Le Blanc 26.06.2024 23:27

Вы обновляете JProgressBar в потоке, который не является потоком отправки событий (EDT). См. Параллелизм в Swing.

Abra 27.06.2024 06:49

Это выглядит безумием. Тем не менее, у вас есть занятой цикл, который блокирует EDT. while(barraGeneral.isAlive() ||... означает, что edt не может обновиться до тех пор, пока все ваши темы не перестанут возвращать true для «isAlive».

matt 27.06.2024 09:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
5
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Похоже, что вы нажимаете кнопку, и у вас появляется основной процесс, который отслеживает ваши подпроцессы. По завершении подпроцесса ваш основной процесс обновляется.

Отключите цикл занятости, происходящий на EDT.

while(barraGeneral.isAlive() || subProcesos.get(0).isAlive() || subProcesos.get(1).isAlive() || subProcesos.get(2).isAlive() ||
            subProcesos.get(3).isAlive() || subProcesos.get(4).isAlive()){
    }

Все, что вы вызываете/используете из EDT, должно завершиться довольно быстро*. Этот занятый цикл блокирует EDT и предотвращает любую перерисовку или обновление.

*При этом есть предостережение, например, ожидание завершения диалога, в котором Swing/awt запускает другое EDT.

Я думаю, это самые маленькие изменения, которые «исправят» вашу проблему. Лично я бы удалил ваш BarraGeneral, так как он вам не нужен как еще одна тема. Измените свой SubProceso на SwingWorker, где метод «run» выполняет работу в фоновом режиме. Затем переопределите метод done, чтобы обновить общий индикатор выполнения. (Это происходит в EDT после завершения фоновой задачи. Там, где должны происходить все обновления индикатора выполнения!)

Спасибо за вашу помощь, я решил проблему, удалив цикл. Я ценю ваши рекомендации и собираюсь их реализовать, а также я читал SwingWorker, это действительно интересно. Причина, по которой я использовал то, что я использовал, заключается в том, что это были инструменты, которые показал нам мой профессор. У меня все еще есть один единственный вопрос: почему вы упоминаете, что моя реализация семафора сломана, потому что теперь, когда я запускаю свою программу, она постепенно заполняет подпанели, и когда одна из них завершена, заполняется общая полоса, поэтому я не знаю если это создает у меня впечатление, правильно это или нет.

ruper 27.06.2024 18:23

@ruper ты прав! Проверил поведение Семафора, ошибся как работает подсчет разрешений. Я обновлю ответ. Я думал, что о нескольких выпусках можно забыть, но они увеличивают разрешения и позволяют вашему циклу продолжаться несколько раз.

matt 27.06.2024 21:39

Да, точно так же, какacquire() уменьшает, Release() увеличивает разрешения, в любом случае ваша помощь была даже больше, чем мне нужно, я очень ценю ее.

ruper 28.06.2024 00:42

Другие вопросы по теме