2013-04-17 4 views
5

Я создал свой собственный CellRenderer, который содержит несколько строк и JProgressBar в элементе JList ... Но JProgressBar, и поэтому весь элемент JList будет нарисован один раз, и я ищу способ перекрасить Элементы ... Я попытался начать нить, которая будет постоянно перерисовываться ... Но я не знаю, что мне нужно перерисовать, чтобы получить результат ...CellRenderer Item repaint

JList repaint ... нет результата CellRenderer repaint ... нет результата JFrame repaint ... нет результата

Кто-нибудь понимает мою проблему и знает выход?

спасибо!

UPDATE: [Update удалено]

СЛЕДУЮЩИЙ UPDATE:

import java.awt.Component; 
import java.awt.Dimension; 
import javax.swing.DefaultListModel; 
import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.JPanel; 
import javax.swing.JProgressBar; 
import javax.swing.ListCellRenderer; 


public class Main extends JFrame{ 

public DefaultListModel contentListModel = new DefaultListModel(); 
public MyCellRenderer MCR = new MyCellRenderer(); 
public JList contentList = new JList(contentListModel); 

public Main(){ 
    super("Example"); 
    setMinimumSize(new Dimension(300,300)); 
    setDefaultCloseOperation(EXIT_ON_CLOSE); 
    contentList.setCellRenderer(MCR); 
    contentListModel.addElement(""); 
    contentListModel.addElement(""); 
    add(contentList); 
} 

public static void main(String[] args){ 
    new Main().setVisible(true); 
} 

class MyCellRenderer extends JPanel implements ListCellRenderer{ 

    public MyCellRenderer(){ 
     JProgressBar jpb = new JProgressBar(); 
     jpb.setIndeterminate(true); 
     add(jpb); 
    } 

    @Override 
    public Component getListCellRendererComponent(JList arg0, Object arg1, 
      int arg2, boolean arg3, boolean arg4) { 
     // TODO Auto-generated method stub 
     return this; 
    } 



} 

} 
+0

[SSCCE] (http://sscce.org/) первым, второй ответ;) – MadProgrammer

+0

для лучшей помощи рано ВЫВЕШИТ [SSCCE] (http://sscce.org/), краткое, выполнимое, компилируемое, только около вопроса – mKorbel

+0

Чтобы превратить 2 исходных файла в SSCCE, только один объявленный как 'public'. Добавьте источник для второго класса, в конец источника для первого. –

ответ

0

Это легко.

public void updateListData(final JList myList) { 
    SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     ListModel lm = myList.getModel(); 
     DefaultListModel dlm = new DefaultListModel(); 
     for (int i = 0; i < lm.getSize(); i++) { 
     dlm.addElement(lm.getElementAt(i)); 
     } 
     myList.setModel(dlm); 
    } 
    }); 
} 

Код, указанный выше, может быть вызван из EDT и из другого потока. Но вы также должны прочитать, как работать с компонентами Swing и понимать модели (ListModel, TableModel и т. Д.). Чтобы попросить элемент в JList перерисовать, вы должны изменить его объект в модели.

+0

Это ничего не изменит. Кроме того, это перебор, чтобы воссоздать весь ListModel с тем же значением. Вы можете просто вызвать 'myList.repaint()', чтобы иметь тот же эффект (что еще не решило бы проблему). –

+0

@ Сергий Медвинский не отвечает на ListCellRenderer, пожалуйста, удалите этот ответ – mKorbel

2

Ящики для ячеек представляют собой статические/резиновые штампы компонентов, они не являются «настоящими», активными компонентами. Они просто «окрашиваются» на поверхность вида, который их использует.

Это означает, что на самом деле невозможно перекрасить их как таковые. Вы можете рекомендовать обновить список, изменив значение строки, которую вы хотите изменить. Это заставит модель инициировать обновление, которое приведет к перерисовке списка.

import java.awt.BorderLayout; 
import java.awt.Component; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.DefaultListModel; 
import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.JProgressBar; 
import javax.swing.JScrollPane; 
import javax.swing.ListCellRenderer; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TestProgressListCellRenderer { 

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

    public TestProgressListCellRenderer() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       final DefaultListModel<Float> model = new DefaultListModel<>(); 
       model.addElement(0f); 

       JList<Float> list = new JList<>(model); 
       list.setCellRenderer(new ProgressListCellRenderer()); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new JScrollPane(list)); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       Timer timer = new Timer(125, new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         float value = model.getElementAt(0); 
         value += 0.01; 
         if (value >= 1f) { 
          value = 1f; 
          ((Timer)e.getSource()).stop(); 
         } 
         model.setElementAt(value, 0); 
        } 
       }); 
       timer.setRepeats(true); 
       timer.setCoalesce(true); 
       timer.start(); 

      } 
     }); 
    } 

    public class ProgressListCellRenderer extends JProgressBar implements ListCellRenderer<Float> { 

     @Override 
     public Component getListCellRendererComponent(JList<? extends Float> list, Float value, int index, boolean isSelected, boolean cellHasFocus) { 
      setValue(Math.round(value * 100)); 
      return this; 
     }    
    }   
} 

Это простой пример, и я попытался с помощью setIndeterminate, но я не мог заставить его обновить (очень раздражает), но это может вызвать некоторые идеи

+0

Так что, возможно, лучше работать с JPanel без JList, ListModel и CellRenderer и развивать только поведение ... –

+1

Проблема с setIndeterminate заключается в том, что ProgressBarUI фактически использует Таймер для ускорения анимации. Однако это делается только в том случае, если JProgressBar является «отображаемым», что никогда не происходит из-за всего механизма JList-рендеринга. Я не уверен, что его можно легко выполнить с помощью JList. Я считаю, что было бы проще использовать компоненты «Live» (но я жду, чтобы их доказали неправильно) –

+0

@TobiasRaphaelDieckmann Я бы «предложил» добавить «JProgressBar» непосредственно в 'JList', но Kleo будет охотиться на меня вниз и делать неприятные вещи для меня ... – MadProgrammer

2
  • +1 за интересный вопрос ,

  • Renderer но в свинге не предназначен к показу анимации, это только статическая картина, иллюзия, снимок,

  • вы должны оживить этот объект в вашем коде, но не легкая работа для JProgressBar.setIndeterminate(true);, если это возможно без грязных хаков,

    1. требуется собственным JProgressBar

    2. требуется собственная анимация для ListCellRenderer, и результат может быть до сих пор по сравнению с JProgressBar, размещенным в JPanel eg


  • Я думаю JList не может быть надлежащим JComponents, используйте JTable с одной колонной и/или без JTableHeader

  • простой обходной путь использовать JPanel (по GridLayout заложен) с JProgressBars для JProgressBar.setIndeterminate(true);, то вывод в GUI Swing будет очень похожей к JTable (без JTableHeader или JList)

    1. положить этот JPanel к JScrollPane

    2. переназначения getPreferredSize для JScrollPane, то вы будете моделировать JList.setVisibleRowCount правильно

    3. изменение JScrollBar.setUnitIncrement для естественного прокруткой для JPanel с JComponents и с JList, JTable, JTextArea поместил i п JScrollPane

+0

+1 для обеспечения решения с помощью живых компонентов. –

3

Вы можете быть в состоянии вести анимацию с вашим собственным javax.swing.Timer в обычае ProgressBarUI, видели here; incrementAnimationIndex() выглядит многообещающе, но я не пробовал.

image

Absent лучшее решение, вы можете использовать ProgressIcon в DefaultListCellRenderer; подход иллюстрируется here в JTabbedPane.

image

3

Как уже упоминалось, рендеры не живут компоненты, которые не являются частью компонента иерархии. Следовательно, «естественные» эффекты анимации (такие как f.i. движение неопределенного шага прогресса) теряются. Трюк, который может сработать, но будьте осторожны: это сильно зависит от LAF! - заключается в том, чтобы лежать в системе и сообщать о том, что бар всегда доступен. Это в сочетании с таймером притворяется новое значение каждый х мс может показать анимацию снова:

public static class ProgressBarRenderer implements TableCellRenderer { 

    /** The bar. */ 
    private JProgressBar indeterminate = new JProgressBar() { 
     // fake displayable to trigger ui animation 
     @Override 
     public boolean isDisplayable() { 
      return true; 
     }; 
    }; 

    /** The bar. */ 
    private JProgressBar determinate = new JProgressBar() ; 

    public ProgressBarRenderer() { 
     indeterminate.setStringPainted(true); 
     indeterminate.setIndeterminate(true); 
     indeterminate.setString(null); 
    }  

    @Override 
    public Component getTableCellRendererComponent(JTable table, 
      Object value, boolean isSelected, boolean hasFocus, int row, 
      int column) { 
     int pbi = (Integer) value; 
     if (pbi < 0) { 
      return indeterminate; 
     } 
     determinate.setValue(pbi); 
     return determinate; 
    } 
} 

// a timer driving the animation 
Action update = new AbstractAction() { 

    int count; 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     table.setValueAt(-1, 0, AncientSwingTeam.INTEGER_COLUMN); 
    } 

}; 
new Timer(100, update).start();