【问题标题】:JScrollPane and JList auto scrollJScrollPane 和 JList 自动滚动
【发布时间】:2011-01-09 02:24:32
【问题描述】:

我得到了下一个代码:

    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());  
        }
    }); 

它会自动向下滚动。但是,如果我尝试向上滚动以重新阅读一条消息,它会强制向下滚动。 我该如何解决这个问题?

【问题讨论】:

    标签: java swing jscrollpane jlist autoscroll


    【解决方案1】:

    添加新消息时,在JList 上调用scrollRectToVisible(),并使用与消息窗格首选大小相同的Rectangle。给定垂直方向,将JScrollPaneJViewport 的首选大小设置为消息窗格高度的整数倍可能会很方便。另见:How to Use Scroll Panes

    附录:关于Text Area Scrolling 的引人注目的讨论也可能会有所帮助。

    【讨论】:

      【解决方案2】:
      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());
      

      【讨论】:

        【解决方案3】:

        我发现这非常有用: http://forums.sun.com/thread.jspa?threadID=623669('inopia' 发布)
        效果很好

        正如他所说: “这里的问题是,在 ListModel、JList 和 JScrollPane 都更新后找到触发的事件可能会变得有点困难。”

        【讨论】:

        • 链接已失效。可以刷新一下吗?
        【解决方案4】:

        @question 询问者。请从

        更改您的代码
        messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
            public void adjustmentValueChanged(AdjustmentEvent e) {  
                e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
            }
        });
        

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

        也就是将getMaximum() 更改为getValue() 然后它按要求工作。 getMaximum() 将滚动条调到最大;而getValue() 将它带到任何事件发生的地方。

        如果你放一行,你可以完全避免使用这段代码

        messageScrollList.setViewportView(messageList);
        

        这就像 add(component) 用于 jList 并获得其固有的行为。

        【讨论】:

          【解决方案5】:

          我将JScrollPaneJTextArea 一起使用。我只在JScrollBar max 值更改时才通过滚动来避免强制向下滚动:

          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();
              }
          );
          

          我想,有更好的解决方案来过滤没有额外变量的事件,如果有人发布它会很感激。

          【讨论】:

            【解决方案6】:

            我认为您想要做的是在向 messageList 添加内容时让它向下滚动,而不是在调整时向下滚动。所以你的代码可能看起来像这样:

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

            否则,您需要判断调整是由模型更改还是由鼠标引起的,并且查看 API 文档我不确定是否有办法轻松做到这一点。虽然您可以看到 AdjustmentEvent.getAdjustmentType() 在这些情况下是否返回不同的值,但如果这是真的,那么您可以在匿名内部类中使用 if 语句。

            您可以尝试的另一件事是在某处设置一个布尔变量,当您将某些内容添加到列表中时该变量会被设置。然后,在您的处理程序中检查变量是否已设置。如果是这样,您进行调整(并取消设置变量),否则,您将忽略它。这样,每个添加到列表中的项目将只有一个向下滚动。

            【讨论】:

            • 两种情况下的调整类型相同。如果添加了消息,我已经尝试向下滚动。但如果我这样做,最后添加的消息将不可见。它向下滚动不够。我该如何解决?
            • 嗯...好吧,您可以做的一件事是在某处设置一个布尔变量,当您将某些内容添加到列表中时该变量会被设置。然后,在您的处理程序中检查变量是否已设置。如果是这样,您进行调整(并取消设置变量),否则,您将忽略它。这样,每个被添加到列表中的项目只会有一个向下滚动。
            【解决方案7】:

            为了自动滚动,我使用了一个非常简单的静态变量概念和 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++);
                 /*
                 *
                 */
            
            
                }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-01-29
              • 2012-01-18
              • 1970-01-01
              相关资源
              最近更新 更多