手动编写的GUI - Java

4
我正在尝试使用Swing和AWT手动编写Java GUI。我正在使用各种布局来尝试实现或类似于下面发布的GUI(这是使用铅笔制作的模拟布局): Mock Layout - (Made with Pencil) 目前为止,我得到了这个,但似乎无法使其尽可能更“礼貌”,吸引人和用户友好。 Java GUI try 这是我迄今为止所做的代码:
import java.awt.*; 
import javax.swing.*;
import javax.swing.JTable;


public class GUI extends JFrame {

    public void buildGui() {

        JFrame frame = new JFrame("Hotel TV Scheduler");

                JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout(0,0));

                JPanel chPanel = new JPanel();
                chPanel.setLayout(new GridLayout(3,2));

                JPanel listPanel = new JPanel();
                listPanel.setLayout(new GridLayout(3,2));

                JPanel infoPanel = new JPanel();
        infoPanel.setLayout(new GridLayout(0,2));


                JPanel addPanel = new JPanel();
        addPanel.setLayout(new GridLayout(0,3));


                mainPanel.add(chPanel, BorderLayout.LINE_START);
                mainPanel.add(listPanel, BorderLayout.CENTER);
                mainPanel.add(infoPanel, BorderLayout.LINE_END);


                JTable chOneTable = new JTable();
                JTable chTwoTable = new JTable();
                JTable listTable = new JTable();

                JLabel ch1Label = new JLabel("Channel 1");
                JLabel ch2Label = new JLabel("Channel 2");
                JLabel listLabel = new JLabel("List");

                JButton rmvChOneButton = new JButton("Remove Channel");
                JButton rmvChTwoButton = new JButton("Remove Channel");

                chPanel.add(ch1Label);
                chPanel.add(ch2Label);
                chPanel.add(chOneTable);
                 chPanel.add(chTwoTable);
                chPanel.add(rmvChOneButton);                                         
                chPanel.add(rmvChTwoButton);

                listPanel.add(listLabel);
                listPanel.add(listTable);                



                JLabel titleLabel = new JLabel("Title");
                JLabel genreLabel = new JLabel("Genre");
                JLabel durationLabel = new JLabel("Duration");
                JLabel actorLabel = new JLabel("Actor");
                JLabel directorLabel = new JLabel("Director");
                JLabel rentableLabel = new JLabel("Rentable");
                JLabel synLabel = new JLabel("Synopsis");

                JTextField txtTitle = new JTextField();          
                JTextField txtGenre = new JTextField();
                JTextField txtDuration = new JTextField();
                JTextField txtActor = new JTextField();
                JTextField txtDirector = new JTextField();
                JTextField txtSynopsis = new JTextField();

                JCheckBox rentCB = new JCheckBox();

                JButton btnAddProg = new JButton("Add Program");

                JList channelList = new JList();
                JList timeList = new JList();

                infoPanel.add(titleLabel);
                infoPanel.add(txtTitle);
                infoPanel.add(genreLabel);
                infoPanel.add(txtGenre);
                infoPanel.add(durationLabel);
                infoPanel.add(txtDuration);
                infoPanel.add(actorLabel);
                infoPanel.add(txtActor);
                infoPanel.add(directorLabel);
                infoPanel.add(txtDirector);
                infoPanel.add(rentableLabel);
                infoPanel.add(rentCB);
                infoPanel.add(synLabel);
                infoPanel.add(txtSynopsis);
                infoPanel.add(btnAddProg);
                infoPanel.add(channelList);
                infoPanel.add(timeList);


                frame.add(mainPanel);
                frame.setVisible(true);


    }


}

不一定要完全按照上面展示的模拟布局,但尽可能相似或至少更加用户友好。

我想使用除了GridBagLayout和SwingLayout之外的任何东西。

有什么想法可以改进代码并使其看起来更相似吗?

非常感谢您的帮助!

Brian


学习GridBagLayout。这真的会对这里的事情有所帮助。我知道它很难,但是要咬紧牙关。 - Starkey
其实这是一项学校作业,我们被要求不使用它的简单原因是您可以找到使用GridBagLayout的GUI创建器。 - Brian
叹气...我的建议是,尽可能嵌套布局以获得您想要的结果。 - Starkey
祝你好运。如果它应该是可调整大小的,那将会非常困难。如果不是,那么您可以尝试使用FlowLayout完全构建它,以便您可以告诉组件它们应该有多大。当然,您不必使用任何LayoutManager。您可以使用setBounds()排列每个部分,但这并不好玩。我现在没有时间,但也许以后我会做一些关于FlowLayouts的事情。 - mmaag
4个回答

2
请看一下MigLayout。它的许可非常包容:

MigLayout可用于商业和非商业项目,并提供源代码。 它根据您喜欢的BSD或GPL许可证进行许可

JNLP演示应用程序应该展示了很好的示例及其相应的源代码。
此外,请尽量避免嵌套逻辑无关的组件。 随着嵌套程度的增加,对齐、边框和填充变得非常困难。

2

GUI界面主要需要的是:

  • 组件之间的空白间隔。提供这种空白间隔的两种常见方法是:
    1. 在布局的构造函数中提供布局填充。
    2. 为组件或容器添加EmptyBorder。对于已经有边框的许多组件,最好将它们包装在一个JPanel中,并将边框添加到面板中。
  • 约束面板。例如,如果希望将位于BorderLayout的“WEST”位置的一组组件“推向顶部”,则将它们添加到具有BorderLayout.NORTH布局/约束的另一个面板中。 这里是一个示例


@mKorbel,我仍然在想所有“真正的LayoutManager大师”都躲在哪里。 ;) - Andrew Thompson

1

看一下这个示例程序,它能满足你的需求吗 :-)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;

public class TVSchedule
{
    private static final int GAP = 5;
    private static TVSchedule tvSchedule;

    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("HOTEL TV SCHEDULE");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLocationByPlatform(true);

        JPanel contentPane = new JPanel();
        contentPane.setLayout(new BorderLayout());

        JPanel centerPanel = new JPanel();
        //centerPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
        centerPanel.setLayout(new GridLayout(0, 4, 5, 5));
        centerPanel.add(createChannelOnePanel());
        centerPanel.add(createChannelTwoPanel());
        centerPanel.add(createListPanel());
        centerPanel.add(createInformationPanel());

        JPanel bottomPanel = new JPanel();
        bottomPanel.setOpaque(true);
        bottomPanel.setBackground(Color.RED.darker());
        bottomPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
        JButton exitButton = new JButton("EXIT");
        bottomPanel.add(exitButton);

        contentPane.add(centerPanel, BorderLayout.CENTER);
        contentPane.add(bottomPanel, BorderLayout.PAGE_END);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setVisible(true);
    }

    private JPanel createChannelOnePanel()
    {
        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());
        panel.setOpaque(true);
        panel.setBackground(Color.DARK_GRAY);
        panel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        GridBagConstraints gbc = new GridBagConstraints();

        String[] columnNames = {
                                    "Time",
                                    "Title"
                               }; 
        Object[][] data = {
                            {"01:00","Cowboy and Alchemist."}
                          };
        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        JTable table = new JTable( model )
        {
            //  Returning the Class of each column will allow different
            //  renderers to be used based on Class
            public Class getColumnClass(int column)
            {
                return getValueAt(0, column).getClass();
            }
        };                      

        table.setPreferredScrollableViewportSize(new Dimension(200, 200));
        table.setFillsViewportHeight(true);
        JScrollPane scrollPane = new JScrollPane(table);
        scrollPane.setBorder(BorderFactory.createTitledBorder(
                        BorderFactory.createLineBorder(Color.BLACK, 1)
                        , "Channel 1"
                        , TitledBorder.CENTER
                        , TitledBorder.DEFAULT_POSITION));      
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        panel.add(scrollPane, gbc);     

        JButton removeButton = new JButton("Remove Selected");
        gbc.weightx = 1.0;
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.gridwidth = 2;
        panel.add(removeButton, gbc);

        return panel;
    }

    private JPanel createChannelTwoPanel()
    {
        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());
        panel.setOpaque(true);
        panel.setBackground(Color.WHITE);
        panel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        GridBagConstraints gbc = new GridBagConstraints();

        String[] columnNames = {
                                    "Time",
                                    "Title"
                               }; 
        Object[][] data = {
                            {"02:00","Grey's Anatomy"}
                          };
        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        JTable table = new JTable( model )
        {
            //  Returning the Class of each column will allow different
            //  renderers to be used based on Class
            public Class getColumnClass(int column)
            {
                return getValueAt(0, column).getClass();
            }
        };                      

        table.setPreferredScrollableViewportSize(new Dimension(200, 200));
        table.setFillsViewportHeight(true);
        JScrollPane scrollPane = new JScrollPane(table);
        scrollPane.setBorder(BorderFactory.createTitledBorder(
                        BorderFactory.createLineBorder(Color.BLACK, 1)
                        , "Channel 2"
                        , TitledBorder.CENTER
                        , TitledBorder.DEFAULT_POSITION));      
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        panel.add(scrollPane, gbc);     

        JButton removeButton = new JButton("Remove Selected");
        gbc.weightx = 1.0;
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.gridwidth = 2;
        panel.add(removeButton, gbc);

        return panel;
    }

    private JPanel createListPanel()
    {       
        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());
        panel.setOpaque(true);
        panel.setBackground(Color.DARK_GRAY);
        panel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        GridBagConstraints gbc = new GridBagConstraints();

        String[] columnNames = {
                                    "Genre",
                                    "Title",
                                    "Duration (Hours)"
                               }; 
        Object[][] data = {
                            {"Comedy","C & A", "1.5"}
                          };
        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        JTable table = new JTable( model )
        {
            //  Returning the Class of each column will allow different
            //  renderers to be used based on Class
            public Class getColumnClass(int column)
            {
                return getValueAt(0, column).getClass();
            }
        };                      

        table.setPreferredScrollableViewportSize(new Dimension(200, 200));
        table.setFillsViewportHeight(true);
        JScrollPane scrollPane = new JScrollPane(table);
        scrollPane.setBorder(BorderFactory.createTitledBorder(
                        BorderFactory.createLineBorder(Color.BLACK, 1)
                        , "List"
                        , TitledBorder.CENTER
                        , TitledBorder.DEFAULT_POSITION));
        gbc.weightx = 1.0;
        gbc.anchor = GridBagConstraints.PAGE_START;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        panel.add(scrollPane, gbc); 

        gbc.weightx = 1.0;
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.gridwidth = 2;
        panel.add(Box.createRigidArea(new Dimension(100, 30)), gbc);    

        return panel;
    }

    private JPanel createInformationPanel()
    {
        JPanel bottomPanel = new JPanel();
        bottomPanel.setLayout(new GridLayout(0, 1, 2, 2));
        bottomPanel.setBorder(BorderFactory.createTitledBorder(
                        BorderFactory.createLineBorder(Color.BLACK, 1)
                        , "Information"
                        , TitledBorder.LEFT
                        , TitledBorder.DEFAULT_POSITION));

        JPanel panel = new JPanel();
        panel.setOpaque(true);
        panel.setBackground(Color.WHITE);
        panel.setLayout(new GridBagLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        GridBagConstraints gbc = new GridBagConstraints();

        JLabel titleLabel = new JLabel("TITLE : ");
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 0;
        panel.add(titleLabel, gbc);

        JTextField titleField = new JTextField(10);
        gbc.gridx = 1;
        panel.add(titleField, gbc);

        JLabel genreLabel = new JLabel("GENRE : ");
        gbc.gridx = 0;
        gbc.gridy = 1;
        panel.add(genreLabel, gbc);

        JTextField genreField = new JTextField(10);
        gbc.gridx = 1;
        panel.add(genreField, gbc);

        JLabel durationLabel = new JLabel("DURATION : ");
        gbc.gridx = 0;
        gbc.gridy = 2;
        panel.add(durationLabel, gbc);

        JTextField durationField = new JTextField(10);
        gbc.gridx = 1;
        panel.add(durationField, gbc);

        JLabel actorLabel = new JLabel("ACTOR : ");
        gbc.gridx = 0;
        gbc.gridy = 3;
        panel.add(actorLabel, gbc);

        JTextField actorField = new JTextField(10);
        gbc.gridx = 1;
        panel.add(actorField, gbc);

        JLabel directorLabel = new JLabel("DIRECTOR : ");
        gbc.gridx = 0;
        gbc.gridy = 4;
        panel.add(directorLabel, gbc);

        JTextField directorField = new JTextField(10);
        gbc.gridx = 1;
        panel.add(directorField, gbc);

        JLabel rentLabel = new JLabel("RENTABLE : ");
        gbc.gridx = 0;
        gbc.gridy = 5;
        panel.add(rentLabel, gbc);

        JCheckBox rentCBox = new JCheckBox(" ", false);
        rentCBox.setOpaque(true);
        rentCBox.setBackground(Color.WHITE);
        rentCBox.setHorizontalTextPosition(SwingConstants.LEFT);
        gbc.gridx = 1;
        panel.add(rentCBox, gbc);

        JLabel synopsisLabel = new JLabel("SYNOPSIS : ");
        gbc.gridx = 0;
        gbc.gridy = 6;
        panel.add(synopsisLabel, gbc);

        JTextArea synopsisArea = new JTextArea(10, 5);
        synopsisArea.setBackground(Color.BLUE.darker());
        synopsisArea.setForeground(Color.WHITE);
        synopsisArea.setCaretColor(Color.WHITE);
        gbc.gridx = 1;
        gbc.gridwidth = 2;
        gbc.gridheight = 2;
        panel.add(synopsisArea, gbc);

        JButton addProgramButton = new JButton("Add Program");
        gbc.gridx = 0;
        gbc.gridy = 8;
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.anchor = GridBagConstraints.PAGE_END;
        gbc.gridwidth = 1;
        gbc.gridheight = 1;
        panel.add(addProgramButton, gbc);

        JSpinner spinner = new JSpinner(new SpinnerNumberModel(00.15, 00.15, 60.00, 00.15));
        gbc.gridx = 2;
        gbc.gridy = 8;      
        panel.add(spinner, gbc);

        bottomPanel.add(panel);
        return bottomPanel;
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                tvSchedule = new TVSchedule();
                tvSchedule.createAndDisplayGUI();
            }
        });
    }
}

我真的不知道你在JButton和'JSpinner'之间使用了什么,所以从来没有添加任何东西,希望你能自己完成。

这是相同代码的输出:

HOTEL TV SCHEDULE


1

使用Eclipse和WindowBuilder。您可以稍后返回并“手动编写”特定部分,如果需要仍然可以返回到WindowBuilder。


Netbeans曾经有一个非常不错的GUI构建器(不确定它是否仍然存在)。Intellij IDEA也有一个,但我认为它只适用于付费版本。 - mbatchkarov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接