[英]Java ScrollPane interactive scrolling
我正在構建一個聊天應用程序,在其中將聊天添加到附加到JScrollPane
的JPanel
中。 可以在我的JPanel
中添加和刪除聊天,並且我希望我的JScrollPane
執行 3 個功能
如果垂直scrollBar
不可見(即由於屏幕上的聊天很少而無需滾動)並且當新的聊天進入面板導致scrollBar
條第一次可見時, scrollBar
條必須滾動到它的最大值,以便使新添加的聊天可見
如果用戶已盡可能物理地滾動到scrollPane
的最大值/最底部,並且當新聊天進入面板時導致scrollBar
的最大值上升到 go 則執行與操作 1 相同的操作
如果用戶向上滾動聊天以查看以前的消息(即到某個隨機點,該點小於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);
}
}
相關文章
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.