Java滚动窗格交互式滚动

Java滚动窗格交互式滚动,java,swing,jscrollpane,Java,Swing,Jscrollpane,我正在构建一个聊天应用程序,在该应用程序中,我将聊天添加到连接到JScrollPane的JPanel。聊天可以从我的JPanel中添加和删除,因此我希望我的JScrollPane执行3个功能 如果垂直滚动条不可见(即,由于屏幕上聊天很少,因此无需滚动),并且当新聊天进入面板时,导致滚动条第一次可见,则滚动条必须滚动到其最大值,以使新添加的聊天可见 如果用户已在物理上尽可能滚动到滚动窗格的最大值/最底部,并且当新聊天进入该面板时,导致滚动条的最大值上升,则执行与操作1相同的操作 如果用户已向上

我正在构建一个聊天应用程序,在该应用程序中,我将聊天添加到连接到
JScrollPane
JPanel
。聊天可以从我的
JPanel
中添加和删除,因此我希望我的
JScrollPane
执行3个功能

  • 如果垂直
    滚动条
    不可见(即,由于屏幕上聊天很少,因此无需滚动),并且当新聊天进入面板时,导致
    滚动条
    第一次可见,则
    滚动条
    必须滚动到其最大值,以使新添加的聊天可见

  • 如果用户已在物理上尽可能滚动到
    滚动窗格的最大值/最底部,并且当新聊天进入该面板时,导致
    滚动条的最大值上升,则执行与操作1相同的操作

  • 如果用户已向上滚动聊天以查看以前的消息(即到某个随机点,该点小于
    滚动条的最大值
    )然后出现一些新聊天,然后聊天中必须出现一个滚动按钮,如果用户单击它,
    滚动条
    滚动到新的最大值,以使新添加的聊天可见

  • 基本上我的算法如下

    //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
    }
    
    不幸的是,这种算法不起作用,滚动按钮始终可见。以下是完整的代码:

    用于显示聊天的聊天显示类

    
    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
            }
        }
    }
    
    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);
        }
    }
    
    current=scrollBar.getValue() 
    
    聊天面板设置为内容窗格

    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));
        }
    }
    
     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);
      }
     }
    
    主类

    
    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
            }
        }
    }
    
    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);
        }
    }
    
    current=scrollBar.getValue() 
    

    我找到了答案

    解决方案

    关键在于,每当对滚动条进行任何“调整”[add/remove an chat]时,滚动条始终滚动到底部,并且只有在用户之前滚动到最大值时,滚动条才必须执行此行为

     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
       }
     });
    
    修复

    
    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
            }
        }
    }
    
    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);
        }
    }
    
    current=scrollBar.getValue() 
    
    将永远不会等于最大值,除非将其添加到屏幕上显示的可见量中,即

    currentValue=scrollBar.getValue()+scrollBar.getVisibleAmount()
    
    解决方案和修复程序是在
    guiUpdate()
    方法中实现的

    FullCode

    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));
        }
    }
    
     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);
      }
     }
    
    相关职位


  • 我找到了答案

    解决方案

    关键在于,每当对滚动条进行任何“调整”[add/remove an chat]时,滚动条始终滚动到底部,并且只有在用户之前滚动到最大值时,滚动条才必须执行此行为

     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
       }
     });
    
    修复

    
    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
            }
        }
    }
    
    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);
        }
    }
    
    current=scrollBar.getValue() 
    
    将永远不会等于最大值,除非将其添加到屏幕上显示的可见量中,即

    currentValue=scrollBar.getValue()+scrollBar.getVisibleAmount()
    
    解决方案和修复程序是在
    guiUpdate()
    方法中实现的

    FullCode

    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));
        }
    }
    
     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);
      }
     }
    
    相关职位


  • 为了获得更好的帮助,请尽快发布一个适当的、与缩进一致的文件,对于Java来说,有4个空格,一个空格几乎不可能遵循程序的流程(并且程序的每一行之间不需要有一个空行,这会使程序比应该的要长,并且更难阅读)
    .setLayout(null)
    有些东西告诉我那里出了问题,特别是
    JScrollPane
    s。我在这里发布了全部代码&我使用null布局管理器只是为了演示。布局管理器也存在同样的问题,我不能在JLayeredPane中使用布局管理器,否则滚动按钮不会出现在聊天的顶部(更高的深度)。主要逻辑在guiUpdate()方法中,与布局无关,以便更好地帮助您更快发布正确的、与缩进一致的内容,对于有4个空格的Java来说,一个空格几乎不可能跟随程序的流程(并且程序的每一行之间不需要有一个空行,这使得程序比应该的要长,并且更难阅读)
    .setLayout(null)
    有些东西告诉我那里出了问题,特别是
    JScrollPane
    s。我在这里发布了全部代码&我使用null布局管理器只是为了演示。布局管理器也存在同样的问题,我不能在JLayeredPane中使用布局管理器,否则滚动按钮不会出现在聊天的顶部(更高的深度)。主要逻辑位于guiUpdate()方法中,与布局无关