2011-04-20 87 views
1

看到标题。我试图将组件方向更改为RIGHT_TO_LEFT,但这有一个意想不到的副作用 - 它具有指定首选大小的组件的行为奇怪。Swing JScrollPane - 如何将垂直滚动条设置到左侧?

(JDK 1.6.0_23,Eclipse的VE)

编辑

下面是这个例子:

我们JFramejMainScrollPane就可以了。在jMainScrollPane里面我们放置了一个jMainPanel。现在将jMainPanel的首选尺寸设置为比jMainScrollPane更窄。 jMainPanel仍将占用jMainScrollPane上的所有空间。现在将jMainScrollPane的方向改为RIGHT_TO_LEFT,看看会发生什么。

示例代码(改变jMainScrollPane的方向看到的差异):

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

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

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

目前有没有这样的错误,但 - 我想,它被选中。

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

+2

重复[JScrollPane左滚动条](http://stackoverflow.com/questions/1311689/jscrollpane-with-scroll-bar-to-left) – Manoj 2011-04-20 08:06:45

+0

@Manoj似乎像@Frozen_Spider已经尝试了答案提到的问题,但结果不满意。 – Riduidel 2011-04-20 08:10:17

+0

@Frozen_Spider当你写下“布局糟糕的布局”时,你能告诉我们你的意思吗?或发送截图? – Riduidel 2011-04-20 08:10:52

回答

2

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

下面是一些代码一起玩(原进一步剥离下来一点的OP,添加彩色边框,看看是什么):

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两次 - 布局看起来没问题。

一个快速和肮脏的黑客可能只是在procduction上下文中做的:在初始布局后,强制CO进入LToR允许正确的坐标,然后回到RToL。

+0

谢谢你,肮脏的黑客工程:)我也发布了一个错误链接,但 - 对我的耻辱 - 我描述了一个bug远远最糟糕的是你没有。 – 2011-04-21 10:52:58

+0

@Frozen Spider很高兴它适合你:-)什么是评论ID(自动错误响应的号码)? – kleopatra 2011-04-21 12:50:03

+0

无论如何,这个bug有什么秘诀......'出于安全原因,一些错误不包括在Bug数据库中。' – eee 2011-04-21 13:45:12