Java 了解布局管理器——I';我不知道,请告诉我

Java 了解布局管理器——I';我不知道,请告诉我,java,swing,Java,Swing,我只是不明白为什么在调用validate()和repaint()方法时会调整大小。我很难理解这一点。本质上,我的程序就是这样显示的。我有一个主框架,在其中插入各种JPanel,我正在扩展这些JPanel以实现相册的各种功能。下面的类是NewAlbum类,它应该允许用户选择文件并用它们制作新的相册 选择文件的代码运行良好。一旦选择了文件,对NewAlbum面板的更改应该是“选择文件”按钮被“完成”按钮替换。在“完成”按钮下是一个JSplitPane,其水平拆分器刚好偏离中心,右侧大于左侧。当有关照

我只是不明白为什么在调用validate()和repaint()方法时会调整大小。我很难理解这一点。本质上,我的程序就是这样显示的。我有一个主框架,在其中插入各种JPanel,我正在扩展这些JPanel以实现相册的各种功能。下面的类是NewAlbum类,它应该允许用户选择文件并用它们制作新的相册

选择文件的代码运行良好。一旦选择了文件,对NewAlbum面板的更改应该是“选择文件”按钮被“完成”按钮替换。在“完成”按钮下是一个JSplitPane,其水平拆分器刚好偏离中心,右侧大于左侧。当有关照片的元数据输入到右侧时,左侧最终会有每张照片的缩略图

右侧窗格将是一个JScrollPane,其中包含一个JPanel,该JPanel以网格形式包含4个条目,要求用户提供有关这些条目的数据。在添加所有内容之后,维度就是我想要的位置,但是当我调用validate/repait组合时,维度变得“混乱”。我很确定这是因为我不理解我正在使用或扩展的各种类的默认布局管理器是如何工作的。请帮我理解。另外,告诉我GridBagLayout是我想要的,还是我想要的是另一个

新专辑代码如下

我为无法编译的代码道歉。我想你只要看看这个类,告诉我,“哦,是的,这就是问题所在。”下面是可编译的,并演示了这个问题。选择文件后,“拆分窗格”窗口将过窄且过长。我想把它放进框架里。实际上,它应该适合JFrame中的JPanel。

谢谢, 安迪

import javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JMenu;
导入javax.swing.JMenuBar;
导入javax.swing.JMenuItem;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.Container;
导入java.awt.Dimension;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.io.File;
导入java.text.ParseException;
导入java.text.simpleDataFormat;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Date;
导入java.util.Iterator;
导入javax.swing.JButton;
导入javax.swing.JFileChooser;
导入javax.swing.JLabel;
导入javax.swing.JOptionPane;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.JSplitPane;
导入javax.swing.JTextArea;
导入javax.swing.JTextField;
类Main扩展了JFrame{
静态JPanel transientPanel=null;
公用干管(){
超级();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
设置大小(640480);
JMenuBar menuBar=新的JMenuBar();
JMenu菜单=新JMenu(“示例”);
JMenuItem albumMenu=新JMenuItem(“新相册”);
albumMenu.addActionListener(新建ActionListener()){
已执行的公共无效行动(行动事件ae){
transientPanel=新专辑();
添加(瞬态面板);
验证();
重新油漆();
}
});
菜单。添加(相册菜单);
菜单栏。添加(菜单);
setJMenuBar(菜单栏);
验证();
}
公共静态void main(字符串[]args){
最终主管道m=新主管道();
m、 setVisible(真);
}
}
/**
*@description NewAlbum是显示给用户的窗口
*为相册选择新照片。选择后,用户
*将提供一个表单,用于完成此文档的元数据
*相册。
*@作者安迪
*/
类NewAlbum扩展了JPanel{
JButton选择文件;
按钮完成;
JButton nextButton=新JButton(“下一个图像”);
ArrayList文件数组;
JSplitPane splitWindow=新的JSplitPane(JSplitPane.HORIZONTAL_SPLIT,true);
JScrollPane滚动窗口;
JPanel rightSidePanel=新的JPanel();
JPanel leftSidePanel=新的JPanel();
JLabel subjectLabel=新JLabel(“图像主题:”);
JLabel locationLabel=新的JLabel(“图像位置:”);
JLabel commentLabel=新的JLabel(“注释:”);
JLabel dateLabel=新的JLabel(“日期(mm/dd/yyyy):”;
JTextField subjectText=新的JTextField(25);
JTextField locationText=新的JTextField(25);
JTextArea commentText=新的JTextArea(4,25);
JTextField dateText=新的JTextField(10);
公共新专辑(){
超级();
selectFiles=newjbutton(“选择照片”);
selectFiles.addActionListener(新建ActionListener(){
已执行的公共无效行动(行动事件ae){
选择filesforalbum();
}
});
添加(选择文件);
}
私有void configureRightPanel(){
int jPanelX=getParent().getWidth();
int jPanelY=getParent().getHeight()-30;//这应该是按钮的原因
//现在,调整此面板的大小,使其成为拆分窗格的正确大小
jPanelX=jPanelX-(int)(jPanelX*.31);
设置大小(jPanelX,jPanelY);
右侧面板。添加(主题标签);
右侧面板。添加(主题文本);
右侧面板。添加(位置标签);
右侧面板。添加(locationText);
右侧面板。添加(注释标签);
添加(注释文本);
添加(日期标签);
添加(日期文本);
右侧面板。添加(下一个按钮);
//对选定的照片进行迭代,现在制作虚假信息
}
私有ArrayList makeFileIntoArrayList(文件[]f){
ArrayList a=新的ArrayList();
a、 addAll(Arrays.asList(f));
返回filesArray=a;
}
/**
*选择文件孔
*此方法是NewAlbum类的专用方法。它是的处理程序
*当用户单击“选择”按钮时
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

class Main extends JFrame {
   static JPanel transientPanel = null;

   public Main() {
      super();
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setSize(640, 480);
      JMenuBar menuBar = new JMenuBar();
      JMenu menu = new JMenu("Example");
      JMenuItem albumMenu = new JMenuItem("New Album");
      albumMenu.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            transientPanel = new NewAlbum();
            add(transientPanel);
            validate();
            repaint();
         }
      });
      menu.add(albumMenu);
      menuBar.add(menu);

      setJMenuBar(menuBar);
      validate();
   }

   public static void main(String[] args) {
      final Main m = new Main();
      m.setVisible(true);
   }
}
/**
 * @description NewAlbum is the window that is presented to the user
 * to select new photographs for the album.  Once selected, the user
 * will be presented a form, of sorts, to complete the metadata for this
 * album.
 * @author Andy
 */
class NewAlbum extends JPanel {
    JButton selectFiles;
    JButton done;
    JButton nextButton = new JButton("Next Image");

    ArrayList<File> filesArray;

    JSplitPane splitWindow = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);
    JScrollPane scrollWindow;
    JPanel rightSidePanel = new JPanel();
    JPanel leftSidePanel = new JPanel();

    JLabel subjectLabel = new JLabel("Image subject:");
    JLabel locationLabel = new JLabel("Image location:");
    JLabel commentLabel = new JLabel("Comments:");
    JLabel dateLabel = new JLabel("Date (mm/dd/yyyy):");

    JTextField subjectText = new JTextField(25);
    JTextField locationText = new JTextField(25);
    JTextArea commentText = new JTextArea(4, 25);
    JTextField dateText = new JTextField(10);

    public NewAlbum() {
        super();

        selectFiles = new JButton("Select Photos");

        selectFiles.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                selectFilesForAlbum();
            }
        });
        add(selectFiles);
    }

    private void configureRightPanel() {
        int jPanelX = getParent().getWidth();
        int jPanelY = getParent().getHeight() - 30; // this should account for buttons

        // now, resize this panel so that it will be the right size for the split pane
        jPanelX = jPanelX - (int)(jPanelX * .31);
        rightSidePanel.setSize(jPanelX, jPanelY);

        rightSidePanel.add(subjectLabel);
        rightSidePanel.add(subjectText);
        rightSidePanel.add(locationLabel);
        rightSidePanel.add(locationText);
        rightSidePanel.add(commentLabel);
        rightSidePanel.add(commentText);
        rightSidePanel.add(dateLabel);
        rightSidePanel.add(dateText);
        rightSidePanel.add(nextButton);

        // iterate over the photos selected, make bogus info for now
    }

    private ArrayList<File> makeFileIntoArrayList(File[] f) {
        ArrayList<File> a = new ArrayList<File>();
        a.addAll(Arrays.asList(f));

        return filesArray = a;
    }

    /**
     * selectFilesForAlbum
     * This method is private to the NewAlbum class.  It is the handler for
     * when the user clicks on the "select photos" button.  When the function
     * executes, it displays the JFileChooser so that the user may select
     * the desired photos.  The files selected are assigned to a class variable
     * of type File[] which is used by the enterPhotoInfo method.
     *
     * @return void
     */
    private void selectFilesForAlbum() {
        JFileChooser jfc = new JFileChooser();
        jfc.setMultiSelectionEnabled(true);
        jfc.showOpenDialog(this);
        makeFileIntoArrayList(jfc.getSelectedFiles());

        changeButtonToDone();
        enterPhotoInfo();

        // TODO write the photo album to the disk
    }

    private void changeButtonToDone() {
        remove(selectFiles);
        done = new JButton("Done");
        add(done);

        // by the time this gets called, we'll have a parent container
        getParent().validate();
        getParent().repaint();
    }

    private void enterPhotoInfo() {
        splitWindow.setSize(this.getWidth(), this.getHeight() - 30);

        // remove when the left side panel actually has something
        Dimension iewDims = splitWindow.getSize();
        int leftX = iewDims.width - (int)(iewDims.width * .69);
        int leftY = iewDims.height;

        leftSidePanel.setSize(leftX, leftY);

        configureRightPanel();

        scrollWindow = new JScrollPane(rightSidePanel);
        scrollWindow.setSize(rightSidePanel.getSize());

        splitWindow.setRightComponent(scrollWindow);
        splitWindow.setLeftComponent(leftSidePanel);
        splitWindow.setDividerLocation(.31);

        System.out.println("Printing dimensions of before validate/repaint: this, splitWindow, scrollWindow, LSP, RSP");
        debugPrintDimensions(this);
        debugPrintDimensions(splitWindow);
        debugPrintDimensions(scrollWindow);
        debugPrintDimensions(leftSidePanel);
        debugPrintDimensions(rightSidePanel);

        //infoEntryWindow.add(infoScroller);
        this.add(splitWindow);
        this.validate();
        this.repaint();

        System.out.println("Printing dimensions of: this, splitWindow, scrollWindow, LSP, RSP");
        debugPrintDimensions(this);
        debugPrintDimensions(splitWindow);
        debugPrintDimensions(scrollWindow);
        debugPrintDimensions(leftSidePanel);
        debugPrintDimensions(rightSidePanel);
    }

    private void debugPrintDimensions(Container c) {
        System.out.println("DEBUG: Containers (x,y): (" +
                String.valueOf(c.getWidth()) +
                "," +
                String.valueOf(c.getHeight()) +
                ")");
    }
}
splitWindow.setSize(this.getWidth(), this.getHeight() - 30);