我有9个jbuttons添加到jpanel,面板添加到jscrollpane并添加到jframe。
http://www.pic1.iran-forum.ir/images/up9/95426323683658592564.jpg
当我通过以下方式更改框架方向时:
applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
面板向右移动,按钮大小固定,不会填充面板,但您在下图中看到滚动条填满了面板的所有宽度
http://www.pic1.iran-forum.ir/images/up9/60975202722295688553.jpg
(我使用gridbaglayout添加按钮,使用borderlayout.center添加滚动窗格)。
是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 JButton btnRight = 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();
}
}
答案 0 :(得分:4)
编辑4
(希望最后:-)
最终的罪魁祸首似乎是scrollPane的主要视口:当它在RToL中的视图大小超过其首选时,它会变得混乱。没跟踪到底出了什么问题,但看起来是可行的(没有找到核心中的bug并轻推snoracle来修复它;)解决方案是使视图实现Scrollablable,具体实现
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和我)玩选项的次数越多,我越倾向于将行为视为错误。总结我们的最新发现
修改强>
再玩一点,它看起来像是一个非常奇怪的实例化行为。要播放的片段(在实例化结束时)
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或两者
确切的行为可能取决于本机组件方向(我的是LToR)。总的来说,我认为这是组件方向核心处理中的一个错误(不出所料,它不像我们在这些年后所期望的那样稳定)。
看起来像是在一个包之后调整大小(稍微大约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看起来很奇怪 - 但结果证明是必要的(在jdk6中),正如我们在SwingX test coverage中所经历的那样
现在我的期望是,在帧的实例化结束时调用相同的动作会使它表现得很好,那就是
.... // configure/fill frame
setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createCOToggle(MyFrame.this).actionPerformed(null);
}
});
不幸的是,事实并非如此。目前还没有任何线索,为什么不,抱歉。
答案 1 :(得分:1)
在玩了很多属性并在声明中上下移动后我找到了答案。 如果你把
scpButtons.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
后
applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
一切都会好起来,不需要setSize(getWidth() + 1, getHeight() + 1);
如此有趣,它从我这里度过了一天...... c#或其他langs有这样的错误吗?
如果你让SwingUtilities
bloc运行,那么为了调整窗口的大小,一切都是LtR。
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();
}
}