簡體   English   中英

Java ScrollPane 交互式滾動

[英]Java ScrollPane interactive scrolling

我正在構建一個聊天應用程序,在其中將聊天添加到附加到JScrollPaneJPanel中。 可以在我的JPanel中添加和刪除聊天,並且我希望我的JScrollPane執行 3 個功能

  1. 如果垂直scrollBar不可見(即由於屏幕上的聊天很少而無需滾動)並且當新的聊天進入面板導致scrollBar條第一次可見時, scrollBar條必須滾動到它的最大值,以便使新添加的聊天可見

  2. 如果用戶已盡可能物理地滾動到scrollPane的最大值/最底部,並且當新聊天進入面板時導致scrollBar的最大值上升到 go 則執行與操作 1 相同的操作

  3. 如果用戶向上滾動聊天以查看以前的消息(即到某個隨機點,該點小於scrollBar的 MAXIMUM 值),然后出現一些新的聊天,那么聊天中必須出現一個滾動按鈕,如果用戶點擊scrollBar滾動到新的最大值以使新添加的聊天可見

基本上我的算法如下

//The user is currently at the bottom of the chat or scrollBar is not visible therefore making current & maximum value = 0
if (scrollBar.currentValue() == scrollBar.maxValue()) {
    scrollButton.setVisible(false);
    guiUpdate();  //Then Add,Remove The Chat
    scrollToVeryButton();
}
else {
    //The user is somewhere top of the chat looking at previous messages
    guiUpdate();   //Then Add,Remove The Chat
    scrollButton.setVisible(true); //Upon clicking scrollToVeryButton(); Is Called
}

不幸的是,該算法不起作用,並且無論如何滾動按鈕始終可見。 這是完整的代碼:

聊天顯示 class 用於顯示聊天


import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;

class ChatDisplay extends JLayeredPane {

    private JScrollPane scrollPane;
    private JPanel chatDisplay;
    private Scroll notify;

    ChatDisplay() {
        setLayout(null);
        addChatDisplay();
        addNotifyButton();
    }

    private void addChatDisplay() {
        chatDisplay = new JPanel();
        chatDisplay.setLayout(new BoxLayout(chatDisplay, BoxLayout.Y_AXIS));
        scrollPane = new JScrollPane(chatDisplay);
        scrollPane.setBounds(0, 0, 300, 300);
        add(scrollPane, new Integer(0));
    }

    private void addNotifyButton() {
        notify = new Scroll();
        notify.setBounds(150, 150, 80, 50);
        add(notify, new Integer(1));
        notify.setVisible(false);
    }

    //Called To Add An New Chat
    void addButton(String text) {
        guiUpdate(() -> {
            chatDisplay.add(new Chat(text));
            chatDisplay.revalidate();
            chatDisplay.repaint();
        });
    }

    //The general update when gui is changed in anyway
    private void guiUpdate(Runnable update) {
        JScrollBar scrollBar = scrollPane.getVerticalScrollBar();
        if (scrollBar.getValue() == scrollBar.getMaximum()) {
            notify.setVisible(false);
            update.run();
            scrollBar.setValue(scrollBar.getMaximum());
        } else {
            update.run();
            notify.setVisible(true);
        }
    }

    //Called To Remove An Chat
    private void removeButton(JButton button) {
        guiUpdate(() -> {
            chatDisplay.remove(button);
            chatDisplay.revalidate();
            chatDisplay.repaint();
        });
    }

    //The Chat Button
    private final class Chat extends JButton implements ActionListener {

        private Chat(String text) {
            setText(text);
            Dimension dim = new Dimension(300, 100);
            setPreferredSize(dim);
            setMinimumSize(dim);
            setMaximumSize(dim);
            addActionListener(Chat.this);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            removeButton(Chat.this); //Upon Clicking Remove Itself From Chat
        }
    }

    // The ScrollBar
    private final class Scroll extends JButton implements ActionListener {

        private Scroll() {
            setText("Scroll");
            setBackground(Color.green);
            addActionListener(Scroll.this);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            JScrollBar scrollBar = scrollPane.getVerticalScrollBar();
            scrollBar.setValue(scrollBar.getMaximum());  //Scroll To The Bottom Upon Clicking
            setVisible(false);  //Its Job Is Done Wait For Next Event
        }
    }
}

ChatPanel 設置為內容窗格

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

class ChatPanel extends JPanel implements ActionListener {
    private ChatDisplay display;
    private int chat;

    ChatPanel() {
        super(null);
        addDisplay();
        addButton();
    }

    private void addDisplay() {
        display = new ChatDisplay();
        display.setBounds(0, 0, 300, 300);
        add(display);
    }

    private void addButton() {
        JButton add = new JButton("ADD CHAT");
        add.addActionListener(this);
        add.setBounds(0, 310, 300, 30);
        add(add);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        display.addButton("Chat " + (++chat));
    }
}

主Class

import javax.swing.JFrame;

public class Main {
    public static void main(String args[]) throws Exception {
        JFrame frame = new JFrame("Design Frame");
        frame.setContentPane(new ChatPanel());
        frame.setSize(320, 380);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setVisible(true);
    }
}

我找到了答案

解決方案

關鍵是讓滾動條在有任何“ADJUSTMENTS”[添加/刪除聊天]時總是滾動到底部,並且只有在用戶之前滾動到最大值時它才必須執行此行為

 scrollBar.addAdjustmentListener((event)->
 {
   if(autoScroll)//an boolean flag which is set to true whenever an chat is added/removed 
   {
    scrollBar.setValue(scrollBar.getMaximum());
    
    autoScroll=false; //set to false so the user can scroll freely upwards otherwise it will always reset it to the amaximum value
   }
 });

修復

current=scrollBar.getValue() 

永遠不會等於最大值,除非它被添加到它在屏幕上顯示的可見量,即

currentValue=scrollBar.getValue()+scrollBar.getVisibleAmount()

解決方案和修復在guiUpdate()方法中實現

全碼

 private boolean autoScroll;
 private void guiUpdate(Runnable update)
 {
  JScrollBar scrollBar=scrollPane.getVerticalScrollBar();
  
  scrollBar.addAdjustmentListener((event)->
  {
   if(autoScroll)
   {
    scrollBar.setValue(scrollBar.getMaximum());
    
    autoScroll=false;
   }
  });
  
 
  if(scrollBar.getValue()+scrollBar.getVisibleAmount()==scrollBar.getMaximum())
  {
   notify.setVisible(false);
     
   autoScroll=true;  //The user is at the bottom of the screen hence autoScroll to the new maximum
   
   update.run();
  }
  else
  {
   autoScroll=false;  //the user is looking at previous chat messages hence don't scroll to the bottom
   
   update.run();
   
   notify.setVisible(true);
  }
 }

相關文章

  1. JScrollPane 滾動到底部

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM