Avatar billede stigc Nybegynder
23. marts 2005 - 16:47 Der er 17 kommentarer og
1 løsning

Langsom KeyEvent.VK_ENTER ved Jlist

Jeg har en Jlist som implements KeyListener. Jeg lægger 25.000 strenge i listen, og oplever at et VK_ENTER keyevent tager meget lang tid. Andre keyevents kører fint både ved få og mange elementer. Er det en bug?


Opret en fil med følgende indhold


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

class Test extends JFrame
{

    JListTest jl = new JListTest();
    JScrollPane jsp = new JScrollPane(jl);
   
    public Test()
    {

        ArrayList al = new ArrayList();
        for (int i=0; i<25000; i++)
            al.add("test:" + i);

        jl.setListData(al.toArray());
        add(jsp);
    }
   
 
    public static void main(String args[])
    {
       
        System.out.println("Starting Test...");
        Test mainFrame = new Test();
        mainFrame.setSize(400, 400);
        mainFrame.setVisible(true);

    }
}


class JListTest extends JList implements KeyListener
{

    public JListTest()
    {
        addKeyListener(this);
    }

    public void keyTyped(KeyEvent e)
    {

    }

    public void keyPressed(KeyEvent e)
    {
        if (e.getKeyCode()==KeyEvent.VK_ENTER)
        {
            System.out.println("VK_ENTER");
              return;
        }    
        if (e.getKeyCode()==KeyEvent.VK_F1)
        {
            System.out.println("VK_F1");
              return;
        } 
    }
    public void keyReleased(KeyEvent e) {}
}
Avatar billede kalp Novice
23. marts 2005 - 16:51 #1
hmm jeg har lige haft brugt den til en ordbog jeg lavede (ikke noget avanceret) og der mærkede jeg ikke nogen forskel på den i forhold til hvis jeg havde valgt noget andet.

Jeg havde dog min kode i on keyReleased.
Avatar billede stigc Nybegynder
23. marts 2005 - 17:07 #2
Det er keyPressed jeg skal fange. Det sjove er at det ikke er keylistener der gør den langsom. Udkommenteres addKeyList

//addKeyListener(this);

så kan man stadigvæk mærke problemet. Marker listen, hold ENTER ned i et par sekunder og hele listen fryser.
Avatar billede stigc Nybegynder
23. marts 2005 - 17:10 #3
Har lige test det med JRE 1.3. Her er der ikke noget problem. I 1.4 lidt langsommer og til sidst 1.5, hvor den er rigtig langsom.
Avatar billede stigc Nybegynder
23. marts 2005 - 17:12 #4
Faktisk er følgende nok til at mærke problemet.


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

class Test extends JFrame
{

    JList jl = new JList();
    JScrollPane jsp = new JScrollPane(jl);
   
    public Test()
    {

        ArrayList al = new ArrayList();
        for (int i=0; i<25000; i++)
            al.add("test:" + i);

        jl.setListData(al.toArray());
        add(jsp);
    }
   
 
    public static void main(String args[])
    {
       
        System.out.println("Starting Test...");
        Test mainFrame = new Test();
        mainFrame.setSize(400, 400);
        mainFrame.setVisible(true);

    }
}
Avatar billede kalp Novice
23. marts 2005 - 18:05 #5
Jeg vil gerne lige lege lidt med det bliver dog lidt senere for er først hjemme en gang i aften:)
Avatar billede _carsten Nybegynder
23. marts 2005 - 18:11 #6
Du kan eventuelt adde denne CellRenderer til din JList - giver et helt andet billede

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

    public MyRenderer(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
23. marts 2005 - 18:25 #7
Hej Carsten. Den CellRenderer kender jeg godt. http://www.eksperten.dk/spm/560788

Men det handler slet ikke om renderen. Det handler om ENTER, som får JListen til at fryse, også selvom eventet slet ikke ændre JListen.
Avatar billede _carsten Nybegynder
23. marts 2005 - 18:45 #8
Det regnede jeg også med :)

Jo, det gør det - og det skyldes at en DefaultCellRenderer som extender JLabel, er langt tungere at gentegne og når du har så mange elementer i listen, er du nødt til at være kreativ for at opnå performance.
Avatar billede stigc Nybegynder
23. marts 2005 - 18:52 #9
Det handler IKKE om CellRenderer. Prøv det. Når jeg trykker ENTER gør jeg intet ved listen (Jeg fanger ikke engang eventet!), og dermed bliver CellRenderer heller ikke kørt.
Avatar billede stigc Nybegynder
23. marts 2005 - 18:53 #10
Og som jeg også skrev i http://www.eksperten.dk/spm/560788 handler det ikke om hvor mange elementer der er i listen, men hvor mange der er synlige på skærmen. :)
Avatar billede _carsten Nybegynder
23. marts 2005 - 19:51 #11
Okay, er med på hvad du mener (trykkede på F1 denne gang), jeg overgiver mig - ligger på ryggen, hel flad.

Det er fordi ENTER er "defaultButton" hvis en knap eller andet ikke specifikt er sat til defaultButton, det er en UI specifik handling.

Hvis du vil grave dybere i det skal du kigge på JRootPane, Look and Feel og noget UIManager.
Avatar billede stigc Nybegynder
31. marts 2005 - 22:29 #12
Er der nogen der har leget med det?
Avatar billede _carsten Nybegynder
12. april 2005 - 22:51 #14
Hvad sker der så når begynder at skrive bogstaver i JListen - ingenting ????
Avatar billede _carsten Nybegynder
12. april 2005 - 22:58 #15
Umiddelbart lyder det ikke som den rigtige løsning, da override af getNextMatch() og return -1 forhindrer søgning på næste match, og derved sætter en vigtigt del af JListens egenskaber ud af funktion, selfølgelig vil den virke i din situation, men rigtig - nej, det mener jeg absolut ikke
Avatar billede stigc Nybegynder
13. april 2005 - 18:46 #16
Ærlig talt, så forstår jeg ikke getNextMatch. Hvis man har en helt normal JList, så indeholder den da ikke "gå til elementet med forbogstavet jeg trykker"-funktionalitet. Den har jeg selv måtte implementere selv.
Avatar billede _carsten Nybegynder
13. april 2005 - 20:17 #17
Det er ikke nødvendigt selv at implementere den funktionalitet, det gør getNextMatch()

Prøv selv, klik på JListen og tryk på 'A'

public class JListTest extends javax.swing.JFrame {

    public JListTest() {
        initComponents();
    }
   
    private void initComponents() {
        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        jList1.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "A", "B", "C", "A", "D", "A" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollPane1.setViewportView(jList1);

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

        pack();
    }

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

    private javax.swing.JList jList1;
    private javax.swing.JScrollPane jScrollPane1;
}
Avatar billede stigc Nybegynder
13. april 2005 - 20:44 #18
Så må det være KeyListeneren der fjerner den. Den har jeg brug for.
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