Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[Java] Kan jProgressbar niet updaten

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik probeer een integer (die ik opvraag uit een andere klasse) te gebruiken in een jLabel maar dit wil natuurlijk niet lukken met mijn beperkte kennis van Java.

Onderstaande klasse ontvangt "int time" en "int[] jumps" van een andere klasse.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class skinning {

    static public int[] jumps = {0, 0, 0, 0};
    static public int time = 1;
    private timer Timer;

    public skinning() {
    }

    public void setJumps(int[] jumps) {
        this.jumps = jumps;
    }

    public int[] getJumps() {
        return jumps;
    }

    public void setTime(int time) {
        this.time = time;
    }

    public int getTime() {
        return time;
    }
}


Deze gegevens worden weer door de "get" methodes opgehaald door een jFrame. Deze jFrame activeert deze "get" methodes door een jLabel (MouseClick).

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Match extends javax.swing.JFrame {

    public skinning skin;

    public Match() {
        initComponents();
        jProgressBarTimeLeft.setMinimum(1);
        jProgressBarTimeLeft.setMaximum(30);
        
        skin = new skinning();
    }
   
    public void getProgres(){
      while (skin.getTime() != 0){
            try {

                Thread.sleep(200); 
            } catch (InterruptedException ex) {
                Logger.getLogger(Match.class.getName()).log(Level.SEVERE, null, ex);
            }

                int time = skin.getTime();
                int[] jumps = skin.getJumps();
               
                jProgressBarTimeLeft.setValue(time);
                jLabelStepsPlayer1.setText(Integer.toString(jumps[0]));
                jLabelStepsPlayer2.setText(Integer.toString(jumps[1]));
                jLabelStepsPlayer3.setText(Integer.toString(jumps[2]));
                jLabelStepsPlayer4.setText(Integer.toString(jumps[3]));
                System.out.println(jumps[0]);
                
                
      }
    }
    private void jLabelStartMouseClicked(java.awt.event.MouseEvent evt) {                                         
        skin.start();
        getProgres();
    }
  }


De System.out.println() zoals hierboven print de "jumps" prima. Alleen de jLabels worden helaas niet gevuld (de jumps zijn dus goed doorgespeeld maar werken niet in de jLabels).

Wat ik geprobeerd heb:
  • Uitvoeren van "getProgress" methode door middel van een andere thread (ook hier werkt System.out.println() wel maar niet het setten van de labels).
  • De jFrame opnieuw opmaken door middel van match.invalidate(), match.validate() en match.repaint() (Nog steeds geen tekst in labels en wel System.out.println())
(ik maak gebruik van NetBeans)

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 16-11 19:52

Gerco

Professional Newbie

Het lijkt erop dat je de event dispatch thread voor eeuwig in je getProgress() method vasthoudt. Als je die method in een eigen thread laat lopen en het displayen met SwingUtilities.invokeLater() doet, zal het waarschijnlijk wel goed werken. Ik neem aan dat je dat nog niet geprobeerd hebt, want je zegt niets over SwingUtilities in je TS.

Let wel op de thread safety van je skin.getJumps() method!

[ Voor 13% gewijzigd door Gerco op 21-05-2008 20:10 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • Mod_Aap
  • Registratie: Oktober 2004
  • Laatst online: 18-11 12:58
Ondertussen hebben we dit ook al geprobeerd:

Als er op de knop start wordt gedrukt:
Java: Match.java
152
153
154
155
private void jLabelStartMouseClicked(java.awt.event.MouseEvent evt) {                                         
        skin.start();
        
    new Thread(new getProgres()).start();}


De Thread die wordt gestart:
Java: getProges.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package Skinning;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Neil
 */
class getProgres implements Runnable{

  public void run() {
      skinning skin = new skinning();
      Match match = new Match();
      
      while (skin.getTime() != 0){
            try {

                Thread.sleep(200); } catch (InterruptedException ex) {
                Logger.getLogger(Match.class.getName()).log(Level.SEVERE, null, ex);
            }

                int time = skin.getTime();
                int[] jumps = skin.getJumps();
            
                
                match.jProgressBarTimeLeft.setValue(time);
                match.jLabelStepsPlayer1.setText(Integer.toString(jumps[0]));
                match.jLabelStepsPlayer2.setText(Integer.toString(jumps[1]));
                match.jLabelStepsPlayer3.setText(Integer.toString(jumps[2]));
                match.jLabelStepsPlayer4.setText(Integer.toString(jumps[3]));
                System.out.println("wassup");


  match.invalidate();
  match.validate();
  match.repaint(); 
                
      }
    }

}


De thread start nu wel, "wassup" wordt uitgeprint, het scherm locked niet meer (de knoppen blijven gewoon werken) maar toch worden de labels niet geupdate.

Is het niet zo dat met "SwingUtilities.invokeLater()" de labels pas zouden worden geupdate als de Thread klaar is? En waar zou ik dat dan neer moeten zetten?

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 16-11 19:52

Gerco

Professional Newbie

SwingUtilities.invokeLater() plaatst een runnable op de Swing event queue, deze zal dan uitgevoerd worden wanneer Swing daar tijd voor heeft. Over het algemeen is dat binnen enkele ms en niet pas wanneer je aanroepende thread klaar is.

Wat dat betreft is invokeLater() een wat bedrieglijke naam. Het komt erop neer dat je zegt: "Voer dit uit, maar ik wil er niet op wachten". Alle interactie met GUI componenten vanuit een andere thread *moet* in zo'n Runnable staan, want Swing is niet re-entrant.

Bijvoorbeeld:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
final int time = skin.getTime();
final int[] jumps = skin.getJumps();            

SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    match.jProgressBarTimeLeft.setValue(time);
    match.jLabelStepsPlayer1.setText(Integer.toString(jumps[0]));
    match.jLabelStepsPlayer2.setText(Integer.toString(jumps[1]));
    match.jLabelStepsPlayer3.setText(Integer.toString(jumps[2]));
    match.jLabelStepsPlayer4.setText(Integer.toString(jumps[3]));
    System.out.println("wassup");
  }
});


Overigens zou je met de code die je net postte een log vol met rare exceptions moeten hebben omdat je Swing aanroept vanuit een verkeerde thread.

[ Voor 6% gewijzigd door Gerco op 22-05-2008 11:43 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • Mod_Aap
  • Registratie: Oktober 2004
  • Laatst online: 18-11 12:58
Ik heb nu dit, maar het werkt helaas nogsteeds niet.

Java: Match.java
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
 private void jLabelStartMouseClicked(java.awt.event.MouseEvent evt) {                                         
//      Start Skinning
        skin.start();

//      Start new Tread
        SwingUtilities.invokeLater(new Runnable() {

//      Run new Treads
            public void run() {

//      Declare objects
                skinning skin = new skinning();
                Match match = new Match();

//      Run while time > 0
                while (skin.getTime() != 0) {
                    
//      Sleap tread (performance!)
                    try {Thread.sleep(200);} 
                        catch (InterruptedException ex) {
                        Logger.getLogger(Match.class.getName()).log(Level.SEVERE, null, ex);
                    }

//      Get time
                    int time = skin.getTime();
                
//      Get Jumps
                    int[] jumps = skin.getJumps();

//      Update labels en progres bar
                    match.jProgressBarTimeLeft.setValue(time);
                    match.jLabelStepsPlayer1.setText(Integer.toString(jumps[0]));
                    match.jLabelStepsPlayer2.setText(Integer.toString(jumps[1]));
                    match.jLabelStepsPlayer3.setText(Integer.toString(jumps[2]));
                    match.jLabelStepsPlayer4.setText(Integer.toString(jumps[3]));
                    System.out.println("wassup");


//      Revalidate and repaint Match frame
                    invalidate();
                    validate();
                    repaint();
                }

            }
        });
    }

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 16-11 19:52

Gerco

Professional Newbie

Omdat je nu weer de event tread aan het blokkeren bent. Je moet echt *alleen* de interactie met de GUI objecten in die Runnable zetten. Die wordt uitgevoerd en stopt weer. Je start geen nieuwe thread met invokeLater(), maar voert alleen een Runnable uit op de event dispatch thread. Die Runnable moet ook zo kort mogelijk duren, want zo lang die runt worden er geen events verwerkt.

Geen muis events, geen toetsenbord events en ook geen repaint events.

Start dus getProgress() in een nieuwe thread. Die nieuwe thread gaat dan elke 200ms de status ophalen en zo'n Runnable in de event queue zetten. Swing gaat die uitvoeren en ondertussen lopen zowel je getProgress() thread en je werk-thread (in de skin neem ik aan) gewoon verder. invalidate() en repaint() zijn overigens nergens voor nodig. Die plaatsen alleen een repaint request in de event queue, die nooit zal worden uitgevoerd omdat die bezig is met je getProgress() method.

Hier is een compleet, werkend voorbeeld wat doet alsof het 10 seconden zwaar werk doet en een progressbar en label update.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;


public class ProgressTest extends JFrame {
    
    private final JLabel label;
    private final JProgressBar progressBar;
    
    private volatile int amount;
    
    public ProgressTest() {
        super("Progressbar test");
        
        label = new JLabel();
        
        progressBar = new JProgressBar();
        progressBar.setMinimum(0);
        progressBar.setMaximum(10);
        
        JPanel panel = new JPanel(new BorderLayout());
        panel.add(label, BorderLayout.NORTH);
        panel.add(progressBar, BorderLayout.SOUTH);
        
        getContentPane().add(panel);
        
        setPreferredSize(new Dimension(200, 100));
        setLocation(400, 300);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        pack();
        
        // Start the work
        new Thread(new Runnable() {
            public void run() {
                doWork();
            }
        }).start();
        
        // Start the monitor thread
        new Thread(new Runnable() {
            public void run() {
                monitorProgress();
            }
        }).start();
        
        setVisible(true);
    } 
    
    protected void monitorProgress() {
        while(amount != 11) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
            
            final int amountDone = amount;
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    label.setText("Working on step " + amountDone);
                    progressBar.setValue(amountDone);
                }
            });
        }
        
        // We're done!
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                label.setText("All done!");
            }
        });
    }

    public void doWork() {

        // Fake working for 10 seconds
        for(amount = 1; amount <= 10; amount++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
        }
        
    }
    
    public static void main(String args[]) {
        new ProgressTest();
    }    
}

[ Voor 87% gewijzigd door Gerco op 22-05-2008 11:45 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • Mod_Aap
  • Registratie: Oktober 2004
  • Laatst online: 18-11 12:58
Is dit wat je bedoeld. (Update de labels helaas nogsteeds niet) :'(

Java: getProgres.java
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
    private void jLabelStartMouseClicked(java.awt.event.MouseEvent evt) {                                         

   skin.start();
        
        new Thread(new getProgres()).start();
        }
    
    public void UpdateScreen(int[] jumps, int time){
        final int[] showjumps = jumps;
        final int showtime = time;
        
        SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    jProgressBarTimeLeft.setValue(showtime);
                    jLabelStepsPlayer1.setText(Integer.toString(showjumps[0]));
                    jLabelStepsPlayer2.setText(Integer.toString(showjumps[1]));
                    jLabelStepsPlayer3.setText(Integer.toString(showjumps[2]));
                   jLabelStepsPlayer4.setText(Integer.toString(showjumps[3]));
                }
            }); 
                       
    }


Java: Match.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package Skinning;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Neil
 */
class getProgres implements Runnable{
    
    private int time;
    private int[] jumps;
    
    
  public void run() {
      skinning skin = new skinning();
      Match match = new Match();
      
      while (skin.getTime() != 0){
            try {

                Thread.sleep(200); } catch (InterruptedException ex) {
                Logger.getLogger(Match.class.getName()).log(Level.SEVERE, null, ex);
            }

                time = skin.getTime();
                jumps = skin.getJumps();
                System.out.println("wassup");
              
                match.UpdateScreen(jumps, time);

      }
    }

}



@Gerco
De code die je hebt gepost werkt trouwens niet. 7(8)7

[ Voor 71% gewijzigd door Mod_Aap op 22-05-2008 12:27 ]


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 16-11 19:52

Gerco

Professional Newbie

Hier anders wel. Direct copy/paste naar ProgressTest.java en opstarten. Ik post geen ongeteste code.

[ Voor 17% gewijzigd door Gerco op 22-05-2008 13:05 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!

Pagina: 1