java – 从右到左方向的按钮大小的无关更改

我有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添加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 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();
}
}

解决方法:

编辑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 /之下调整大小,就会出现错误行为(注意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:框架以最大化大小出现,子项填充已完成的内容,然后调整大小以打包并再次最大化:子项不填充
>评论2:框架出现几乎(一个像素更大)打包大小,最大化(和所有其他大小调整)正确填充屏幕

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

看起来像hack around是在一个包之后调整大小(稍微大约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);
    }
});

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

上一篇:php – 直接从iPad上传到网站时,Ipad照片不会旋转,但从计算机上传时可以正常


下一篇:php – 使用Ghostscript时禁止以PDF格式旋转页面