【问题标题】:GUI FlowLayout, lock all components positionGUI FlowLayout,锁定所有组件位置
【发布时间】:2015-10-11 00:01:44
【问题描述】:

我一直在四处寻找,但在使用FlowLayout 时找不到任何关于在窗口中锁定组件位置的信息。我使用的是GridLayout,除了不喜欢它的外观,我无法调整JTextArea 的大小。我把窗口上的所有东西都放在我想要的位置和正确的大小,除非用户调整窗口的大小,然后一切都在这个地方。

有什么方法可以锁定 JTextArea/JButtons/JLabels,以便用户调整窗口大小时它们不会移动,或者甚至可以更好地锁定窗口以便用户无法调整?

这是我尝试过的:

public class CopyFile extends JFrame{

private JFileChooser fc;
private JButton copyButton;
private JButton chooseFileButton;
private JButton destinationButton;
private File workingDirectory;
private JLabel sourceLabel;
private JTextArea displayCopyText;
private JLabel destinationLabel;
private JTextField sourceText;
private JLabel copyText;
private JTextField destinationText;

public static void main(String [] args) {
    CopyFile go = new CopyFile();
    go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    go.setSize(500, 150);
    go.setVisible(true);
}

public CopyFile() {
    super("Copy a text file");
    setLayout(new FlowLayout());
    fc = new JFileChooser();

    //Open dialog box inside project folder to make easier to find files
    workingDirectory = new File(System.getProperty("user.dir"));
    fc.setCurrentDirectory(workingDirectory);
    //create labels and buttons for window
    chooseFileButton = new JButton("CHOOSE SOURCE FILE");
    destinationButton = new JButton("DESTINATION FOLDER");
    copyButton = new JButton("COPY FILE");      
    sourceLabel = new JLabel("SOURCE FILE: ", JLabel.CENTER);
    sourceText = new JTextField(15);
    sourceText.setEditable(false);
    destinationText = new JTextField(15);
    destinationText.setEditable(false); 
    destinationLabel = new JLabel("DESTINATION:", JLabel.CENTER);
    //JScrollPane SP = new JScrollPane();       
    displayCopyText = new JTextArea();
    displayCopyText.setPreferredSize(new Dimension(300, 50));
    displayCopyText.setRows(2);
    displayCopyText.setLineWrap(true);
    displayCopyText.setWrapStyleWord(true);
    displayCopyText.setEditable(false);     



    //add everything to JFrame  
    add(sourceLabel);
    add(sourceText);
    add(chooseFileButton);  
    add(destinationLabel);
    add(destinationText);
    add(destinationButton);
    //add(copyText);
    add(displayCopyText);
    add(copyButton);

    //Create TheHandler object to add action listeners for the buttons.
    TheHandler handler = new TheHandler();
    chooseFileButton.addActionListener(handler);
    destinationButton.addActionListener(handler);
    copyButton.addActionListener(handler);
}

//Inner class to create action listeners    
private class TheHandler implements ActionListener {
    private File selectedDestinationFile;
    private File selectedSourceFile;
    private int returnVal;
    public void actionPerformed(ActionEvent event) {



        //Selecting a source file and displaying what the user is doing.
        if(event.getSource() == chooseFileButton) {     
            returnVal = fc.showOpenDialog(null);
            //Set the path for the source file. 
            if(returnVal == JFileChooser.APPROVE_OPTION) {  
                selectedSourceFile = fc.getSelectedFile();
                sourceText.setText(selectedSourceFile.getName());   
            }       
        }//end if

        //Handle destination button.
        if(event.getSource() == destinationButton) {
            returnVal = fc.showSaveDialog(null);
            if(returnVal == JFileChooser.APPROVE_OPTION) {
                selectedDestinationFile = fc.getSelectedFile();
                destinationText.setText(fc.getSelectedFile().getAbsolutePath());    
            }               
        }//end if

        //Handle copy button
        if(event.getSource() == copyButton) {
            Path sourcePath = selectedSourceFile.toPath();
            Path destinationPath = selectedDestinationFile.toPath();        
            try {
                Files.copy(sourcePath,  destinationPath);
            } catch (IOException e) {
                e.printStackTrace();
            }   

            if(returnVal == JFileChooser.APPROVE_OPTION) {      
                displayCopyText.append("SUCCESSFULLY COPIED:\n" 
                                + selectedDestinationFile.getName());   
            }
            else {
                displayCopyText.append("COPY WAS CANCELED BY USER.\n");
            }   
        }//end if

    }//end actionPerformed      
}//end TheHandler class
}//end class

【问题讨论】:

    标签: java swing user-interface resize flowlayout


    【解决方案1】:

    强烈不同意接受的答案,但我发现了一些问题:

    • 通过锁定设定的大小,您可能会在除您自己的平台之外的所有平台(操作系统、显示设置)中显示糟糕的 GUI。
    • 通过设置 JTextAreas 的显示大小,可以完全防止它在 JScrollPane 中滚动。
    • 通过强制使用相对“笨拙”的布局管理器 FlowLayout 显示您的 GUI,您会限制您的布局选项。
    • 通过设置任何组件的大小,您可以人为地限制其大小,从而防止布局管理器和组件本身为该平台的组件设置最佳大小。

    相反,我建议:

    • 您应该设置 JTextArea 的显示行和列
    • 在 JScrollPane 中显示 JTextArea。
    • 使用更灵活的布局管理器,或者通常更好的布局组合,通常由嵌套的 JPanel 使用,每个都使用自己的布局管理器。
    • 避免设置尺寸,而是在添加所有组件后在您的顶级窗口上调用pack(),从而让布局和组件自己调整到最佳尺寸。

    例如:

    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class CopyFile2 extends JPanel {
       private static final int ROWS = 3;
       private static final int COLS = 20;
       private static final int GBC_I = 4;
       private static final Insets INSETS = new Insets(GBC_I, GBC_I, GBC_I, GBC_I);
       private JTextField sourceField = new JTextField(10);
       private JTextField destField = new JTextField(10);
       private JTextArea displayCopyText = new JTextArea(ROWS, COLS);
    
       public CopyFile2() {
          setLayout(new GridBagLayout());
          add(new JLabel("Source File:"), createGbc(0, 0));
          add(sourceField, createGbc(1, 0));
          add(new JButton("Choose Source File"), createGbc(2, 0));
          add(new JLabel("Destination:"), createGbc(0, 1));
          add(destField, createGbc(1, 1));
          add(new JButton("Destination Folder"), createGbc(2, 1));
    
          GridBagConstraints gbc = createGbc(0, 2);
          gbc.gridwidth = 2;
          add(new JScrollPane(displayCopyText), gbc);
          add(new JButton("Copy File"), createGbc(2, 2));      
       }
    
       private GridBagConstraints createGbc(int x, int y) {
          GridBagConstraints gbc = new GridBagConstraints();
          gbc.gridx = x;
          gbc.gridy = y;
          gbc.weightx = 1.0;
          gbc.weighty = 1.0;
          gbc.fill = GridBagConstraints.HORIZONTAL;
          gbc.insets = INSETS;
          return gbc;
       }
    
       private static void createAndShowGUI() {
          CopyFile2 paintEg = new CopyFile2();
    
          JFrame frame = new JFrame("CopyFile2");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(paintEg);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGUI();
             }
          });
       }
    }
    

    【讨论】:

      【解决方案2】:

      您可以使用JFrame::setResizable(false) 锁定正在调整大小的窗口。

      所以你的代码可能是这样的

      public static void main(String[] args) {
              CopyFile go = new CopyFile();
              go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      
              go.setResizable(false);   //No resize is possible
      
             go.setSize(500, 150);
             go.setVisible(true);
      }
      

      这可能会解决您的问题

      使用固定大小是一个非常非常糟糕的主意。尝试使用更灵活的布局可能会组合布局来实现您的目标。关于布局管理器见here

      尝试关注Hovercraftanswer

      【讨论】:

      • 完美,因为无论如何,一切都在我想要的地方。谢谢!
      • 哦,好的。我有一个 GridLayout,但我无法得到 JTextArea 的大小和我想要的位置,而 FlowLayout 看起来和工作得很好。这是课堂作业,但我明白你在说什么。
      • @sjud9227:设置尺寸是非常糟糕的做法。
      • 是的,我没有意识到布局可以在不同的机器上改变,谢谢你的帮助!
      猜你喜欢
      • 1970-01-01
      • 2020-08-11
      • 2012-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-05
      相关资源
      最近更新 更多