2013-04-23 2 views
2

Проблема:Почему «javax.swing.JProgressBar» отображает новые значения поверх старых значений при обновлении из другого класса?

ClassA 
    static JProgressBar progressBar; 
ClassB 
    ClassA.progressBar.setValue(0); 
    ... 
    ClassA.progressBar.setValue(10); 
    ... 
    ClassA.progressBar.setValue(20); 

Прогресс бар показывает 0, то 10 на верхней части 0, то 20 на верхней части 10.

Код:

public class ClassA 
{ 
    static JProgressBar progressBar; 
    public ClassA() 
    { 
     ... 
     progressBar = new JProgressBar(0, 100); 
     progressBar.setStringPainted(true); 
     ... 
    } 
    public static void main(String[] args) 
    { 
     ClassA cA = new ClassA(); 
     cA.something(); 
    } 
    public void something() 
    { 
     ... 
     panel.add(progressBar, BorderLayout.CENTER); 
     ... 
    } 
    ... 
} 
public class ClassB 
{ 
    public void something() 
    { 
     ... 
     ClassA.progressBar.setValue(0); 
     ClassA.progressBar.update(ClassA.progressBar.getGraphics()); 
     ... 
    } 
    ... 
} 

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

EDIT: Проблема очень похожа на это: Java Swing revalidate() vs repaint(). Однако вместо

старое содержание по-прежнему на самом деле видно (хотя затемняется новым содержанием )

быть проблема с JPanel, шахта проблема с JProgressBar. Я пробовал ClassA.progressBar.revalidate(); и ClassA.progressBar.repaint();, но ничего не работает, кроме ClassA.progressBar.update(ClassA.progressBar.getGraphics());, который, как уже упоминалось выше, отображает новые значения поверх старых значений.

+0

Помогите опубликовать небольшой контекст, немного больше кода и немного больше объяснений? Кроме того, почему статическая переменная? –

+3

Вы получите лучшие ответы, если вы предоставите [SSCCE] (http://sscce.org/) – MadProgrammer

+0

@Hovercraft Full Of Eels, статическую переменную, потому что я устанавливаю значение без создания объекта. – Arthur

ответ

7

Вам не нужна эта строка:

ClassA.progressBar.update(ClassA.progressBar.getGraphics()); 

setValue() Вызов обновит прогресс бар UI.

Иначе нет ничего плохого в коде, который вы разместили здесь. Вопрос должен лежать в другом месте. Вот SSCCE, основанный на вашем коде, который работает так, как ожидалось, без проблем с краской.

public class ClassA { 
    static JProgressBar progressBar; 
    private ClassB classb; 
    private JPanel panel; 


    public ClassA() { 
     progressBar = new JProgressBar(0, 100); 
     progressBar.setStringPainted(true); 

     classb = new ClassB(); 

     JButton button = new JButton("test"); 
     button.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       classb.something(); 
      } 
     }); 

     panel = new JPanel(); 
     panel.add(button); 
     panel.add(progressBar, BorderLayout.CENTER); 
     JFrame frame = new JFrame(); 
     frame.add(panel); 
     frame.pack(); 
     frame.setVisible(true); 
    } 


    public static void main(String[] args) { 
     new ClassA(); 
    } 
} 

public class ClassB 
{ 
    private int index; 

    public void something() 
    { 
     ClassA.progressBar.setValue(++index); 
     //ClassA.progressBar.update(ClassA.progressBar.getGraphics()); 
    } 
} 
3

Arthur, ваш фрагмент кода не показывает, как вызываются вызовы ClassB.something. Большинство Swing не являются потокобезопасными, и если javadoc явно не указывает иначе, компоненты Swing ui необходимо изменить из Thread Dispatch Thread. Обычно, если компонент Swing является потокобезопасным, он явно вызывает это в javadoc. Я взглянул на JProgressBar javadoc и не увидел отказа от ответственности, на самом деле у него есть warning, что Swing не является потокобезопасным.
Если компоненты Swing доступны из других потоков, это может привести к тому, что приложения будут вести себя странно. Я видел, как компоненты отображались странно и не полностью из-за неправильной потоковой передачи. Если ClassA собирается создавать и изменять компоненты swing в конструкторе, конструктор должен быть выполнен из Thread Dispatch Thread.

public class ClassA 
{ 
    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(new ClassA()); 
    } 
} 
+0

+1, конечно, стоит попробовать, так как у нас нет никакого контекста, где это даже называется. – Brian