开发者

How to make Scrollbar of scroll pane make movable automatically with the cursor as we press TAB Button on keyboard?

I have following code. After executing following code It shows an JFrame containg A JInternalFrame which has a JScrollPane This JScrollPane has a JPanel has many input controls. As the size of JPanel is larger because of many input controls than the size of JInternalFrame So I it Scrollable.

import java.awt.Dimension;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

public class InterfaceDesign {

    public static void main(String args[]) {
        InterfaceDesign id = new InterfaceDesign();
        id.getPnlProjectDetail("My Project");
    }

    public void getPnlProjectDetail(String strProjectName) {
        JPanel pnlPjDetail = new JPanel();
        JScrollPane scrPjDetail;
        pnlPjDetail.setLayout(null);
        pnlPjDetail.setBounds(0, 0, 400, 400);
        JFrame frmtest = new JFrame();
        JInternalFrame interFrame = new JInternalFrame();
        interFrame.setBounds(0, 0, 280, 180);

        frmtest.setBounds(1, 1, 300, 200);
        pnlPjDetail.setPreferredSize(new Dimension(400, 400));

        JLabel lblFirstName = new JLabel("First Name");
        JLabel lblLastName = new JLabel("Last Name");
        JLabel lblAddress = new JLabel("Address");
        JLabel lblCity = new JLabel("City");
        JLabel lblZipCode = new JLabel("Zip Code");
        JLabel lblPhone = new JLabel("Phone");
        JLabel lblEmailID = new JLabel("Emain Id");

        JTextField tfFirstName = new JTextField();
        JTextField tfLastName = new JTextField();
        JTextField tfAddress = new JTextField();
        JTextField tfCity = new JTextField();
        JTextField tfZipCode = new JTextField();
        JTextField tfPhone = new JTextField();
        JTextField tfEmailID = new JTextField();

        lblFirstName.setBounds(25, 55, 85, 20);
        tfFirstName.setBounds(25, 85, 85, 20);
        pnlPjDetail.add(lblFirstName);
        pnlPjDetail.add(tfFirstName);

        lblLastName.setBounds(25, 115, 85, 20);
        tfLastName.setBounds(25, 145, 85, 20);
        pnlPjDetail.add(lblLastName);
        pnlPjDetail.add(tfLastName);

        lblAddress.setBounds(25, 175, 85, 20);
        tfAddress.setBounds(25, 205, 85, 20);
        pnlPjDetail.add(lblAddress);
        pnlPjDetail.add(tfAddress);

        lblCity.setBounds(25, 235, 85, 20);
        tfCity.setBounds(25, 265, 85, 20);
        pnlPjDetail.add(lblCity);
        pnlPjDetail.add(tfCity);

        lblZipCode.setBounds(25, 295, 85, 20);
        tfZipCode.setBounds(25, 325, 85, 20);
        pnlPjDetail.add(lblZipCode);
        pnlPjDetail.add(tfZipCode);

        lblPhone.setBounds(25, 355, 85, 20);
        tfPhone.setBounds(25, 385, 85, 20);
        pnlPjDetail.add(lblPhone);
        pnlPjDetail.add(tfPhone);

        lblEmailID.setBounds(25, 415, 85, 20);
        tfEmailID.setBounds(25, 445, 85, 20);
        pnlPjDetail.add(lblEmailID);
        pnlPjDetail.add(tfEmailID);

        scrPjDetail = new JScrollPane(pnlPjDetail);

        scrPjDetail.setAutoscrolls(true);

        //frmtest.setContentPane(scrProjectDetail);
        interFrame.setContentPane(scrPjDetail);
        JDesktopPane dpane = new JDesktopPane();
        interFrame.setVisible(true);
        dpane.add(interFrame);

        //frmtest.getLayeredPane().add(interFrame);
        frmtest.setContentPane(dpane);
        //frmtest.add(scrProjectDetail);
        frmtest.setVisible(true);
        frmtest.setResizable(false);
        frmtest.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //return pnlPjDetail;
    }
}

I need your guidance in solving following problems/doubts

  1. As we press TAB Button on keyboard the cursor moves from one text box to another but the ScrollBar (here vertical scroll bar) does not moves automatically with the cursor as cursor moves to the lower input fields So how to make the scrollbar move itself with the cursor as it moves either downwards or upperwards?
  2. As this is a demo code is it possible to add the two JscrollPan开发者_运维问答e in JInterNalFrame side by Side?
  3. Is it necessary to user JDesktopPane to add JInternalFrame in to JFrame? i.e. is it true that we can not add JInternalFrame as follows <JFrame>.getContentPane.add(<JInternalFrame>);


Simple task, astonishingly quirky solutions - personally, I judge every application code solution which must rely on focus as quirky ;-)

Couldn't come up with anything not depending on focus: only marginally more maintainable by not requiring a focusListener on each component on the form. Instead, register a PropertyChangeListener with the KeyboardFocusManager and do the scrolling when notified about change in its permanentFocusOwner property

public static class FocusDrivenScroller implements PropertyChangeListener {

    private JComponent parent;

    public FocusDrivenScroller(JComponent parent) {
        this.parent = parent;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        Component focused = (Component) evt.getNewValue();
        if (focused == null || !SwingUtilities.isDescendingFrom(focused, parent)) return;
        parent.scrollRectToVisible(focused.getBounds());
    }

}

To use in application code, instantiate with the form that resides inside a JScrollPane

public void buildAndShowDetailsFrame(String strProjectName) {
    // the container to scroll such that a focused child
    // is visible when gaining focus
    JPanel detailsForm = new JPanel();
    KeyboardFocusManager.getCurrentKeyboardFocusManager()
        .addPropertyChangeListener("permanentFocusOwner", 
                new FocusDrivenScroller(detailsForm));

    // choose and use an appropriate LayoutManager
    // note: this is only an example!
    // real-world requirements most probably need a stronger one
    detailsForm.setLayout(new BoxLayout(detailsForm, BoxLayout.PAGE_AXIS));
    // quick fill with stuff 
    String[] labels = {"First Name", "Last Name", 
            "Address", "City", "Zip Code", "Phone", "Emain Id"};
    for (String string : labels) {
        detailsForm.add(new JLabel(string));
        detailsForm.add(new JTextField());
    }
    JFrame frame = new JFrame();
    frame.add(new JScrollPane(detailsForm));
    frame.pack();
    // force scrollbar to appear
    frame.setSize(frame.getWidth(), frame.getHeight()/2);
    frame.setVisible(true);
    frame.setResizable(false);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

apart from the first lines of this methods, it's only a shortened version of the OP code (to lure him/her into using an appropriate LayoutManager :-)


Scrolling a Form is a fancy implementation of Kleopartra's suggestion.


Regarding your scrolling question: you can e.g. add a listener to focus events and scroll your pane accordingly.

FocusAdapter scrollFocusListener = new FocusAdapter() {
@Override
    public void focusGained(FocusEvent e) {
        System.out.println(((JComponent) e.getSource()).getBounds());
        scrPjDetail.getViewport().scrollRectToVisible(((JComponent) e.getSource()).getBounds());
    }
};
tfFirstName.addFocusListener(scrollFocusListener);
tfLastName.addFocusListener(scrollFocusListener);
tfAddress.addFocusListener(scrollFocusListener);
...


try this:

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class InterfaceDesign {

    private SrcollListener l = new SrcollListener();

    public static void main( String args[] ) {
        InterfaceDesign id = new InterfaceDesign();
        id.getPnlProjectDetail( "My Project" );
    }

    public void getPnlProjectDetail( String strProjectName ) {
        JPanel pnlPjDetail = new JPanel();
        JPanel pnlPjDetail2 = new JPanel();
        JScrollPane scrPjDetail;
        JScrollPane scrPjDetail2;
        pnlPjDetail.setLayout( null );
        pnlPjDetail.setBounds( 0, 0, 200, 250 );
        pnlPjDetail2.setLayout( null );
        pnlPjDetail2.setBounds( 0, 0, 200, 300 );
        JFrame frmtest = new JFrame();
        JInternalFrame interFrame = new JInternalFrame();
        interFrame.setBounds( 0, 0, 280, 180 );

        frmtest.setBounds( 1, 1, 600, 200 );
        pnlPjDetail.setPreferredSize( new Dimension( 200, 250 ) );
        pnlPjDetail2.setPreferredSize( new Dimension( 200, 300 ) );

        JLabel lblFirstName = new JLabel( "First Name" );
        JLabel lblLastName = new JLabel( "Last Name" );
        JLabel lblAddress = new JLabel( "Address" );
        JLabel lblCity = new JLabel( "City" );
        JLabel lblZipCode = new JLabel( "Zip Code" );
        JLabel lblPhone = new JLabel( "Phone" );
        JLabel lblEmailID = new JLabel( "Emain Id" );

        JTextField tfFirstName = new JTextField();
        JTextField tfLastName = new JTextField();
        JTextField tfAddress = new JTextField();
        JTextField tfCity = new JTextField();
        JTextField tfZipCode = new JTextField();
        JTextField tfPhone = new JTextField();
        JTextField tfEmailID = new JTextField();

        lblFirstName.setBounds( 25, 55, 85, 20 );
        tfFirstName.setBounds( 25, 85, 85, 20 );
        tfFirstName.addFocusListener( l );
        pnlPjDetail.add( lblFirstName );
        pnlPjDetail.add( tfFirstName );

        lblLastName.setBounds( 25, 115, 85, 20 );
        tfLastName.setBounds( 25, 145, 85, 20 );
        tfLastName.addFocusListener( l );
        pnlPjDetail.add( lblLastName );
        pnlPjDetail.add( tfLastName );

        lblAddress.setBounds( 25, 175, 85, 20 );
        tfAddress.setBounds( 25, 205, 85, 20 );
        tfAddress.addFocusListener( l );
        pnlPjDetail.add( lblAddress );
        pnlPjDetail.add( tfAddress );

        lblCity.setBounds( 25, 55, 85, 20 );
        tfCity.setBounds( 25, 85, 85, 20 );
        tfCity.addFocusListener( l );
        pnlPjDetail2.add( lblCity );
        pnlPjDetail2.add( tfCity );

        lblZipCode.setBounds( 25, 115, 85, 20 );
        tfZipCode.setBounds( 25, 145, 85, 20 );
        tfZipCode.addFocusListener( l );
        pnlPjDetail2.add( lblZipCode );
        pnlPjDetail2.add( tfZipCode );

        lblPhone.setBounds( 25, 175, 85, 20 );
        tfPhone.setBounds( 25, 205, 85, 20 );
        tfPhone.addFocusListener( l );
        pnlPjDetail2.add( lblPhone );
        pnlPjDetail2.add( tfPhone );

        lblEmailID.setBounds( 25, 235, 85, 20 );
        tfEmailID.setBounds( 25, 265, 85, 20 );
        tfEmailID.addFocusListener( l );
        pnlPjDetail2.add( lblEmailID );
        pnlPjDetail2.add( tfEmailID );

        scrPjDetail = new JScrollPane( pnlPjDetail );
        scrPjDetail2 = new JScrollPane( pnlPjDetail2 );

        scrPjDetail.setAutoscrolls( true );

        //frmtest.setContentPane(scrProjectDetail);
        JSplitPane splitPane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, scrPjDetail, scrPjDetail2 );
        splitPane.setDividerLocation( 300 );
        interFrame.setContentPane( splitPane );
        interFrame.setVisible( true );

        //frmtest.getLayeredPane().add(interFrame);
        frmtest.setContentPane( interFrame );
        //frmtest.add(scrProjectDetail);
        frmtest.setVisible( true );
        frmtest.setResizable( false );
        frmtest.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

        //return pnlPjDetail;       
    }

    public class SrcollListener implements FocusListener {

        @Override
        public void focusGained( FocusEvent e ) {
            final Component component = e.getComponent();
            if( component != null && component.getParent() != null && component.getParent() instanceof JComponent ) {
                SwingUtilities.invokeLater( new Runnable() {
                    @Override
                    public void run() {
                        ((JComponent)component.getParent()).scrollRectToVisible( component.getBounds() );
                    }
                } );
            }
        }

        @Override
        public void focusLost( FocusEvent e ) {
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜