Scrolling a scrollbar to the bottom when its at the bottom - java

I am trying to make a chatbox application, im trying to code the side bar so that it will stay at the bottom but can also scroll up to view history. Is there any way i can do this?
pane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
}
});

, im trying to code the side bar so that it will stay at the bottom but can also scroll up to view history
Check out the Smart Scrolling. When the scrollbar is at the bottom it will stay there as next text is added. If you scroll somewhere else, it will stay there (even when new text is added) until you move the scrollbar back to the bottom.

Related

Text area can't scroll properly with caret

I use a JTextArea for the chat of my simple chat program, and I added a caret so it will autoscroll when text is appended to it. This spawned an issue of the user not being able to scroll when the chat is being used a lot.
I've tried looking through options for the caret, and I looked into the scroll pane options, but there's nothing on not scrolling down when the user is scrolling.
I intend to be able to allow the user to scroll but not immediately get scrolled down because someone sent a message. What would be ideal is it it worked like Discord, where it only scrolls down when the user scrolls all the way down or something like that.
What would be ideal is it it worked like Discord, where it only scrolls down when the user scrolls all the way down or something like that.
Check out Smart Scrolling. It adds an AdjustmentListener to the scroll bar to control scrolling:
When the scroll bar is at the bottom it will continue to automatically scroll.
When it is not at the bottom it won't scroll. The user would need to scroll to the bottom to reactivate automatic scrolling.
My Recommendation is similar to Camickr's. Add a changelistener to the scrollbar and enable/disable caret movement based on whether or not the user is scrolled to the bottom. If the scrollbar is at the maximum, enable caret movement. If it is not, then keep it disabled.
YourJScrollPane.getVerticalScrollBar().getModel().addChangeListener()
{
//Override stateChanged(ChangeEvent e) With Caret Movement Switch
}
Detect and compare current scrollbar position by calling the extent, value, and maximum extent from the Model (Which is a BoundedRangeModel).
https://docs.oracle.com/javase/7/docs/api/javax/swing/BoundedRangeModel.html
/*Where to find the needed scrollbar position values*/
YourJScrollPane.getVerticalScrollBar().getModel().getExtent()
YourJScrollPane.getVerticalScrollBar().getModel().getValue()
YourJScrollPane.getVerticalScrollBar().getModel().getMaximum() //Bottom Position
/*Pseudocode*/
if (Value + Extent == Maximum)
{
/*Enable Caret Movement - User is at bottom of page*/
}
else
{
/*Disable Caret Movement - User is not at bottom of page*/
}
Comment Below with any improvements or recommendations.

Can you make the background of a JScrollBar transparent?

I have a series of column labels that scrolls independently from the data that is displayed in a matrix below. I can make the whole scrollbar transparent except on hover. The labels are right up against the data, which I like, however, upon hover, unless I shift the vertical scroll (which I'd rather not do), the scrollbar obscures the beginning of all the labels.
I would like to set the background of the scrollbar as transparent so that only the "grabber" (or whatever it's called) is the only thing that is drawn. (It will obscure the beginning of the labels it is over, but would be a lot less so.)
Is there any way to do that? Here is what I tried:
Color bg = new Color(255,255,255,0);
colLabelScroll.setBackground(bg);
This does not seem to make the background of the scrollbar transparent.
What I'm shooting for is like how the iPhone's scrollbar grabber hovers over info in some apps. Is that even possible with JScrollBars?
Transparent JScrollBar can do it, but consider this: if column labels are related to the data and you can scroll them independently, beginner users may not understand what is going on and associate column labels with whatever is visually aligned beneath it. Either you will need some sort of visual indicator that makes it clear that the labels are disconnected from the data, or you should change the way labels are scrolled that never leaves them statically in 1 place.
Here's how I ended up making the relationship between the labels and the data clearer:
Instead of allowing the user to independently and intentionally scroll the labels, I decided to control the label scroll position via mouse hover. This eliminates the need for the obtrusive scrollbar.
I created a scroll-bar-like indicator that shows the portion of the data the labels represent.
I highlighted the currently hovered label that corresponds to the data below it, i.e. the only label that is ever correctly aligned with the data is the one that is under (or directly above) the cursor.
When the mouse is not hovered over (or dragging from) the column labels, do not display any labels. This helps prevent invalid label/data associations by the user.
A few nuanced notes: Implementing your own scrollbar-like indicator is somewhat involved, especially if your labels are painted and then rotated, because the paint position of 0 is at the bottom of the pane, yet the vertical scroll position of the pane is at the top. You will have to track the vertical scroll position to be able to recover it again when the cursor returns since you are blanking the labels on mouse out.
When developing a plugin for IntelliJ, I accomplished it with:
scrollPane.getVerticalScrollBar().setUI(ButtonlessScrollBarUI.createTransparent());
It takes advantage of the the:
ButtonlessScrollBarUI.createTransparent()
method, which is an IntelliJ specific method. However, if you can find a ScrollBarUI which has a transparent background, you can use the same trick.
Since I got a bit lost myself at first after reading #hepcat72's answer I'm posting a little explanation about the BasicScrollBarUI class:
JScrollBar scrollbar = scrollPaneConversation.getVerticalScrollBar();
scrollbar.setUI(new BasicScrollBarUI(){
// This function returns a JButton to be used as the increase button
// You could create your own customized button or return an empty(invisible) button
#Override
protected JButton createIncreaseButton(int orientation){
}
// Same as above for decrease button
#Override
protected JButton createDecreaseButton(int orientation){
}
// This function paints the "track" a.k.a the background of the scrollbar
// If you want no background just return from this function without doing anything
// If you want a custom background you can paint the 'Graphics g' object as you like
#Override
protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds)
{
}
// This function paints the "thumb" a.k.a the thingy that you drag up and down
// You can override this function to paint it as you like
#Override
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds)
{
}
});
Refer to the Transparent JScrollBar link posted by #hepcat72 for hints about what to do exactly in these functions.

Set the vertical scroll to current position after revalidate

I know that this question might have been asked before, but I just can't get by head around this, and hopefully we could produce a complete answer to a somewhat tricky interface.
The GUI could be described as follows:
Application extends JFrame. Application adds a JPanel mPanel. mPanel adds a JScrollPane ml containing a MoviePanel extending JPanel.
The JScrollPane ml has vertical scrolling. My goal is that once the content of MoviePanel changes, and a run a revalidate() on it, the scroll pane should not, as it currently does, scroll to the bottom. Rather I'd like it to scroll to what ever position it had before the change to MoviePanel. Giving the feel that it never scrolled at all.
I have tried to manually set the scroll position after I run the revalidate() method:
removeAll(); // Removes all components from the JPanel MoviePanel
add(mList()); // Adds a bunch of content (other JPanels) to MoviePanel
revalidate();
ml.getVerticalScrollBar().setValue(0); // Scroll to top (don't work) - and I'd like this value to be the position of the scroll before these lines started to run
but it seems it really doesn't do anything.
I would be so grateful if someone might help me with this!
Add the scrolling code to a SwingUtilities.invokeLater:
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
ml.getVerticalScrollBar().setValue(0);
}
});

Is there a better way to lock the main scroll bar without hiding it in GWT?

I set my body element to
body {
overflow-y: scroll;
}
This creates a scroll bar on my body element. When I create a scrollbar and scroll to the bottom the main area of my page is also scrolled.
I found some posts on this topic: Prevent scrolling of parent element? prevent Scroll "bubbling" from element to window but these are not applicable for GWT.
I tried the following:
#UiHandler("panel")
void onPanelMouseOver(MouseOverEvent event) {
Window.enableScrolling(false);
}
#UiHandler("panel")
void onPanelMouseOut(MouseOutEvent event) {
Window.enableScrolling(true);
}
This is a bad solution because the main scroll bar disappear and the page is moving from left to right and back. I want to lock the scroll bar not hide it. Hiding will move the screen.
Is there a better way to lock the main scroll bar in GWT?
For this purpose only gwt introduced concept of layout panels. Use RootLayout Panel and other layout panels. Then your applications won't have body scrolls if you maintain the hierarchy. Layout panels also resizes child widgets on browser resize. So you will get an added advantage
EDIT
If you want a fixed header and scroll on the rest of the part, use RootLayoutPanel and add DockLayoutPanel to it. Set your header panel to dockPanel North side and add scroll panel to the center of the dockPanel
FlowPanel headerPanel = new FlowPanel();
headerPanel.setWidth("100%");
ScrollPanel bodyPanel = new ScrollPanel();
DockLayoutPanel myApp = new DockLayoutPanel(Unit.PX);
myApp.addNorth(headerPanel, 100);
myApp.add(bodyPanel);
RootLayoutPanel.get().add();
To hide and lock the scrollbar of the body
body {
overflow:hidden;
}

JScrollbar scroll per 50 px

I'm working on a program that includes a scrollbar.
In the program I got a scrollable field of 500px and I want the scrollbar to scroll per 50px.
So I get 10 pages.
I dont want to be able to show 50% of a page I only want to be able to show 1 page at a time.
So how do I change the scroll dimensions?
Or is there a better way to accomplish this?
Greets,
And thanks in advance
Bram
You can make the scrollable field implement the Scrollable interface, which declares two methods the scroll field will use to decide how far it scrolls, getScrollableUnitIncrement (scroll-wheel, clicking the scroll arrow) and getScrollableBlockIncrement (clicking the scrollbar's track).
If you're really only ever going to want it to be 50, you can use
jScrollPane.getVerticalScrollBar().setUnitIncrement(50);
jScrollPane.getVerticalScrollBar().setBlockIncrement(50);
However, if the user then drags the scrollbar until half a page is shown (I don't think this behavior can be easily changed), scrolling will still jump 50 pixels and show half of the next page... If you implement Scrollable, you can base the amount scrolled on what is currently visible.
Try this with you JScrollPane
scrollPane.getVerticalScrollBar().setUnitIncrement(50);
This helps when you scroll with JScrollPane buttons up/down but you be able show a half of page by moving knob with mouse.
As alternative I can propose to watch knob position with AdjustmentListener and shift scrollPane value manually.
scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener()
{
public void adjustmentValueChanged(AdjustmentEvent e)
{
scrollPane.getVerticalScrollBar().setValue(e.getValue() / 50 * 50);
}
});
But I think it isn't good idea. May be somebody will propose better way.

Categories

Resources