Java ScrollPane 交互式滚动
Java ScrollPane interactive scrolling
我正在构建一个聊天应用程序,我将聊天添加到附加到 JScrollPane
的 JPanel
。可以在我的 JPanel
中添加和删除聊天,碰巧我希望我的 JScrollPane
执行 3 个功能
如果垂直 scrollBar
不可见(即由于屏幕上的聊天很少而无需滚动)并且当新聊天进入面板时导致 scrollBar
第一次可见然后 scrollBar
必须滚动到它的最大值以使新添加的聊天可见
如果用户已尽可能滚动到 scrollPane
的最大 value/very 底部,并且当新聊天进入面板时导致 scrollBar
' s 最大值上升然后执行与操作 1 相同的操作
如果用户向上滚动聊天以查看以前的消息(即滚动到某个随机点,该点小于 scrollBar
的最大值)然后出现一些新聊天滚动按钮必须出现在聊天中,如果用户单击它,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
}
不幸的是,该算法不起作用,无论如何,scrollButton 总是最终可见。这是完整的代码:
聊天显示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);
}
}
我找到了答案
解决方案
关键是只要有任何“调整”[add/remove 聊天] 滚动条总是滚动到底部,并且只有当用户之前滚动到它时它才必须执行此行为最大值
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);
}
}
相关帖子
- JScrollPane scrollToBottom
我正在构建一个聊天应用程序,我将聊天添加到附加到 JScrollPane
的 JPanel
。可以在我的 JPanel
中添加和删除聊天,碰巧我希望我的 JScrollPane
执行 3 个功能
如果垂直
scrollBar
不可见(即由于屏幕上的聊天很少而无需滚动)并且当新聊天进入面板时导致scrollBar
第一次可见然后scrollBar
必须滚动到它的最大值以使新添加的聊天可见如果用户已尽可能滚动到
scrollPane
的最大 value/very 底部,并且当新聊天进入面板时导致scrollBar
' s 最大值上升然后执行与操作 1 相同的操作如果用户向上滚动聊天以查看以前的消息(即滚动到某个随机点,该点小于
scrollBar
的最大值)然后出现一些新聊天滚动按钮必须出现在聊天中,如果用户单击它,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
}
不幸的是,该算法不起作用,无论如何,scrollButton 总是最终可见。这是完整的代码:
聊天显示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);
}
}
我找到了答案
解决方案
关键是只要有任何“调整”[add/remove 聊天] 滚动条总是滚动到底部,并且只有当用户之前滚动到它时它才必须执行此行为最大值
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);
}
}
相关帖子
- JScrollPane scrollToBottom