I am building an chat app where I add chats to an JPanel
attached to a JScrollPane
. Chats can be added and removed from my JPanel
and as that happens I want my JScrollPane
to perform 3 functions
If the vertical
scrollBar
is not visible (i.e no need for scrolling due to very little chats on screen) and when an new chat enters the panel causing thescrollBar
to become visible for the first time then thescrollBar
must scroll to it's maximum value so as to make the newly added chat visibleIf the user has scrolled to the maximum value/very bottom of the
scrollPane
as physically possible and when an new chat enters the panel causing thescrollBar
's maximum value to go up then perform the same as Action 1If the user has scrolled up the chat to see previous messages (i.e to some random point which is LESS than the MAXIMUM value of the
scrollBar
) and then some new chat appears then a scroll button must appear in the chat and if the user clicks on it thescrollBar
scrolls to the NEW MAXIMUM value so as to make the newly added chats visible
Basically my algorithm is as follows
//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
}
This algorithm unfortunatly dosen't work and the scrollButton always ends up visible regardless. Here Is the full code:
Chat Display class for displaying chats
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 set as content pane
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));
}
}
Main 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);
}
}