Простое руководство по GUI. Могу ли я придерживаться BorderLayout или мне нужно что-то еще?

1

Я пытаюсь создать графический интерфейс для личного проекта. У меня есть выбор файла, область консоли, текстовое поле (с меткой), панель кнопок (2 кнопки) и, наконец, область "зона выпадения".

Графический интерфейс разделен вертикально пополам с помощью консоли справа. На UpperLeft у меня есть FileChooser, расположенный в BorderLayout.CENTER, а затем ButtonPanel на BorderLayout.SOUTH.

Ниже находится "зона выпадения",

В настоящее время он выглядит примерно так:

 _________________
|  file  | console|
| chooser|        |
| buttons|        |
|--------|        |
| drop   |        |
| zone   |        |
|________|________|

Я хочу добавить новое текстовое поле между файловым выбором и панелью кнопок, но когда я меняю выбор файла на NORTH, jtextfield на CENTER и кнопки SOUTH, выбор файла странно мал и jtextfield очень велик. Я думаю, что это связано с присущими BorderLayout свойствами, но я не уверен. Должен ли я использовать другой макет и какие изменения я бы сделал?

Я включил код, с которым я работаю ниже. Спасибо за любую помощь заранее!

import java.awt.datatransfer.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.io.*;

import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.text.*;
import java.util.*;
import java.nio.*;

public class ConsolidatorDemo extends JPanel implements ActionListener {
    JFileChooser fc;
    JButton clear;
    JButton ok;
    JTextArea console;

    JList<File> dropZone;
    DefaultListModel listModel;
    JSplitPane childSplitPane, parentSplitPane;
    PrintStream ps;

    JTextField wordCount;
    JLabel lblCount;

  public ConsolidatorDemo() {
    super(new BorderLayout());
    fc = new JFileChooser();;
    fc.setMultiSelectionEnabled(true);
    fc.setDragEnabled(true);
    fc.setControlButtonsAreShown(false);
    fc.setFileSelectionMode(JFileChooser.FILES_ONLY);


    JPanel fcPanel = new JPanel(new BorderLayout());
    fcPanel.add(fc, BorderLayout.CENTER);

    clear = new JButton("Clear All");
    clear.addActionListener(this);

    JPanel buttonPanel = new JPanel(new BorderLayout());
    buttonPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    buttonPanel.add(clear, BorderLayout.LINE_END);

    ok = new JButton("OK");
    ok.addActionListener(this);
    buttonPanel.add(ok, BorderLayout.WEST);

    JPanel sizePanel = new JPanel(new BorderLayout());
    sizePanel.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));

    wordCount = new JTextField();
    sizePanel.add(wordCount, BorderLayout.LINE_END);

//    lblCount = new JLabel("Word Counter");
//    buttonPanel.add(lblCount, BorderLayout.CENTER);

    JPanel leftUpperPanel = new JPanel(new BorderLayout());
    leftUpperPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    leftUpperPanel.add(fcPanel, BorderLayout.NORTH);
    leftUpperPanel.add(sizePanel, BorderLayout.CENTER);
    leftUpperPanel.add(buttonPanel, BorderLayout.PAGE_END);

    JScrollPane leftLowerPanel = new javax.swing.JScrollPane();
    leftLowerPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));

    listModel = new DefaultListModel();
    dropZone = new JList(listModel);
    dropZone.setCellRenderer(new FileCellRenderer());
    dropZone.setTransferHandler(new ListTransferHandler(dropZone));
    dropZone.setDragEnabled(true);
    dropZone.setDropMode(javax.swing.DropMode.INSERT);
    dropZone.setBorder(new TitledBorder("Selected files/folders"));
    leftLowerPanel.setViewportView(new JScrollPane(dropZone));

    childSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
            leftUpperPanel, leftLowerPanel);
    childSplitPane.setDividerLocation(400);
    childSplitPane.setPreferredSize(new Dimension(480, 650));

    console = new JTextArea();
    console.setColumns(40);
    console.setLineWrap(true);
    console.setBorder(new TitledBorder("Console"));

    parentSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                    childSplitPane, console);
    parentSplitPane.setDividerLocation(480);
    parentSplitPane.setPreferredSize(new Dimension(800, 650));

    add(parentSplitPane, BorderLayout.CENTER);

    this.redirectSystemStreams();

}
  private void updateTextArea(final String text) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        console.append(text);
      }
    });
  }

  private void redirectSystemStreams() {
    OutputStream out = new OutputStream() {
      @Override
      public void write(int b) throws IOException {
        updateTextArea(String.valueOf((char) b));
      }

      @Override
      public void write(byte[] b, int off, int len) throws IOException {
        updateTextArea(new String(b, off, len));
      }

      @Override
      public void write(byte[] b) throws IOException {
        write(b, 0, b.length);
      }
    };

    System.setOut(new PrintStream(out, true));
    System.setErr(new PrintStream(out, true));
  }


  public void setDefaultButton() {
    getRootPane().setDefaultButton(ok);
  }

public void actionPerformed(ActionEvent e) {
    if (e.getSource() == clear) {
        listModel.clear();
    }
    if(e.getSource() == ok){
     try{
      if(dropZone.isSelectionEmpty() == true){
       int start = 0;
       int end = dropZone.getModel().getSize() - 1;
       if (end >= 0) {
        dropZone.setSelectionInterval(start, end);
       }
      }
      List<File> list = dropZone.getSelectedValuesList(); 
      for (File file : list) {
       //StringEditing.editDocument(file, Integer.parseInt(wordCount.getText()));
      }
     }
     catch(NumberFormatException nfe){
       System.out.println("You did not input a number");
     }
     catch(Exception ef){
      System.out.println("Something is wrong!");
     }
    }
}


/**
 * Create the GUI and show it. For thread safety,
 * this method should be invoked from the
 * event-dispatching thread.
 */
private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    try {
      //UIManager.setLookAndFeel("de.javasoft.plaf.synthetica.SyntheticaBlackStarLookAndFeel");
        for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    }catch (Exception e){
      e.printStackTrace();
    }

    //Create and set up the window.
    JFrame frame = new JFrame("Consolidator!");
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    //Create and set up the menu bar and content pane.
    ConsolidatorDemo demo = new ConsolidatorDemo();
    demo.setOpaque(true); //content panes must be opaque
    frame.setContentPane(demo);

    //Display the window.
    frame.pack();
    frame.setVisible(true);
    demo.setDefaultButton();
}

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}
}

class FileCellRenderer extends DefaultListCellRenderer {

    public Component getListCellRendererComponent(JList list,
        Object value,
        int index,
        boolean isSelected,
        boolean cellHasFocus) {

        Component c = super.getListCellRendererComponent(
            list,value,index,isSelected,cellHasFocus);

        if (c instanceof JLabel && value instanceof File) {
            JLabel l = (JLabel)c;
            File f = (File)value;
            l.setIcon(FileSystemView.getFileSystemView().getSystemIcon(f));
            l.setText(f.getName());
            l.setToolTipText(f.getAbsolutePath());
        }

        return c;
    }
}

class ListTransferHandler extends TransferHandler {

    private JList list;

    ListTransferHandler(JList list) {
        this.list = list;
    }

    @Override
    public boolean canImport(TransferHandler.TransferSupport info) {
        // we only import FileList
        if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            return false;
        }
        return true;
    }

    @Override
    public boolean importData(TransferHandler.TransferSupport info) {
        if (!info.isDrop()) {
            return false;
        }

        // Check for FileList flavor
        if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            displayDropLocation("List doesn't accept a drop of this type.");
            return false;
        }

        // Get the fileList that is being dropped.
        Transferable t = info.getTransferable();
        List<File> data;
        try {
            data = (List<File>)t.getTransferData(DataFlavor.javaFileListFlavor);
        }
        catch (Exception e) { return false; }
        DefaultListModel model = (DefaultListModel) list.getModel();
        for (Object file : data) {
            model.addElement((File)file);
        }
        return true;
    }

    private void displayDropLocation(String string) {
        System.out.println(string);
    }
}

Я закончил использование GridBagLayout, используя различные ответы здесь, спасибо за вашу помощь!

В этом примере у меня есть тонна дополнительных/неиспользуемых материалов, главным образом потому, что я начал реализовывать функции, которые мне нужны, когда я решил, что опубликую здесь обновление. Тем не менее, он должен компилироваться и работать нормально.

Одна из проблем заключается в том, что графический интерфейс появляется с помощью кнопки панели/разделителя зоны сортировки пищи друг друга. Кроме того, есть текстовое поле, которое не имеет ширины, несмотря на то, что оно отлично работает, прежде чем я использую разделенные панели. Если бы кто-нибудь знал, как обойти эти ошибки, я был бы признателен!

import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.*;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import java.awt.datatransfer.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.io.*;

import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.text.*;
import java.util.*;
import java.nio.*;

public class TestGridBagLayout {
  final static boolean shouldFill = true;
  final static boolean shouldWeightX = true;
  final static boolean RIGHT_TO_LEFT = false;

  public static void addComponentsToPane(Container pane) {
    if (RIGHT_TO_LEFT) {
      pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
    }
    JButton clear;
    JButton ok;
    JLabel num;
    JTextField input;
    JSplitPane childSplitPane, parentSplitPane;
    PrintStream ps;
    JTextArea console;
    JList<File> dropZone;
    DefaultListModel listModel;

    pane.setLayout(new GridBagLayout());

    JPanel leftUpperPanel = new JPanel(new GridBagLayout());
    leftUpperPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    GridBagConstraints c = new GridBagConstraints();
    if (shouldFill) {
      //natural height, maximum width
      c.fill = GridBagConstraints.HORIZONTAL;
    }

    JFileChooser fc = new JFileChooser();;
    fc.setMultiSelectionEnabled(true);
    fc.setDragEnabled(true);
    fc.setControlButtonsAreShown(false);
    fc.setFileSelectionMode(JFileChooser.FILES_ONLY);

    c.fill = GridBagConstraints.HORIZONTAL;
    c.ipady = 40;      //make this component tall
    c.weightx = 0.0;
    c.gridwidth = 4;
    c.gridx = 0;
    c.gridy = 1;
    leftUpperPanel.add(fc, c);

    ok = new JButton("OK");
    c.fill = GridBagConstraints.HORIZONTAL;
    c.ipady = 0;       //reset to default
    c.anchor = GridBagConstraints.PAGE_END; //bottom of space
    c.insets = new Insets(10,0,0,0);  //top padding
    c.weightx = 0.5;
    c.gridx = 0;       //aligned with button 2
    c.gridwidth = 1;   
    c.gridy = 2;       //third row
    leftUpperPanel.add(ok, c);

    num = new JLabel("Word Count:");
    c.fill = GridBagConstraints.NONE;
    c.anchor = GridBagConstraints.PAGE_END;
    c.insets = new Insets(10,0,0,0);  //top padding
    c.weightx = 0.25;
    c.gridx = 1;
    c.gridy = 2;
    leftUpperPanel.add(num, c);

    input = new JTextField("", 50);
    c.fill = GridBagConstraints.HORIZONTAL;
    c.anchor = GridBagConstraints.PAGE_END;
    c.insets = new Insets(10,0,0,0);  //top padding
    c.weightx = 0.25;
    c.gridx = 2;
    c.gridy = 2;
    leftUpperPanel.add(input, c);

    clear = new JButton("Clear All");
    c.fill = GridBagConstraints.HORIZONTAL;
    c.ipady = 0;
    c.anchor = GridBagConstraints.PAGE_END;
    c.insets = new Insets(10,0,0,0);  //top padding
    c.weightx = 0.5;
    c.gridx = 3;
    c.gridy = 2;
    leftUpperPanel.add(clear, c);

    JScrollPane leftLowerPanel = new javax.swing.JScrollPane();
    leftLowerPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));

    listModel = new DefaultListModel();
    dropZone = new JList(listModel);
    dropZone.setCellRenderer(new FileCellRenderer());
    dropZone.setTransferHandler(new ListTransferHandler(dropZone));
    dropZone.setDragEnabled(true);
    dropZone.setDropMode(javax.swing.DropMode.INSERT);
    dropZone.setBorder(new TitledBorder("Selected files/folders"));
    leftLowerPanel.setViewportView(new JScrollPane(dropZone));

    childSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
            leftUpperPanel, leftLowerPanel);
    childSplitPane.setDividerLocation(400);
    childSplitPane.setPreferredSize(new Dimension(480, 650));

    console = new JTextArea();
    console.setColumns(40);
    console.setLineWrap(true);
    console.setBorder(new TitledBorder("Console"));

    parentSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                    childSplitPane, console);
    parentSplitPane.setDividerLocation(480);
    parentSplitPane.setPreferredSize(new Dimension(800, 650));

    pane.add(parentSplitPane);

  }

  public static void initUI() {

    JFrame frame = new JFrame("GridBagLayoutDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    addComponentsToPane(frame.getContentPane());

    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        TestGridBagLayout testMultiplePanels = new TestGridBagLayout();
        testMultiplePanels.initUI();

      }
    });
  }

}
  • 0
    Вы можете придерживаться простых менеджеров по расположению. Иногда вам нужно иметь несколько вложенных ... так что у вас есть панель с собственным макетом на одной из границ. Это может даже работать в динамическом контексте (изменение размера окна). Однако я думаю, что это помогает взглянуть на компоновку gridbag - или использовать один из этих полу-абсолютных новых макетов (диалог).
Теги:
swing
jframe
jbutton
border-layout

3 ответа

1

Для гибкости вы можете использовать JSplitPane с HORIZONTAL_SPLIT; поставить console справа и вложенной JSplitPane с VERTICAL_SPLIT fcPanel dropZone JSplitPane, имеющий VERTICAL_SPLIT слева, чтобы удерживать fcPanel и dropZone.

1

Я бы, вероятно, создал панель с BoxLayout с ориентацией оси y и поместил в нее две "половинки" и поместил ее в западном конце JFrame по умолчанию BoxLayout. Затем я положил бы другую панель в центр, предполагая, что вы хотите, чтобы она растягивалась и сжималась в обоих направлениях, когда пользователь меняет размер окна.

1

Вы можете начать с установки GridLayout для отображения двух столбцов и одной строки. Это началось бы в качестве основного дисплея/контейнера/панели для вертикального разделения. Вам понадобится еще один JPanel, возможно, с установкой GridLayout, чтобы отобразить один столбец и две строки, это отобразило бы выбор файла и зону сброса.

Затем вы добавите эту панель и текстовую область в основную панель.

Вы также можете сделать это, используя один GridBagLaout, но вы можете найти с помощью сложного GridLayout проще.

Узнайте, как использовать GridLayout и как использовать GridBagLayout для получения более подробной информации

Ещё вопросы

Сообщество Overcoder
Наверх
Меню