2011-04-20 148 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