Как запрограммировать этот графический интерфейс в Java Swing

В настоящее время я разрабатываю небольшую утилиту со следующим графическим интерфейсом:

Пример графического интерфейса

Прямо сейчас у меня есть контейнер (JPanel) с макетом BorderLayout, который держит все на месте. У меня есть еще 2 панели JPanel, размещенные на BorderLayout.NORTH и BorderLayout.SOUTH соответственно, каждая с GridLayout (2 столбца на 1 строку). Стол находится на основном контейнере, расположенном в ЦЕНТРЕ его.

Как вы думаете, это лучший подход? У меня тяжелые времена, связанные с расстоянием между компонентами и границами кадра.

Прямо сейчас у меня есть этот код:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.SwingUtilities;

public class GUI extends JFrame {

    private JButton loadFileBtn = new JButton("Load File");
    private JButton generateReportBtn = new JButton("Generate Report");
    private JButton exitBtn = new JButton("Exit");
    private JLabel fileNameLbl = new JLabel("File Name Here");
    private JMenuBar menuBar = new JMenuBar();
    private JMenu fileMI = new JMenu("File");
    private JMenuItem openFileMenu = new JMenuItem("Open File");
    private JSeparator separator = new JSeparator();
    private JMenuItem exitMenu = new JMenuItem("Exit");
    private JMenu reportMI = new JMenu("Report");
    private JMenuItem generateReportMenu = new JMenuItem("Generate Report");
    private JMenu helpMI = new JMenu("Help");
    private JMenuItem aboutMenu = new JMenuItem("About");
    private JTable table = new JTable(5, 2);
    private JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
    private JPanel panel1 = new JPanel(new BorderLayout());
    private JPanel panel2 = new JPanel(new GridLayout(1, 2));
    private JPanel panel3 = new JPanel(new GridLayout(1, 2));

    public GUI() {

        super("Sample GUI");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(new Dimension(300, 300));
        setResizable(false);

        setLayout(new BorderLayout(10, 10));

        fileMI.add(openFileMenu);
        fileMI.add(separator);
        fileMI.add(exitMenu);

        reportMI.add(generateReportMenu);

        helpMI.add(aboutMenu);

        menuBar.add(fileMI);
        menuBar.add(reportMI);
        menuBar.add(helpMI);

        setJMenuBar(menuBar);

        panel1.add(table, BorderLayout.CENTER);

        panel2.add(fileNameLbl);
        panel2.add(loadFileBtn);

        panel3.add(generateReportBtn);
        panel3.add(exitBtn);

        mainPanel.add(panel2, BorderLayout.NORTH);
        mainPanel.add(panel1, BorderLayout.CENTER);
        mainPanel.add(panel3, BorderLayout.SOUTH);

        add(mainPanel);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GUI app = new GUI();
                app.setVisible(true);
            }
        });
    }
}

Как вы думаете, что было бы лучшим подходом для этого?

Любая помощь будет оценена по достоинству. Спасибо.


ОБНОВЛЕНИЕ:

Прямо сейчас у меня есть следующий графический интерфейс

введите здесь описание изображения

Я хочу, чтобы компоненты равномерно отстояли от границ, как в макете.


person DaveQuinn    schedule 12.03.2013    source источник
comment
В чем именно ваша проблема? Какое пространство вы хотели бы представить и вызывает проблемы? Вы всегда можете использовать BorderFactory.createEmptyBorder(int, int, int, int)   -  person Guillaume Polet    schedule 12.03.2013
comment
@Guillaume Polet не уверен, пожалуйста, не нападайте, вы имеете в виду, использовать EmptyBorder, чтобы избежать setPreferredSize, или использовать EmptyBorder, чтобы избежать SpringLayout с GridBagLayout в форме NestedLayout, MigLayout или ...   -  person mKorbel    schedule 12.03.2013
comment
@mKorbel Пустые границы - это очень простое (а иногда и элегантное) решение для правильного позиционирования компонентов в их контейнере без необходимости переключения на другой LayoutManager. Если OP чувствует себя комфортно с этими LayoutManager, пустые границы могут быть хорошим решением его реальных проблем.   -  person Guillaume Polet    schedule 12.03.2013


Ответы (4)


2 вещи, которые вы можете использовать, чтобы это произошло:

  1. Используйте 1_
  2. Используйте конструктор с 4 аргументами GridLayout

Существуют и другие LayoutManager, которые могут обеспечить ту же функциональность (например, GridBagLayout или использование вложенных BorderLayout), но если вы чувствуете себя комфортно с текущими LayoutManager, нет необходимости переходить на них. То, как вы это сделали, тоже приемлемо.

введите здесь описание изображения

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

Небольшой пример кода:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.SwingUtilities;

public class GUI extends JFrame {

    private JButton loadFileBtn = new JButton("Load File");
    private JButton generateReportBtn = new JButton("Generate Report");
    private JButton exitBtn = new JButton("Exit");
    private JLabel fileNameLbl = new JLabel("File Name Here");
    private JMenuBar menuBar = new JMenuBar();
    private JMenu fileMI = new JMenu("File");
    private JMenuItem openFileMenu = new JMenuItem("Open File");
    private JSeparator separator = new JSeparator();
    private JMenuItem exitMenu = new JMenuItem("Exit");
    private JMenu reportMI = new JMenu("Report");
    private JMenuItem generateReportMenu = new JMenuItem("Generate Report");
    private JMenu helpMI = new JMenu("Help");
    private JMenuItem aboutMenu = new JMenuItem("About");
    private JTable table = new JTable(5, 2);
    private JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
    private JPanel panel1 = new JPanel(new BorderLayout());
    private JPanel panel2 = new JPanel(new GridLayout(1, 2, 10, 10));
    private JPanel panel3 = new JPanel(new GridLayout(1, 2, 10, 10));

    public GUI() {

        super("Sample GUI");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(new Dimension(300, 300));
        setResizable(false);

        setLayout(new BorderLayout(10, 10));

        fileMI.add(openFileMenu);
        fileMI.add(separator);
        fileMI.add(exitMenu);

        reportMI.add(generateReportMenu);

        helpMI.add(aboutMenu);

        menuBar.add(fileMI);
        menuBar.add(reportMI);
        menuBar.add(helpMI);

        setJMenuBar(menuBar);

        panel1.add(table, BorderLayout.CENTER);

        panel2.add(fileNameLbl);
        panel2.add(loadFileBtn);

        panel3.add(generateReportBtn);
        panel3.add(exitBtn);

        mainPanel.add(panel2, BorderLayout.NORTH);
        mainPanel.add(panel1, BorderLayout.CENTER);
        mainPanel.add(panel3, BorderLayout.SOUTH);
        mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        add(mainPanel);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GUI app = new GUI();
                app.setVisible(true);
            }
        });
    }
}
person Guillaume Polet    schedule 12.03.2013
comment
Это именно то, что я хотел. Спасибо @Guillaume Polet. Я также пробовал GridBagLayout, но я не могу понять концепцию. Какие хорошие учебники вы бы порекомендовали? На веб-странице orcles не все так просто для новичка. - person DaveQuinn; 12.03.2013
comment
хмммм, вы знаете, что пустые панели JPanel добавлены в области W, E, S, N в JFrame для автоматического создания этого промежутка, нет причин добавлять EmptyBorders для этой идеи :-) - person mKorbel; 12.03.2013
comment
@mKorbel Вы предлагаете добавить пустой JPanel с принудительно предпочтительным размером к западу, востоку, северу и югу от JFrame? - person Guillaume Polet; 12.03.2013
comment
Как предложил @Gilbert Le Blanc, использование FlowLayout вместо GridLayout должно быть гораздо более гибким и позволить мне создать зазор между меткой и кнопкой на севере и двумя кнопками на юге. Каково ваше мнение? - person DaveQuinn; 12.03.2013
comment
@PMMP Зависит от того, чего вы пытаетесь достичь. Если вы хотите, чтобы кнопки были одинакового размера, GridLayout — это то, что вам нужно. Если теперь вы предпочитаете, чтобы каждая кнопка имела свой собственный размер и была каким-то образом выровнена, FlowLayout или BoxLayout являются лучшими кандидатами. Нет правильных или неправильных LayoutManager, есть только подходящие для данных потребностей/желаний. - person Guillaume Polet; 12.03.2013
comment
@Guillaume Polet этот зазор автоматически создается в контейнере верхнего уровня, BorderLayout, пустой JPanel, не требуется никакого размера, делается с помощью BorderLayout - person mKorbel; 12.03.2013
comment
@mKorbel Хорошо, теперь я понимаю, что ты имеешь в виду. Если я добавлю пустые JPanels, hGap и vGap BorderLayout вступят в действие и автоматически заставят пустую границу появиться. Лично я все же предпочитаю явную пустую рамку, созданную именно для достижения описанного эффекта. О цветах и ​​вкусах всегда можно поспорить.... ;-) - person Guillaume Polet; 12.03.2013

В прошлом я обнаружил, что использование MigLayout решает все мои проблемы

person epoch    schedule 12.03.2013
comment
Да, MigLayout почти всегда мой путь. Довольно прост в освоении и очень прост в использовании. - person wchargin; 12.03.2013
comment
Не знал этого. Такс, проверим. - person DaveQuinn; 12.03.2013

Вот как я бы устроил ваш графический интерфейс. Это всего лишь один из способов. Это не единственный способ.

  • JTable входит в JScrollPane.

  • Button2 и Button3 идут внутри кнопки JPanel с FlowLayout.

  • Label и Button1 идут внутри метки JPanel с FlowLayout.

  • Файл, отчет и справка — это JMenuItems на JMenuBar.

  • Главный JPanel имеет BoxLayout с ориентацией Y_AXIS.

  • Добавьте метку JPanel, JScrollPane и кнопку JPanel на главную JPanel.

person Gilbert Le Blanc    schedule 12.03.2013
comment
Попробую @Gilbert Le Blanc. Спасибо за ваш вклад. Очень признателен. - person DaveQuinn; 12.03.2013

Лучший способ создать графический интерфейс — написать код таким образом, чтобы его поняли и вы, и другие. Взгляните на это Руководство по менеджерам компоновки. Вы можете использовать разные менеджеры компоновки для разных компонентов. Это поможет вам установить правильный интервал.

Если ваша проблема заключается только в расстоянии между компонентами, установите его Вставки.

person Jean Waghetti    schedule 12.03.2013
comment
Какие менеджеры макетов вы рекомендуете для этого дизайна? Это мотивация моего вопроса. - person DaveQuinn; 12.03.2013
comment
GridBagLayout, на мой взгляд, самый гибкий. Но, возможно, я бы смешал некоторые менеджеры компоновки. Поместите панель сверху и снизу, а таблицу посередине с помощью BorderLayout. Панели внизу я бы использовал FlowLayout, а панель вверху, возможно, FlowLayout или GridBagLayout. Или делайте все с помощью GridBagLayout (много кода). - person Jean Waghetti; 12.03.2013