Swing JScrollPane - 如何将垂直滚动条设置为左侧?
看标题。我尝试将组件方向更改为 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 提交了一个错误。他们向我邮寄了错误链接
https://bugs.java.com/bugdatabase/view_bug? bug_id=7038455
目前还没有这样的错误 - 我想它正在被检查。
但问题仍然存在——是否有解决方法或其他方法?
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)
EDIT
Here is the example of this:
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.
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
Due to the strange nature of this, I've submitted a bug to Oracle. They mailed me a bug link
https://bugs.java.com/bugdatabase/view_bug?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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
同意OP的观点:这是错误。 RToL方向的设置会触发viewPosition的计算。这发生在布局完成之前。在这种情况下,JViewport 返回视图的首选大小而不是其实际大小(当时为零)。在内心深处,BasicScrollPaneUI.Handler 不知道那个伪造的大小,并根据不正确的数据进行计算。
下面是一些可以使用的代码(OP 原始版本进一步精简,添加了彩色边框以查看位置):
初始布局完全错误(如 OP 所报告),用按钮切换 CO 两次 - 布局看起来好的。
一个快速而肮脏的黑客可能是在生产环境中这样做:在初始布局后,强制 CO 进入 LToR 以允许正确的坐标,然后返回到 RToL。
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.
Here's some code to play with (the OPs original stripped down a bit further, added colored borders to see where is what):
The initial layout is completely wrong (as reported by OP), toggle the CO with the button twice - the Layout looks okay.
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.