Swing JScrollPane-如何将垂直滚动条设置到左侧? [英] Swing JScrollPane - how to set vertical scroll bar to left?

查看:110
本文介绍了Swing JScrollPane-如何将垂直滚动条设置到左侧?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

查看标题.我尝试将组件的方向更改为RIGHT_TO_LEFT,但这有意外的副作用-对于具有指定首选尺寸的组件,它的行为会很奇怪.

See the title. I've tried to change component orientation to RIGHT_TO_LEFT, but that had a unexpected side effect - it behaves strangely with components with specified preferred size.

(JDK 1.6.0_23,Eclipse VE)

(JDK 1.6.0_23, Eclipse VE)

编辑

以下是示例:

我们有JFramejMainScrollPane.在jMainScrollPane内部,放置一个jMainPanel.现在将jMainPanel的首选大小设置为小于jMainScrollPane的首选大小. jMainPanel仍会占用jMainScrollPane上的所有空间.现在,将jMainScrollPane的方向更改为RIGHT_TO_LEFT,然后看看会发生什么.

We have JFrame with jMainScrollPane on it. Inside jMainScrollPane we place a jMainPanel. Now set jMainPanel's preferred size to be narrower than jMainScrollPane's. jMainPanel will still take all the space on jMainScrollPane. Now changejMainScrollPane's orientation to RIGHT_TO_LEFT and see what happen.

示例代码(更改jMainScrollPane的方向以查看不同之处):

Sample code (change jMainScrollPane's orientation to see the difference):

import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Dimension;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class TestFrame extends JFrame {
    private JPanel      jContentPane    = null;
    private JScrollPane jMainScrollPane = null;
    private JPanel      jMainPanel      = null;

    public TestFrame(){
        super();
        initialize();
    }

    private void initialize(){
        this.setSize(480, 339);
        this.setContentPane(getJContentPane());
        this.setTitle("JFrame");
    }

    private JPanel getJContentPane(){
        if (jContentPane == null) {
            jContentPane = new JPanel();
            jContentPane.setLayout(new BorderLayout());
            jContentPane.add(getJMainScrollPane(), BorderLayout.CENTER);
        }
        return jContentPane;
    }

    private JScrollPane getJMainScrollPane(){
        if (jMainScrollPane == null) {
            jMainScrollPane = new JScrollPane();
            jMainScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
            jMainScrollPane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
            jMainScrollPane.setViewportView(getJMainPanel());
        }
        return jMainScrollPane;
    }

    private JPanel getJMainPanel(){
        if (jMainPanel == null) {
            jMainPanel = new JPanel();
            jMainPanel.setLayout(new BorderLayout());
            jMainPanel.setPreferredSize(new Dimension(30, 30));
        }
        return jMainPanel;
    }
}

EDIT2

由于这种奇怪的性质,我已经向Oracle提交了一个错误.他们给我寄了一个错误链接

Due to the strange nature of this, I've submitted a bug to Oracle. They mailed me a bug link

http://bugs.sun.com/bugdatabase/view_bug.do? bug_id = 7038455

目前还没有此类错误-我想是正在检查中.

At the moment there is no such bug yet - I suppose, it's being checked.

但是,问题仍然存在-是否有解决方法或其他方法?

But still, question is open - is there a workaround or another way?

推荐答案

同意OP:这是错误. RToL方向的设置触发viewPosition的计算.这种情况发生在布局完成之前.在这种情况下,JViewport返回视图的preferredSize而不是其实际大小(当时为零).在肠子深处,BasicScrollPaneUI.Handler不知道该伪造的大小,并基于不正确的数据进行计算.

Agree with the OP: it's bug. The setting of RToL orientation triggers the calculation of the viewPosition. This happens before the layout is done. In that case, the JViewport returns the view's preferredSize instead of its actual size (which at that time is zero). Deep in the bowels, the BasicScrollPaneUI.Handler doesn't know about that faked size and bases its calculation on incorrect data.

这里有一些代码可以使用(OP原件进一步精简,添加了彩色边框以查看位置):

Here's some code to play with (the OPs original stripped down a bit further, added colored borders to see where is what):

public class COInScrollPane extends JFrame {

    public COInScrollPane(){
        super();
        initialize();
    }

    private void initialize(){
        this.setTitle("JFrame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JScrollPane jMainScrollPane = getJMainScrollPane();
        this.add(jMainScrollPane);
        this.setSize(480, 339);
        Action action = new AbstractAction("Toggle CO") {

            @Override
            public void actionPerformed(ActionEvent e) {
                ComponentOrientation co = jMainScrollPane.getComponentOrientation().isLeftToRight() ?
                        ComponentOrientation.RIGHT_TO_LEFT : ComponentOrientation.LEFT_TO_RIGHT;
                jMainScrollPane.applyComponentOrientation(co);
                jMainScrollPane.revalidate();
                jMainScrollPane.repaint();
            }
        };
        add(new JButton(action), BorderLayout.SOUTH);
    }

    private JScrollPane getJMainScrollPane() {
        JScrollPane jMainScrollPane = new JScrollPane(getJMainPanel());
        jMainScrollPane.setViewportBorder(BorderFactory
                .createLineBorder(Color.GREEN));
        jMainScrollPane
                .applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
        return jMainScrollPane;
    }

    private JPanel getJMainPanel() {
        JPanel jMainPanel = new JPanel();
        jMainPanel.add(new JButton("just a button"));
        jMainPanel.setBorder(BorderFactory.createLineBorder(Color.RED));
        return jMainPanel;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new COInScrollPane().setVisible(true);

            }
        });
    }
}

初始布局完全错误(如OP所述),请使用按钮两次切换CO-布局看起来还可以.

The initial layout is completely wrong (as reported by OP), toggle the CO with the button twice - the Layout looks okay.

一个快速而肮脏的技巧可能就是在生产过程中这样做:在初始布局之后,将CO强制放入LToR以允许正确的坐标,然后返回RToL.

A quick and dirty hack might be to do just that in procduction context: after initial layout, force the CO into LToR to allow for correct coordinates then back to RToL.

这篇关于Swing JScrollPane-如何将垂直滚动条设置到左侧?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆