Avatar billede stigc Nybegynder
12. november 2004 - 18:03 Der er 13 kommentarer og
1 løsning

Jlist og ListCellRenderer

Jeg har skrevet mig egen ListCellRenderer for at vinde lidt hastighed. Nå jeg kører JRE 1.5 er jeg nød til at kalde setMaximumSize, setMinimumSize, setPreferredSize før at rækkerne bliver synlige (Ellers er de 0 pixels høje). For det første undre jeg mig over hvordan jeg kan kalde disse metoder på Component, som jo ikke er en JComponent. For det andet virker dette ikke i 1.4 og før. Hvordan arver jeg fra Component, og får min rækker til at være synlige i JRE 1.3+


class ListCellRendererNew extends Component implements ListCellRenderer
{


    public ListCellRendererNew()
    {
        setMaximumSize(new Dimension(150,16));
        setMinimumSize(new Dimension(150,16));
        setPreferredSize(new Dimension(150,16));
    }



http://groups.google.dk/groups?q=%22extends+Component+implements+ListCellRenderer+%22&hl=da&btnG=Google-s%C3%B8gning
Avatar billede _carsten Nybegynder
12. november 2004 - 19:48 #1
Troede du havde løst den - (hvis den hænger sammen med et tidligere spørgsmål)

Prøv den her, fordeler ca. 60/40

  import java.awt.*;
  import javax.swing.*;
 
  public class ListLeaders {
    static class MyCellRenderer extends JPanel
          implements ListCellRenderer {
      JLabel left;
      JLabel right;
      MyCellRenderer() {
        setLayout(new GridBagLayout());
        left = new JLabel();
        right = new JLabel();
        left.setOpaque(true);
        right.setOpaque(true);
       
        GridBagConstraints gbc = new java.awt.GridBagConstraints();
        gbc.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gbc.weightx = 0.6;
        add(left, gbc);
       
        gbc.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gbc.weightx = 0.4;
        add(right, gbc);


      }
      public Component getListCellRendererComponent(
              JList list,
              Object value,
              int index,
              boolean isSelected,
              boolean cellHasFocus) {
       
       
        String leftData = ((String[])value)[0];
        String rightData = ((String[])value)[1];
        left.setText(leftData);
        right.setText(rightData);
        if (isSelected) {
          right.setBackground(
            list.getSelectionBackground());
          right.setForeground(
            list.getSelectionForeground());
          left.setBackground(
            list.getSelectionBackground());
          left.setForeground(
            list.getSelectionForeground());
        } else {
          right.setBackground(list.getBackground());
          right.setForeground(list.getForeground());
          left.setBackground(list.getBackground());
          left.setForeground(list.getForeground());
        }
        setEnabled(list.isEnabled());
        setFont(list.getFont());
       
        left.setPreferredSize( new Dimension(20 , 16));
        right.setPreferredSize(  new Dimension(10 , 16));
        return this;
      }
    }

    public static void main(String args[]) {
      JFrame frame = new JFrame("ListLeaders");
      frame.setDefaultCloseOperation(
        JFrame.EXIT_ON_CLOSE);
      Container contentPane = frame.getContentPane();
      String data[][] = {
        {"Tony Blair", "England"},
        {"Thabo Mbeki", "South Africa"},
        {"Megawati Soekarnoputri", "Indonesia"},
        {"Hosni Mubarak", "Egypt"},
        {"Vladimir Putin", "Russia"},
        {"Vicente Fox", "Mexico"},
        {"Ariel Sharon", "Israel"}
      };
      JList list = new JList(data);
      MyCellRenderer render = new MyCellRenderer();
      list.setCellRenderer( render );
      JScrollPane scrollPane = new JScrollPane(list);

      scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
      contentPane.add(scrollPane, BorderLayout.CENTER);
      System.out.println("" + scrollPane.getWidth());
      System.out.println("" + scrollPane.getInsets());
      frame.setSize(300, 150);
      frame.show();
    }
  }
Avatar billede stigc Nybegynder
12. november 2004 - 21:36 #2
Hej Carsten.

Ja jeg fik det løst. Problemet er bare er når man nu bruger JPanel, JLabels og så videre, så begynder en JList at performe rigtig dårlig. Derfor har jeg lavet min egen som arver fra Component. I paint metoden bruger jeg drawString og må derfor selv regne placerigen ud. Tilgengæld kan jeg få det præcis som jeg vil, og det perfomer meget bedre. Men det giver mig desværre dette problem med højden.
Avatar billede _carsten Nybegynder
12. november 2004 - 21:42 #3
Jeg tror problemet ligger et andet sted.

Hvor mange elementer har du i den JList ??

En JList som indeholder 1000 elementer, med en listCellRenderer som eksempelvis extender et JTextArea initieres på mindre end 1 sek.
Avatar billede stigc Nybegynder
12. november 2004 - 21:53 #4
Jeg har op mod 5000 elementer.
Avatar billede stigc Nybegynder
12. november 2004 - 21:54 #5
Men det er jo kun 20-30 stykker der synlige på en gang.
Avatar billede _carsten Nybegynder
12. november 2004 - 22:06 #6
Prøv lige at teste denne her med 100.000 elementer, jeg venter med at skifte cellRenderer til alt er fuldt initieret.

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

public class TestList extends javax.swing.JFrame {
    public TestList() {
        initComponents();
     
        long t1 = System.currentTimeMillis();

        list.setCellRenderer(new MyCellRenderer2());

        System.out.println("At skifte cellRenderer ved 100.000 elementer tog " +
                    (System.currentTimeMillis() - t1) + " millisekunder" );
    }
   
    private void initComponents() {
        data = new String[100000];
       
        for(int i = 0; i < 100000;i++){
            data[i] = Integer.toString(i);
        }

        jScrollPane1 = new javax.swing.JScrollPane();
        list = new javax.swing.JList(data);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        jScrollPane1.setViewportView(list);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

        pack();
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new TestList().setVisible(true);
            }
        });
    }

    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JList list;
    private String[] data;
}


    class MyCellRenderer2 extends JLabel implements ListCellRenderer {

      MyCellRenderer2() {
          setOpaque(true);
      }
     
      public Component getListCellRendererComponent(
              JList list,
              Object value,
              int index,
              boolean isSelected,
              boolean cellHasFocus) {
       
       
        if (isSelected) {
          setBackground(list.getSelectionBackground());
          setForeground(list.getSelectionForeground());
        } else {
          setBackground(list.getBackground());
          setForeground(list.getForeground());
        }
       
        setText(value.toString());
        setEnabled(list.isEnabled());
        setFont(list.getFont());
       
        return this;
      }
    }
Avatar billede stigc Nybegynder
12. november 2004 - 22:13 #7
Prøv så at holde "Page Down" nede og kig på dit CPU forbrug. Det er meget tungt.
Avatar billede stigc Nybegynder
12. november 2004 - 22:14 #8
At extende fra Component (JComponent er hel del langsommere) og at bruge drawString hjælper en del, men giver mig problemet med højden.
Avatar billede _carsten Nybegynder
12. november 2004 - 22:17 #9
Mit CPU forbrug ca. 5% højere end hvis jeg ikke adder en listCellRenderer
Avatar billede stigc Nybegynder
12. november 2004 - 22:24 #10
Jeg arbejder på en langsom CPU. Her er det tydligere : 70-80% ved ingen listCellRenderer, men 100% ved bare en simple listCellRenderer med flere JLables. Bruger jeg Component og drawString ryger jeg ned på 60-65%. Dvs. hurtigere end standard listCellRenderer!

Jeg ønsker også at bruge Component fordi det er meget flexibelt. Men jeg har stadigvæk problemer med højden. Har du set linket fra google?
Avatar billede _carsten Nybegynder
12. november 2004 - 22:29 #11
Mit CPU forbrug ca 25 - 30 % med og 18 - 25% uden

Og det betragter jeg egentlig ikke som noget problem ved 100.000 elementer, men er vi ikke der henne hvor antallet af elementer skal minimeres, en JList med 5000 elementer ville jeg betragte som uoverskuelig for brugeren.

Jeg har kun skimmet linket, men da dine CPU tal viser en mulighed vil jeg kigge på det. Vender tilbage i løbet af weekenden (nok ikke før søndag) håber det går.
Avatar billede stigc Nybegynder
12. november 2004 - 22:37 #12
Det lyder godt, og jo det begynder at blive uoverskueligt med så mange elementer. Performanve på JListen er ikke afhængig af antal elementer (og dog - sikkert lidt), men hvor stor JListen er på skærmen, og hvor tung ListCellRenderer'n er. Det må være muligt at kunne få det til at virke med Component, så jeg håber du finder tricket!
Avatar billede _carsten Nybegynder
13. november 2004 - 10:04 #13
Fik lige tid til at kigge på det her fra formiddagen af, og jeg må jo pænt give dig ret, man kan godt vinde op til 40% i CPU forbrug, man mister så også lidt af JLabels indbyggede funktionalitet, men har man ikke for den er det jo ligegyldigt.

Et Component object har per definition en størrelse på 0,0 indtil en sådan er defineret, derfor skal du som minimum override getPreferredSize() i klassen og derved give objectet en størrelse.

Du kan sikkert trimme denne cellRenderer en lille smule mere ved at lave en constructor der tager en JList som parameter og definere renderens farver udfra parameteren, i stedet for som jeg gjort at kalde list.getSelectionBackground() etc.

Jeg vil tillade mig at kalde det et svar!

Prøv den:  minJList.setCellRenderer( new LayoutColumnRenderer());


class LayoutColumnRenderer extends Component implements ListCellRenderer{
    public LayoutColumnRenderer(){
    } 

    public LayoutColumnRenderer(int width, int height){
        this.width = width;
        this.height = height;
    }
   
    public Dimension getPreferredSize(){
        return new Dimension(width, height);
    }
   
    public Component getListCellRendererComponent(
        JList list,
        Object value,
        int index,
        boolean isSelected,
        boolean hasFocus) {


        text = value.toString();
        this.list = list;
        this.select = isSelected;
       
        return this;
    }

    public void paint(Graphics g)  {
        if (select) {
            cb = list.getSelectionBackground();
            cf = list.getSelectionForeground();
        }
        else {
            cb = list.getBackground();
            cf = list.getForeground();
        }

        // udkommenter evt. denne linie og erstat fm.getAscent() med 2 eller 3
        // måske vinder du en brøkdel i performance ved det.
        fm = g.getFontMetrics(g.getFont());
       
        g.setColor(cb);
        g.fillRect(0,0, width, height);
        g.setColor(cf);
        g.drawString(text, 0, fm.getAscent());
    }
 
  private String text;
  private JList list;
  private boolean select;
  private Color cb, cf;
  private FontMetrics fm;
  private int width = 100, height = 16;
}
Avatar billede stigc Nybegynder
13. november 2004 - 10:42 #14
Meget fint svar. Jeg takker.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester