Java Forum / General / May 2008
Custom JScrollPane - Double JScrollBars
pek - 23 Apr 2008 05:15 GMT Is there any way I can customize a JScrollPane and instead of one horizontal JScrollPane it would show two? Can you point me somewhere?
Thank you.
pek - 24 Apr 2008 02:19 GMT > Is there any way I can customize a JScrollPane and instead of one > horizontal JScrollPane it would show two? Can you point me somewhere? > > Thank you. Sorry, I meant displaying two horizontal ScrollBars.
RedGrittyBrick - 24 Apr 2008 12:23 GMT >> Is there any way I can customize a JScrollPane and instead of one >> horizontal JScrollPane it would show two? Can you point me somewhere? >> >> Thank you. > > Sorry, I meant displaying two horizontal ScrollBars. Maybe you want a JSplitPane.
If not, try describing what you want to achieve more clearly.
 Signature RGB
David A. Redick - 24 Apr 2008 14:30 GMT You'll have to override the layout manager.
In the example below, I made the scroll pane display 2 vertical bars. All I did was resize/reposition the viewport, the vertical and the horizontal bar.
The outer most vertical bar will still act like that standard horiz bar. The inner vertical bar will be the same normal vertical bar.
PS. Are you sure you really need to do this? I agree with RGB that you sure have a look at the other default panes just make sure. =/
---------------------------------------------------------
import java.awt.*; import java.awt.event.*; import javax.swing.*;
class MySPLayout extends ScrollPaneLayout { public void layoutContainer(Container parent) { hsb.setOrientation(JScrollBar.HORIZONTAL); super.layoutContainer(parent);
Rectangle hRec = hsb.getBounds(); Rectangle vRec = vsb.getBounds(); Dimension size = viewport.getExtentSize();
// adjust viewport size, add to the bottom, sub from right side size.width -= vRec.width; size.height += hRec.height; viewport.setExtentSize(size);
// get rid of the corner vRec.height += hRec.height;
// scoot over to make room vsb.setLocation(vRec.x - vRec.width, vRec.y); vsb.setSize(vRec.width, vRec.height);
hsb.setOrientation(JScrollBar.VERTICAL); hsb.setLocation(vRec.x, vRec.y); hsb.setSize(vRec.width, vRec.height); } }
public class GUI extends JFrame /* implements ActionListener */ {
// GUI objects JTextArea m_pText; JScrollPane m_pScrollPane;
GUI() { super("Test GUI");
m_pText = new JTextArea("This is a test."); m_pText.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
m_pScrollPane = new JScrollPane(m_pText);
m_pScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); m_pScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
m_pScrollPane.setLayout(new MySPLayout());
add(m_pScrollPane);
pack(); }
public void dispose() { super.dispose(); } }
pek - 26 Apr 2008 06:51 GMT On Apr 24, 4:30 pm, "David A. Redick" <tinyweldingto...@gmail.com> wrote:
> You'll have to override the layout manager. > [quoted text clipped - 80 lines] > > } First of all thank you for your replies. To be fair, I'll explain a little more. I want to create a panel that, when needed, will display vertical and horizontal bars. When either a horizontal or a vertical scroll bar appears, I want them to be double (2 horizontal scroll bars or 2 vertical scroll bars). Both will point at the same view, but each will behave different (probably one of them will scroll faster or scroll the other way or anything). I want to explicitly define how each will behave.
I'll try your code and report back. Thank you once again.
pek - 26 Apr 2008 08:59 GMT > On Apr 24, 4:30 pm, "David A. Redick" <tinyweldingto...@gmail.com> > wrote: [quoted text clipped - 94 lines] > > I'll try your code and report back. Thank you once again. OK.. I must admit, the code was awesome! I didn't imagine what it would do! Thank you very much.
So, since I don't know how (or even why) this code works, I'll just post what exactly I want to do and hope that you'll also help me on this.
I came across Picassa this other day. I'm not actually sure if it was Picassa, but anyway. I noticed that the vertical scroll bar isn't the conventional one. It works like this:
Let's say that the viewports' view is three screens high. The vertical bars' knob is at the middle. If you drag it either way (up or down) the view scrolls respectively. The cool the about it is that the further the knob is away from the starting middle point, the faster the view scrolls. When the knob isn't anymore dragged (you release the mouse) the knob returns to it's initial position (the middle).
What I'm trying to accomplish (with no luck what so ever) is have both scroll bars (conventional and picassa-like) in one pane using code like JDoubleScrollPane.setPicassaLikeVerticalScrollBarPolicy(...) (OK, it's rather huge, but I'll a better one). So, the developers and the end user would have the best of both worlds.
Now, I didn't know where to start. I actually thought I had to create a new component and implement its' own look and feel. Which goes to say what is the level of my knowledge in Swing.
So, what do you think? Can you help? Or at least give me some pointers and hints?
Thank you very much.
Panagiotis.
Jeff Higgins - 26 Apr 2008 12:58 GMT > Let's say that the viewports' view is three screens high. > The vertical bars' knob is at the middle. [quoted text clipped - 12 lines] > So, what do you think? Can you help? Or at least give me some pointers > and hints? Some applications use the mouse wheel for that behavior. Adobe Acrobat Reader comes to mind. When you press the mouse wheel the cursor is changed to indicate a multi- directional pan control that pans at a rate that increases with the distance the mouse moves away from the original drag point. It's not self-centering. The scrollbar knobs still indicate the position within the document.
David A. Redick - 28 Apr 2008 20:59 GMT > OK.. I must admit, the code was awesome! I didn't imagine what it > would do! Thank you very much. No prob.
> So, since I don't know how (or even why) this code works, I'll just > post what exactly I want to do and hope that you'll also help me on > this. The how and why are fairly easy once you start thinking in the Java way (or OO way). Think of JScrollPane as just a container for 2 scrollbars and a view. How does it know where to put things? Simple, the ScrollPaneLayout object tells it.
Every panel/pane type object uses a Layout object to place things. Some are easily hijacked (like JScrollPane) some are harder (JTable seems to be near impossible).
In the example I used earlier I just shuffled stuff around and resized them every time the JScrollPane wanted an update.
See http://en.wikipedia.org/wiki/Model-view-controller
The model can be thought of as the actual data interface (JTextArea). The view can be thought of as the thing that controls what you see (ScrollPaneLayout). The controller can be thought of as the thing that handles events (JScrollPane).
Of course the boundaries are rather fuzzy.
If you zoom in on the scroll bars then what does what is a bit different. Model: BoundedRangeModel (which is inside JScrollBar) View: JScrollBar (I'm guessing via BoxLayout. Docs don't say) Controller: JScrollBar
> [snip] > > Now, I didn't know where to start. I actually thought I had to create > a new component and implement its' own look and feel. Which goes to > say what is the level of my knowledge in Swing. You should be careful with your choice of words. People used look and "feel to mean" a wide variety of concepts. In the Java world look and feel just means graphical look (see PLAF).
I prefer to break the GUI into three parts. Look - the graphical side (does a button have the 3d look or flat? Is there a drop shadow? Does a button have rounded edges or hard corners. Is this a red or gray or blue button. Does it have hash marks?
Behavior (what non-programmers usually mean by feel) - How does scroll bar act? User interaction with widgets.
Layout - Where stuff is placed on the screen, the size of that stuff.
Naturally there is some overlap. And this is really just meant as an aside. A FYI, so to speak. Take with liberal amounts of salt.
To put this in the same context as my reply above...
Look is controlled by the UIManager object and ScrollBarUI, ScrollPaneUI, TextUI (all behind the scenes). Behavior is controlled by the JScrollPane, JScrollBars and whatever the JViewport is. Layout is controlled by ScrollPaneLayout.
> So, what do you think? Can you help? Or at least give me some pointers > and hints? Well below is a basic template for DoubleScollPane. The inner scrollbars are the standard ones. The outer ones will be the wacky Picassa ones. At the moment they just sit there and don't do a damn thing.
I'm still not 100% sure of how this Picassa scroll bars will behave so its difficult to say on how to implement them.
You'll probablity have to make a PicassaScrollBar object that extends ScrollBar.
Override several of the methods (maximum, minimum, BlockIncrement, UnitIncrement, value, IsAdjusting, VisibleAmount) and fittle with BoundedRangeModel.
Make DoubleScrollPane an AdjustmentListener for the two PicassaScrollBars. And adjust the view port in either the pane itself or the layout. To be honest, I'm not sure which is the more proper. I can see it for either one but I'm really not sure. I'd guess the pane.
Here's my guess of the Picassa model:
MIN*-----A------B------C-----*MAX
When the knob is at B it has a scroll speed of 0 When the knob is at A it has a scroll speed of -x When the knob is at C it has a scroll speed of x
So you'll have to figure out how to compute the speed based on the position (fittle with BoundedRangeModel)
Heres the DoubleScrollPane template (its much cleaner than my original example):
import java.awt.*; import java.awt.event.*; import javax.swing.*;
class DoubleScrollPaneLayout extends ScrollPaneLayout { protected JScrollBar m_pHSB2; protected JScrollBar m_pVSB2;
DoubleScrollPaneLayout(JScrollBar pHSB2, JScrollBar pVSB2) { super();
m_pHSB2 = pHSB2; m_pVSB2 = pVSB2; }
public void layoutContainer(Container parent) { super.layoutContainer(parent);
Rectangle hRec = hsb.getBounds(); Rectangle vRec = vsb.getBounds(); Dimension size = viewport.getExtentSize();
// make viewport size a bit smaller size.width -= vRec.width; size.height -= hRec.height; viewport.setExtentSize(size);
// scoot VSB1 over to the left vsb.setLocation(vRec.x - vRec.width, vRec.y);
// scoot HSB1 up hsb.setLocation(hRec.x, hRec.y - hRec.height);
// adjust size to make the corner hRec.width -= vRec.width; vRec.height -= hRec.height; hsb.setSize(hRec.width, hRec.height); vsb.setSize(vRec.width, vRec.height);
// set our second set of scroll bars to be // the same size as its partner m_pHSB2.setSize(hRec.width, hRec.height); m_pVSB2.setSize(vRec.width, vRec.height);
// set the location of our second set of scroll bars m_pHSB2.setLocation(hRec.x, hRec.y); m_pVSB2.setLocation(vRec.x, vRec.y); } }
// 2 horiz. bars and 2 vert. bars. class DoubleScrollPane extends JScrollPane { protected JScrollBar m_pHSB2; protected JScrollBar m_pVSB2;
DoubleScrollPane(Component pView) { super(pView);
setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
m_pHSB2 = new JScrollBar(JScrollBar.HORIZONTAL); m_pVSB2 = new JScrollBar(JScrollBar.VERTICAL);
m_pHSB2.setVisible(true); m_pVSB2.setVisible(true);
add(m_pHSB2); add(m_pVSB2);
setLayout(new DoubleScrollPaneLayout(m_pHSB2, m_pVSB2)); } }
public class GUI extends JFrame { // GUI objects JTextArea m_pText; DoubleScrollPane m_pScrollPane;
public GUI() { super("Test GUI");
m_pText = new JTextArea("This is a test."); m_pText.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
m_pScrollPane = new DoubleScrollPane(m_pText);
add(m_pScrollPane); pack(); }
public static void main(String[] args) { GUI pApp = new GUI();
try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); SwingUtilities.updateComponentTreeUI(pApp); } catch(Exception ex) { System.out.println("Java's PLAF is fubar"); }
pApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pApp.setVisible(true); } }
David A. Redick - 29 Apr 2008 15:07 GMT I played around some more this morning and I think I figured it out. Just add the SpringyScrollBar class and replace the DoubleScrollPane class. The rest is the same.
class SpringyScrollBar extends JScrollBar { public SpringyScrollBar(int iOrientation) { super(iOrientation);
setMaximum(99); setMinimum(0); moveToMid(); }
public int getMid() { int iMid = getMaximum() - getMinimum() + 1; iMid /= 2;
int iSize = getVisibleAmount()/2;
iMid -= iSize;
return iMid; }
public void moveToMid() { setValue(getMid()); }
public int getSpeed() { int i = getValue(); i -= getMid();
if(i < 0) i *= -1;
return i; }
public int getDir() { int i = getValue(); i -= getMid();
if(i < 0) return -1;
return 1; } }
// 2 horiz. bars and 2 vert. bars. class DoubleScrollPane extends JScrollPane implements AdjustmentListener { protected SpringyScrollBar m_pHSB2; protected SpringyScrollBar m_pVSB2;
DoubleScrollPane(Component pView) { super(pView);
setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
m_pHSB2 = new SpringyScrollBar(JScrollBar.HORIZONTAL); m_pVSB2 = new SpringyScrollBar(JScrollBar.VERTICAL);
m_pHSB2.addAdjustmentListener(this); m_pVSB2.addAdjustmentListener(this);
m_pHSB2.setVisible(true); m_pVSB2.setVisible(true);
add(m_pHSB2); add(m_pVSB2);
setLayout(new DoubleScrollPaneLayout(m_pHSB2, m_pVSB2)); }
public void adjustmentValueChanged(AdjustmentEvent e) { SpringyScrollBar p = (SpringyScrollBar) e.getAdjustable(); boolean bIsHoriz = p.equals(m_pHSB2); int iSpeed = p.getSpeed(); int iDir = p.getDir();
// Adjust position. JScrollBar pBar; if(bIsHoriz) pBar = horizontalScrollBar; else pBar = verticalScrollBar;
int iInc = pBar.getUnitIncrement(iDir); iInc *= iSpeed; int iValue = pBar.getValue(); iValue += iDir*iInc; pBar.setValue(iValue);
if(!e.getValueIsAdjusting()) { // move back to center p.moveToMid(); } } }
pek - 30 Apr 2008 20:18 GMT On Apr 29, 5:07 pm, "David A. Redick" <tinyweldingto...@gmail.com> wrote:
> I played around some more this morning and I think I figured it out. > Just add the SpringyScrollBar class and replace the DoubleScrollPane [quoted text clipped - 111 lines] > > } Amazing! ;) Exactly how I wanted it! I can't thank you enough. I'll tweak some things and report back. Oh. In case you have any website/ blog, I'd like to hear about it. I want to post the source code in my blog and have some kind of reference to you.. ;)
By the way, there is a little problem. I'm running Linux, and when the knob is being dragged, it moves the view perfectly. But if let's say, I drag the knob from the middle to 1/3 position and just hold the knob there, the view doesn't move. As long as the knob is being dragged it does. I hope you understand what I'm saying.
I tried adding MouseMotionListener and MouseListener but again, when the knob is still, no event is fired, no matter in which position it is.
Other than that, excellent! ;)
Larry A Barowski - 01 May 2008 16:08 GMT > On Apr 29, 5:07 pm, "David A. Redick" <tinyweldingto...@gmail.com> > By the way, there is a little problem. I'm running Linux, and when the > knob is being dragged, it moves the view perfectly. But if let's say, > I drag the knob from the middle to 1/3 position and just hold the knob > there, the view doesn't move. As long as the knob is being dragged it > does. I hope you understand what I'm saying. Something like this should work:
private Timer horizTimer = new Timer(250, new ActionListener() { public void actionPerformed(ActionEvent ev) { int iDir = m_pHSB2.getDir(); int iInc = horizontalScrollBar.getUnitIncrement(iDir); int iSpeed = m_pHSB2.getSpeed(); iInc *= iSpeed; int iValue = horizontalScrollBar.getValue(); iValue += iDir*iInc; horizontalScrollBar.setValue(iValue); } });
private Timer vertTimer = new Timer(250, new ActionListener() { public void actionPerformed(ActionEvent ev) { int iDir = m_pVSB2.getDir(); int iInc = verticalScrollBar.getUnitIncrement(iDir); int iSpeed = m_pVSB2.getSpeed(); iInc *= iSpeed; int iValue = verticalScrollBar.getValue(); iValue += iDir*iInc; verticalScrollBar.setValue(iValue); } });
public void adjustmentValueChanged(final AdjustmentEvent e) { SpringyScrollBar p = (SpringyScrollBar) e.getAdjustable(); boolean bIsHoriz = p.equals(m_pHSB2); Timer timer = bIsHoriz? horizTimer : vertTimer; if(!e.getValueIsAdjusting()) { // move back to center timer.stop(); p.moveToMid(); } else { if (p.getSpeed() != 0 && !timer.isRunning()) { timer.start(); } } }
pek - 08 May 2008 21:52 GMT On May 1, 6:08 pm, "Larry A Barowski" <ThisisLarrybarAtEngDotAuburnDotLearninginstitution> wrote:
> > On Apr 29, 5:07 pm, "David A. Redick" <tinyweldingto...@gmail.com> > > By the way, there is a little problem. I'm running Linux, and when the [quoted text clipped - 48 lines] > } > } Thanks to this code and the one provided by the others, I finally created exactly what I wanted. I did some changes (such as setting speed, enable/disable springyscrollbar etc.) and I'm ready to post it but there is one small problem. I'm trying to follow as much "principles" as the JScrollPane has, so, I didn't forced verticalScrollBarPolicy to ALWAYS but left it for the user to decide. Well, the default vertical and horizontal scrollbars have each a policy of their own. What about the springyscrollbars? How do I implement a policy? The source code of JScrollPane doesn't indicate anywhere where the policies are used, or more likely, *I* didn't find any such indication. Any suggestions on how to implement policies for the springyscrollbars?
Thank you again.
Jeff Higgins - 08 May 2008 23:32 GMT > Well, the default vertical and horizontal scrollbars have each a > policy of their own. What about the springyscrollbars? How do I > implement a policy? The source code of JScrollPane doesn't indicate > anywhere where the policies are used, or more likely, *I* didn't find > any such indication. Any suggestions on how to implement policies for > the springyscrollbars? int HSSBPolicy int VSSBPolicy
get/set SSBPolicies
DoubleScrollPaneLayout
pek - 15 May 2008 16:19 GMT > > Well, the default vertical and horizontal scrollbars have each a > > policy of their own. What about the springyscrollbars? How do I [quoted text clipped - 9 lines] > > DoubleScrollPaneLayout Nope, nothing worked. I used the same JScrollPaneConstants for the policy in the DoubleScrollPane, but nothing changed. I copied the code that JScrollPane uses from the source code. It is almost the same thing, but nothing happens. But when I set the horizontalScrollBarPolicy (not the springy one) it works for both! Probably because I use the same JScrollPaneConstants, but then again, how else can I implement this?
Roedy Green - 01 May 2008 07:39 GMT >Is there any way I can customize a JScrollPane and instead of one >horizontal JScrollPane it would show two? Can you point me somewhere? It strikes me as an odd thing to do given how precious screen real estate is.
I would study the code for JScrollPane and related classes in src.zip. You could then base your class overriding just what you need, or building one from scratch without any special features.
 Signature
Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Lord Zoltar - 15 May 2008 16:57 GMT On May 1, 2:39 am, Roedy Green <see_webs...@mindprod.com.invalid> wrote:
> On Tue, 22 Apr 2008 21:15:07 -0700 (PDT), pek <kimwl...@gmail.com> > wrote, quoted or indirectly quoted someone who said : [quoted text clipped - 4 lines] > It strikes me as an odd thing to do given how precious screen real > estate is. I did see one application of two horizontal scrollbars stacked on top of each other, where they acted like the focusing knobs on a high school microscope - one scroll bar was for largescale zooming/ translating, and the other was for more fine-grained control. It was some specialized scientific viewing thingy (I don't remember the details now) but for that domain, the users really seemed to like it.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|