1

JProgressBar の最小値、値、および最大値を設定すると、ウィンドウを閉じて再度開かない限り更新されません。


写真:

ここに画像の説明を入力

誰でも私に洞察を与えることができますか?私はこれに頭を悩ませています。解析が正しく行われていることを確認するためにテストしました(つまり)。数値を直接入力するだけでテストしました。明らかに機能しますが、ウィンドウが初めて開かれたときに表示されないだけです(値を更新すると、最後の値のみが表示されると思います.

* 編集 *

紳士淑女の皆様... 差し上げてもいいですか... SSCCE. これを投稿して申し訳ありません。これで私の痛みを感じるでしょう:x


package com.jayavon.game.helper;

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

public class SSCCE extends JFrame implements WindowListener {

    private static final long serialVersionUID = 1L;
    JFrame frame;
    JPanel panel;
    JButton characterButton;
    JInternalFrame characterFrame;
    /* Character Window */
    JProgressBar totalExpProgressBar;

    Action ClassCharacterButton = new ClassCharacterButton();

    public static void main(String[] args){
        //for thread safety     
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new SSCCE();
            }
        });
    }

    SSCCE() {
        initGUI();
    }

    public void initGUI(){

        frame = new JFrame("SSCCE");
        panel = (JPanel)frame.getContentPane();

        /**********************************
         ** 
         **     Buttons
         **    
         *********************************/
        characterButton = new JButton("");
        characterButton.setBounds(50,175,395,100);
        characterButton.setVisible(true);
        characterButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("C"), "characterButtonPress");
        characterButton.getActionMap().put("characterButtonPress", ClassCharacterButton);
        characterButton.setAction(ClassCharacterButton);
        characterButton.setText("Click me three times(open/close/open) to get progress bar to fill");
        panel.add(characterButton);

        /**********************************
         ** 
         **     Internal Frames
         **    
         *********************************/
        //#### Character frame start ####
        characterFrame = new JInternalFrame("Character", true, true, false, false);
        characterFrame.setLocation(50, 50);
        characterFrame.setSize(300,105);

        totalExpProgressBar = new JProgressBar();
        totalExpProgressBar.setString("0/0");
        totalExpProgressBar.setStringPainted(true);

        characterFrame.add(totalExpProgressBar);
        characterFrame.setResizable(false);
        panel.add(characterFrame);
        //#### Character frame end ####

        /**********************************
         ** 
         **     Panel Code
         **    
         *********************************/
        panel.setLayout(null);
        panel.setFocusable(true);

        /**********************************
         ** 
         **     Frame Code
         **    
         *********************************/
        frame.setLocation(100, 100);
        frame.setSize(500, 350);
        frame.setVisible(true);
        frame.setFocusable(true);
        frame.addWindowListener(this);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    class ClassCharacterButton extends AbstractAction {  
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            if (characterFrame.isVisible()){
                characterFrame.setVisible(false);
            } else {
                fakeGetServerResponse();
            }
        }
    }

    public void fakeGetServerResponse(){
        String incommingReply = "proskier-charactersWindow@20|10|10|10|0|234|3|200|400"; //fake message from server
        final String splitAt[] = incommingReply.split("@"); //split the character name from the incommingReply at the '@' sign
        String beforeAt[] = splitAt[0].split("-");
        String commandName = beforeAt[1];
        final String afterAt[] = splitAt[1].split("\\|");

        if (commandName.equals("charactersWindow")){
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    totalExpProgressBar.setString(afterAt[5] + "/" + afterAt[8]);
                    totalExpProgressBar.setMinimum(0);
                    totalExpProgressBar.setMinimum(Integer.parseInt(afterAt[7])); //TODO::SCREW YOU JAVA
                    totalExpProgressBar.setValue(Integer.parseInt(afterAt[5]));   //TODO::SCREW YOU JAVA
                    totalExpProgressBar.setMaximum(Integer.parseInt(afterAt[8])); //TODO::SCREW YOU JAVA
                    characterFrame.setVisible(true);
                }
            });
        }
    }

    @Override
    public void windowClosing(WindowEvent arg0){
        frame.dispose();
        System.exit(1);
    }
    @Override
    public void windowActivated(WindowEvent arg0) {
    }
    @Override
    public void windowClosed(WindowEvent arg0) {
    }
    @Override
    public void windowDeactivated(WindowEvent arg0) {
    }
    @Override
    public void windowDeiconified(WindowEvent arg0) {           
    }
    @Override
    public void windowIconified(WindowEvent arg0) {
    }
    @Override
    public void windowOpened(WindowEvent arg0) {            
    }
}
4

3 に答える 3

4

おそらくEDT(イベントディスパッチスレッド)で作業を行っています。このスレッドにはイベントのキューがあり、AWTはスレッドセーフではないため、イベントは一度に1つずつ順番にディスパッチされます。これにより、UIを更新してイベント(repaintやinvokeLaterなどのプログラムイベント、またはマウスやキーイベントなどのユーザーイベント)に反応することができます。

したがって、EDTで作業するときは、スレッドをブロックし、再描画、クリック、キーイベントなどのイベントをディスパッチしないようにします...

通常、解決策は、たとえばSwingWorkerを使用して、作業を別のスレッドに移動することです。

ところで、Thread.sleep(long)は静的メソッドなので、currentThread()を呼び出す必要はありません。必要な場合は、Thread.sleep(...)を呼び出すだけです。ただし、EDTはブロックされ、UIもブロックされるため、EDTではこれを行わないようにする必要があります。

于 2012-04-26T22:36:11.793 に答える
3

this is valid for all Swing JComponents, Runnable and Thread.sleep(int) with quasi animations to the GUI

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

public class ShakingButtonDemo implements Runnable {

    private JButton button;
    private JRadioButton radioWholeButton;
    private JRadioButton radioTextOnly;

    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeLater(new ShakingButtonDemo());
    }

    @Override
    public void run() {
        radioWholeButton = new JRadioButton("The whole button");
        radioTextOnly = new JRadioButton("Button text only");
        radioWholeButton.setSelected(true);
        ButtonGroup bg = new ButtonGroup();
        bg.add(radioWholeButton);
        bg.add(radioTextOnly);
        button = new JButton("  Shake with this Button  ");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                shakeButton(radioWholeButton.isSelected());
            }
        });
        JPanel p1 = new JPanel();
        p1.setBorder(BorderFactory.createTitledBorder("Shake Options"));
        p1.setLayout(new GridLayout(0, 1));
        p1.add(radioWholeButton);
        p1.add(radioTextOnly);
        JPanel p2 = new JPanel();
        p2.setLayout(new GridLayout(0, 1));
        p2.add(button);
        JFrame frame = new JFrame();
        frame.setTitle("Shaking Button Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(p1, BorderLayout.NORTH);
        frame.add(p2, BorderLayout.SOUTH);
        frame.setSize(240, 160);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void shakeButton(final boolean shakeWholeButton) {
        final Point point = button.getLocation();
        final Insets margin = button.getMargin();
        final int delay = 75;
        Runnable r = new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 30; i++) {
                    try {
                        if (shakeWholeButton) {
                            moveButton(new Point(point.x + 5, point.y));
                            Thread.sleep(delay);
                            moveButton(point);
                            Thread.sleep(delay);
                            moveButton(new Point(point.x - 5, point.y));
                            Thread.sleep(delay);
                            moveButton(point);
                            Thread.sleep(delay);
                        } else {// text only
                            setButtonMargin(new Insets(margin.top, margin.left + 3, margin.bottom, margin.right - 2));
                            Thread.sleep(delay);
                            setButtonMargin(margin);
                            Thread.sleep(delay);
                            setButtonMargin(new Insets(margin.top, margin.left - 2, margin.bottom, margin.right + 3));
                            Thread.sleep(delay);
                            setButtonMargin(margin);
                            Thread.sleep(delay);
                        }
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }

    private void moveButton(final Point p) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                button.setLocation(p);
            }
        });
    }

    private void setButtonMargin(final Insets margin) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                button.setMargin(margin);
            }
        });
    }
}

EDIT

example SwingWorker and JProgressBar & SwingWorker#cancel()

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

public class SwingWorkerExample extends JFrame implements ActionListener {

    private static final long serialVersionUID = 1L;
    private final JButton startButton, stopButton;
    private JScrollPane scrollPane = new JScrollPane();
    private JList listBox = null;
    private DefaultListModel listModel = new DefaultListModel();
    private final JProgressBar progressBar;
    private mySwingWorker swingWorker;

    public SwingWorkerExample() {
        super("SwingWorkerExample");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setLayout(new GridLayout(2, 2));
        startButton = makeButton("Start");
        stopButton = makeButton("Stop");
        stopButton.setEnabled(false);
        progressBar = makeProgressBar(0, 99);
        listBox = new JList(listModel);
        scrollPane.setViewportView(listBox);
        add(scrollPane);
        //Display the window.
        pack();
        setVisible(true);
    }
//Class SwingWorker<T,V> T - the result type returned by this SwingWorker's doInBackground
//and get methods V - the type used for carrying out intermediate results by this SwingWorker's
//publish and process methods

    private class mySwingWorker extends javax.swing.SwingWorker<ArrayList<Integer>, Integer> {
//The first template argument, in this case, ArrayList<Integer>, is what s returned by doInBackground(),
//and by get(). The second template argument, in this case, Integer, is what is published with the
//publish method. It is also the data type which is stored by the java.util.List that is the parameter
//for the process method, which recieves the information published by the publish method.

        @Override
        protected ArrayList<Integer> doInBackground() {
//Returns items of the type given as the first template argument to the SwingWorker class.
            if (javax.swing.SwingUtilities.isEventDispatchThread()) {
                System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() returned true.");
            }
            Integer tmpValue = new Integer(1);
            ArrayList<Integer> list = new ArrayList<Integer>();
            for (int i = 0; i < 100; i++) {
                for (int j = 0; j < 100; j++) { //find every 100th prime, just to make it slower
                    tmpValue = FindNextPrime(tmpValue.intValue());
//isCancelled() returns true if the cancel() method is invoked on this class. That is the proper way
//to stop this thread. See the actionPerformed method.
                    if (isCancelled()) {
                        System.out.println("SwingWorker - isCancelled");
                        return list;
                    }
                }
//Successive calls to publish are coalesced into a java.util.List, which is what is received by process,
//which in this case, isused to update the JProgressBar. Thus, the values passed to publish range from
//1 to 100.
                publish(new Integer(i));
                list.add(tmpValue);
            }
            return list;
        }//Note, always use java.util.List here, or it will use the wrong list.

        @Override
        protected void process(java.util.List<Integer> progressList) {
//This method is processing a java.util.List of items given as successive arguments to the publish method.
//Note that these calls are coalesced into a java.util.List. This list holds items of the type given as the
//second template parameter type to SwingWorker. Note that the get method below has nothing to do with the
//SwingWorker get method; it is the List's get method. This would be a good place to update a progress bar.
            if (!javax.swing.SwingUtilities.isEventDispatchThread()) {
                System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() + returned false.");
            }
            Integer percentComplete = progressList.get(progressList.size() - 1);
            progressBar.setValue(percentComplete.intValue());
        }

        @Override
        protected void done() {
            System.out.println("doInBackground is complete");
            if (!javax.swing.SwingUtilities.isEventDispatchThread()) {
                System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() + returned false.");
            }
            try {
//Here, the SwingWorker's get method returns an item of the same type as specified as the first type parameter
//given to the SwingWorker class.
                ArrayList<Integer> results = get();
                for (Integer i : results) {
                    listModel.addElement(i.toString());
                }
            } catch (Exception e) {
                System.out.println("Caught an exception: " + e);
            }
            startButton();
        }

        boolean IsPrime(int num) { //Checks whether a number is prime
            int i;
            for (i = 2; i <= num / 2; i++) {
                if (num % i == 0) {
                    return false;
                }
            }
            return true;
        }

        protected Integer FindNextPrime(int num) { //Returns next prime number from passed arg.
            do {
                if (num % 2 == 0) {
                    num++;
                } else {
                    num += 2;
                }
            } while (!IsPrime(num));
            return new Integer(num);
        }
    }

    private JButton makeButton(String caption) {
        JButton b = new JButton(caption);
        b.setActionCommand(caption);
        b.addActionListener(this);
        getContentPane().add(b);
        return b;
    }

    private JProgressBar makeProgressBar(int min, int max) {
        JProgressBar progressBar1 = new JProgressBar();
        progressBar1.setMinimum(min);
        progressBar1.setMaximum(max);
        progressBar1.setStringPainted(true);
        progressBar1.setBorderPainted(true);
        getContentPane().add(progressBar1);
        return progressBar1;
    }

    private void startButton() {
        startButton.setEnabled(true);
        stopButton.setEnabled(false);
        System.out.println("SwingWorker - Done");
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if ("Start" == null ? e.getActionCommand() == null : "Start".equals(e.getActionCommand())) {
            startButton.setEnabled(false);
            stopButton.setEnabled(true);
// Note that it creates a new instance of the SwingWorker-derived class. Never reuse an old one.
            (swingWorker = new mySwingWorker()).execute(); // new instance
        } else if ("Stop" == null ? e.getActionCommand() == null : "Stop".equals(e.getActionCommand())) {
            startButton.setEnabled(true);
            stopButton.setEnabled(false);
            swingWorker.cancel(true); // causes isCancelled to return true in doInBackground
            swingWorker = null;
        }
    }

    public static void main(String[] args) {
// Notice that it kicks it off on the event-dispatching thread, not the main thread.
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                SwingWorkerExample swingWorkerExample = new SwingWorkerExample();
            }
        });
    }
}
于 2012-04-26T23:17:53.473 に答える
1

問題は、プログレス バーの値を設定した後に最大値を設定すると、値が最小値にリセットされることです。

import javax.swing.*;

public class ProgressBarMinValue {
   private static void createAndShowGui() {
      JProgressBar progressBar = new JProgressBar();

      int value = 234;
      int denominator = 400;
      int minValue = 200;
      progressBar.setString(value + "/" + denominator);
      progressBar.setMinimum(minValue);
      System.out.println("value := " + value);

      progressBar.setValue(value);  // (A)

      progressBar.setMaximum(denominator);

      // progressBar.setValue(value);  // (B)

      JPanel mainPanel = new JPanel();
      mainPanel.add(progressBar);

      JOptionPane.showMessageDialog(null, mainPanel);
      System.out.println("progressBar.getValue() := " + progressBar.getValue());
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

コメント行とコメント解除行 (A) と (B) を入れ替えて、最小値と最大値を設定したにプログレス バーの値を設定すると、すべてがうまく機能することを確認します。

そして、それがあなたの解決策です。

この最小限の SSCCE は、問題が再現できなくなるまでコードを継続的に削り取ることによって得られたことに注意してください。

于 2012-04-28T02:15:59.533 に答える