从右到左方向的按钮大小无关紧要

我有9个jbuttons添加到jpanel,面板添加到jscrollpane,它添加到jframe。

http://www.pic1.iran-forum.ir/images/up9/95426323683658592564.jpg

当我通过以下applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);更改框架方向时: applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

面板向右移动,按钮大小固定,不会填充面板,但您在下图中看到滚动条填满了面板的所有宽度

http://www.pic1.iran-forum.ir/images/up9/60975202722295688553.jpg

(我使用gridbaglayout添加按钮,使用borderlayout.center添加scrollpane)。

这是java中的错误还是?

编辑:它是最简单的观点。 有帮助吗?

 import java.awt.BorderLayout; import java.awt.ComponentOrientation; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import javax.swing.*; public class MyFrame extends JFrame{ private JButton[] arrayButton = new JButton[9]; private JButton btnLeft = new JButton(""); private JScrollPane scpButtons = new JScrollPane(); public MyFrame() { for (int i = 0; i < arrayButton.length; i++) arrayButton[i] = new JButton("btn"); JPanel pnlButton = initPnlButton(); scpButtons.setViewportView(pnlButton); setLayout(new BorderLayout()); add(scpButtons, BorderLayout.CENTER); // comment it and see the result applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); pack(); setDefaultCloseOperation(EXIT_ON_CLOSE); setExtendedState(JFrame.MAXIMIZED_BOTH); setVisible(true); } private JPanel initPnlButton() { JPanel pnlButton = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1, 1, 10, 1, new Insets(0, 0, 0, 0), 0, 0); int ind = 0; int row = 3; int column = 4; for (int i = 0; i < row; i++) { for (int j = 1; j < column; j++) { gbc.gridx = j; gbc.gridy = i; pnlButton.add(arrayButton[ind++], gbc); } } gbc.weightx = 0; gbc.gridheight = 3; gbc.gridx = 0; gbc.gridy = 0; pnlButton.add(btnLeft, gbc); gbc.gridx = 4; gbc.gridy = 0; pnlButton.add(btnRight, gbc); pnlButton.setPreferredSize(new Dimension(1000, 700)); return pnlButton; } public static void main(String[] args) { new MyFrame(); } } 

编辑4

(希望是最后一次:-)

最终的罪魁祸首似乎是scrollPane的主要视口:当它在RToL中的视图大小超过其首选时,它会变得混乱。 没有跟踪到底出了什么问题,但看起来像是可行的(没有找到核心中的bug并轻推snoracle来修复它;)解决方案是使视图实现Scrollablable,具体实现

  • getPreferredScrollableViewportSize返回getPreferredSize
  • 实现getScrollableTracksViewportHeight / Width如果高度/宽度小于父高度/宽度则返回true,否则返回false

JXPanel(包含在SwingX中 )是一个Scrollable,它默认执行第一个,并且可以通过设置ScrollableSizeHints来为后者配置:

 private JPanel initPnlButton() { JXPanel pnlButton = new JXPanel(new GridBagLayout()); pnlButton.setScrollableWidthHint(ScrollableSizeHint.PREFERRED_STRETCH); pnlButton.setScrollableHeightHint(ScrollableSizeHint.PREFERRED_STRETCH); ... } 

有了这个,不需要进一步的hacky线,只需在添加所有组件后应用CO:

 applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); pack(); setExtendedState(JFrame.MAXIMIZED_BOTH); setVisible(true); 

编辑2

我们(@Reza Gh和我)玩选项越多,我越倾向于将行为看作是一个错误。 总结我们的最新发现

  • scrollPane似乎是一个罪魁祸首(Reza)
  • 一旦面板在其preferredSize /下面resize,就会出现不良行为(注意arteficial – 至少我希望它不是Reza生产代码的一部分 – 创建面板时setPreferred)

编辑

玩了一下,它看起来像是一个非常奇怪的实例化行为。 要播放的片段(在实例化结束时)

 pack(); // [1] setSize(getWidth() + 1, getHeight() + 1); // [2] setExtendedState(JFrame.MAXIMIZED_BOTH); setVisible(true); SwingUtilities.invokeLater(new Runnable() { public void run() { applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); } }); 

和评论1,2或两者

  • 评论两者:框架出现在打包大小,最大化它不填充框架,但孩子停靠在右边缘
  • 注释1:框架以最大化的大小出现,子项填充已完成的内容,然后resize以打包并再次最大化:子项不填充
  • 注释2:框架出现几乎(一个像素更大)打包大小,最大化(和所有其他大小调整)正确填充屏幕

确切的行为可能取决于本机组件方向(我的是LToR)。 总的来说,我认为这是一个在核心处理组件方向的某个地方的错误(不出所料,它不像我们在这些年后所期望的那样稳定)。

看起来像是在一个包之后resize(稍微大约1个像素,单独最大不起作用),然后调用applyCO。

原版的

这不能解决原始问题(即在框架实例化时应用componentOrientation),仅演示如何在运行时安全地切换CO

 Action createCOToggle(final JFrame frame) { Action toggleComponentOrientation = new AbstractAction("toggle orientation") { @Override public void actionPerformed(ActionEvent e) { ComponentOrientation current = frame.getComponentOrientation(); if (current.isLeftToRight()) { frame.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); } else { frame.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); } frame.getRootPane().revalidate(); frame.invalidate(); frame.validate(); frame.repaint(); } }; return toggleComponentOrientation; } 

使用它配置动作感知组件,将使帧按预期运行,即填充整个区域。 许多re / in / validates看起来很奇怪 – 但结果certificate是必要的(在jdk6中)我们在SwingX测试覆盖中经历过

现在我的期望是,在帧的实例化结束时调用相同的动作会使它表现得同样,那就是

 .... // configure/fill frame setVisible(true); SwingUtilities.invokeLater(new Runnable() { public void run() { createCOToggle(MyFrame.this).actionPerformed(null); } }); 

不幸的是,事实并非如此。 目前还没有任何线索,为什么不,抱歉。

在玩了很多属性并在陈述中上下移动后我找到了答案。 如果你放

 scpButtons.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); 

applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

一切都会好的,不需要setSize(getWidth() + 1, getHeight() + 1);

很有趣它从我这里得到了一天…… c#或其他langs有这样的错误吗?

如果你让SwingUtilities集团运行,那么为了调整窗口的大小,一切都还没有。

 import java.awt.BorderLayout; import java.awt.ComponentOrientation; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import javax.swing.*; public class MyFrame extends JFrame { private JButton[] arrayButton = new JButton[9]; private JButton btnLeft = new JButton("<"); private JButton btnRight = new JButton(">"); private JScrollPane scpButtons = new JScrollPane(); public MyFrame() { for (int i = 0; i < arrayButton.length; i++) arrayButton[i] = new JButton("btn"); JMenu mnuSettings = new JMenu("MENU"); JMenuBar menubar = new JMenuBar(); menubar.add(mnuSettings); setJMenuBar(menubar); JPanel pnlButton = initPnlButton(); scpButtons.setViewportView(pnlButton); setLayout(new BorderLayout()); setDefaultCloseOperation(EXIT_ON_CLOSE); add(scpButtons, BorderLayout.CENTER); pack(); // [1] setExtendedState(JFrame.MAXIMIZED_BOTH); //setSize(getWidth() + 1, getHeight() + 1); // [2] setVisible(true); // SwingUtilities.invokeLater(new Runnable() { // public void run() { applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); //here scpButtons.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); // } // }); } private JPanel initPnlButton() { JPanel pnlButton = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1, 1, 10, 1, new Insets(0, 0, 0, 0), 0, 0); int ind = 0; int row = 3; int column = 4; for (int i = 0; i < row; i++) { for (int j = 1; j < column; j++) { gbc.gridx = j; gbc.gridy = i; pnlButton.add(arrayButton[ind++], gbc); } } gbc.weightx = 0; gbc.gridheight = 3; gbc.gridx = 0; gbc.gridy = 0; pnlButton.add(btnRight, gbc); gbc.gridx = 4; gbc.gridy = 0; pnlButton.add(btnLeft, gbc); pnlButton.setPreferredSize(new Dimension(1000, 700)); return pnlButton; } public static void main(String[] args) { new MyFrame(); } 

}