查看标题。我试图将组件方向更改为RIGHT_TO_LEFT
,但这会产生意想不到的副作用 - 对于具有指定首选大小的组件,它会表现得很奇怪。
(JDK 1.6.0_23,Eclipse VE)
修改
以下是此示例:
我们JFrame
上有jMainScrollPane
。在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
由于这种奇怪的特性,我向Oracle提交了一个错误。他们给我邮寄了一个错误链接
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7038455
目前还没有这样的错误 - 我想,它正在检查中。
但问题仍未解决 - 是否有解决方法或其他方式?
答案 0 :(得分:2)
同意OP:这是错误。 RToL方向的设置触发viewPosition的计算。在布局完成之前发生。在这种情况下,JViewport返回视图的preferredSize而不是实际大小(当时为零)。在深层,BasicScrollPaneUI.Handler不知道伪造的大小,并根据不正确的数据计算。
这里有一些代码可以使用(OPs原版进一步剥离,添加彩色边框以查看其中的内容):
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 - 布局看起来没问题。
快速而肮脏的黑客可能就是在生成环境中做到这一点:在初始布局之后,强制CO进入LToR以允许正确的坐标然后返回到RToL。