Pergunta

Eu tenho o próximo código:

    listModel = new DefaultListModel();
    listModel.addElement(dateFormat.format(new Date()) + ": Msg1");
    messageList = new JList(listModel);
    messageList.setLayoutOrientation(JList.VERTICAL);

    messageScrollList = new JScrollPane(messageList);
    messageScrollList.setPreferredSize(new Dimension(500, 200));

    messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
        }
    }); 

Ele rola automaticamente para baixo.Mas, se eu tentar rolar para cima para reler uma mensagem, isso forçará a rolagem para baixo.Como posso consertar isso?

Foi útil?

Solução

Ao adicionar uma nova mensagem, invocar scrollRectToVisible() no JList usando um Rectangle Tendo as mesmas dimensões que o tamanho preferido do seu painel. Dada uma orientação vertical, pode ser conveniente fazer o tamanho preferido do JScrollPane's JViewport Um múltiplo integral da altura do painel de mensagens. Veja também: Como usar painéis de rolagem.

Adendo: esta discussão convincente de Rolagem da área de texto Pode ser útil também.

Outras dicas

Eu achei isso realmente útil:http://forums.sun.com/thread.jspa?threadid=623669 (Post by 'Inopia')
Funciona perfeitamente

Como ele diz: "O problema aqui é que pode se tornar um pouco difícil encontrar um evento que dispara depois que o ListModel, JList e JScrollPane foram atualizados".

this.list = blah blah... 
this.list.setSelectedValue(whatever);   
final JScrollPane sp = new JScrollPane(this.list); // needs to be after the parent is the sp 
this.list.ensureIndexIsVisible(this.list.getSelectedIndex());

@Question Enquirer. Altere seu código de

messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
        }
    });

para

messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getValue());  
        }
    }); 

Isso é mudança getMaximum() para getValue() Então funciona conforme necessário. getMaximum() leva o rolador ao máximo; enquanto getValue() leva para onde quer que o evento aconteça.

Você pode evitar usar esse pedaço de código se você colocar uma linha

messageScrollList.setViewportView(messageList);

Isso funciona como add(component) para JList e recebe seu comportamento inerente.

Para rolar automaticamente, estou usando um conceito muito simples de variável estática e list.makeVisible (Int Index)

    public class autoScrollExample
    {
     static int index=0;
     private void someFunction()
     /*   
     * 
     */
     list1.add("element1");
     list1.makeVisible(index++);
     /*
     *
     */

     private void someOtherFunction()
     /*   
     * 
     */
     list1.add("element2");
     list1.makeVisible(index++);
     /*
     *
     */


    }

eu usei JScrollPane com JTextArea.Evitei forçar a rolagem para baixo rolando apenas quando JScrollBar max valor alterado:

        JScrollPane scrollPane = new JScrollPane(jTextArea);

        verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
        scrollPane.getVerticalScrollBar().addAdjustmentListener(
                e -> {
                    if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0)
                        return;
                    e.getAdjustable().setValue(e.getAdjustable().getMaximum());
                    verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
                });

Suponho que exista uma solução melhor para filtrar eventos sem variáveis ​​extras, e agradeceria se alguém publicasse isso.

Eu acho que o que você quer fazer é rolar para baixo quando você adicionar coisas ao seu messagelista, e não no ajuste. Portanto, seu código pode ficar assim:

Adjustable sb = messageScrollList.getVerticalScrollBar()
boolean onBottom = sb.getValue() == sb.getMaximum();
//
// add your message to the JList.
//
if(onBottom)  sb.setValue(sb.getMaximum());

Caso contrário, você precisaria saber se o ajuste foi causado por uma alteração do modelo, ou pelo mouse e, olhando através dos documentos da API, não tenho certeza se há uma maneira de fazer isso facilmente. Embora você possa ver se o AdjustmentEvent.getAdjustmentType() Retorna valores diferentes nesses casos, se isso for verdade, você poderá ter uma instrução IF na sua classe interna anônima.

Outra coisa que você poderia tentar seria ter uma variável booleana em algum lugar que seja definido quando você adicionar algo à lista. Então, no seu manipulador, você verifica se a variável está definida. Nesse caso, você faz o ajuste (e desperta a variável), caso contrário, ignora -o. Dessa forma, haverá apenas uma rolagem por item sendo adicionada à lista.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top