在BorderLayout面板中堆叠FlowLayout面板会导致除SOUTH面板以外的所有面板消失吗?

时间:2013-05-16 23:09:47

标签: java swing

我有一个应用程序,我试图在FlowLayout面板中简单地将两个BorderLayout面板堆叠在一起。但是,当我这样做时,两个面板都不可见。

在我尝试堆叠这些面板之前,表单看起来像这样:

Before Stacking

但堆叠后它们看起来像这样:

After Stacking

使用SSCCE时,导致问题的一行是:

pane.add(textAreaPanel, BorderLayout.CENTER);

所以如果你评论那条线,表格至少会显示第一个面板。

SSCCE

TutoringCalculator

package tutoringcalculator;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.*;
import javax.swing.*;

public class TutoringCalculator extends JFrame {
    FlowLayout layout = new FlowLayout(FlowLayout.LEFT);

    public TutoringCalculator(String name) {
        super(name);
    }

    public void addComponentsToPane(final Container pane) {
        final JPanel contentPanel = new JPanel();
        contentPanel.setLayout(layout);
        final JPanel textAreaPanel = new JPanel();
        textAreaPanel.setLayout(layout);
        final JPanel buttons = new JPanel();
        buttons.setLayout(new FlowLayout(FlowLayout.RIGHT));

        contentPanel.add(new JLabel("Session Minutes:"));

        JTextField txt = new JTextField(10);
        txt.setName("sessionMinutes");

        txt.addFocusListener(new DecimalFieldFocusListener(new IValidDecimalValue() {
            @Override
            public boolean callback(String val) {
                return ApplicationState.getInstance().setCurrentSessionMinutes(val);
            }
        }));
        contentPanel.add(txt);

        // setup the default border
        ApplicationState.getInstance().setDefaultTextFieldBorder(txt.getBorder());

        contentPanel.add(new JLabel("Earnings:"));

        txt = new JTextField(10);
        txt.setName("earnings");

        txt.addFocusListener(new DecimalFieldFocusListener(new IValidDecimalValue() {
            @Override
            public boolean callback(String val) {
                return ApplicationState.getInstance().setCurrentEarnings(val);
            }
        }));
        contentPanel.add(txt);

        JButton btn = new JButton("Enter");
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String result = ApplicationState.getInstance().acceptEarnings();
                if (result != null) {
                    JOptionPane.showMessageDialog(null, result, "Error Entering Earnings", JOptionPane.ERROR_MESSAGE);
                }
                else {
                    JOptionPane.showMessageDialog(null, "The session minutes and earnings were accepted.", "Success!", JOptionPane.INFORMATION_MESSAGE);

                    JTextField sessionMinutes = (JTextField)contentPanel.getComponent(1);
                    sessionMinutes.setText("");

                    JTextField earnings = (JTextField)contentPanel.getComponent(3);
                    earnings.setText("");

                    sessionMinutes.requestFocus();
                }
            }
        });
        contentPanel.add(btn);

        JTextArea textArea = new JTextArea();
        textAreaPanel.add(textArea);

        btn = new JButton("Run Report");
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
            }
        });
        buttons.add(btn);

        btn = new JButton("Quit");
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        buttons.add(btn);

        pane.add(contentPanel, BorderLayout.CENTER);
        pane.add(textAreaPanel, BorderLayout.CENTER);
        pane.add(buttons, BorderLayout.SOUTH);
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event dispatch thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        TutoringCalculator frame = new TutoringCalculator("Tutoring Calculator");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        //Set up the content pane.
        frame.addComponentsToPane(frame.getContentPane());
        //Display the window.
        frame.setPreferredSize(new Dimension(600, 400));
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        /* Use an appropriate Look and Feel */
        try {
            //UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
        } catch (UnsupportedLookAndFeelException | IllegalAccessException | InstantiationException | ClassNotFoundException ex) {
            ex.printStackTrace();
        }
        /* Turn off metal's use of bold fonts */
        UIManager.put("swing.boldMetal", Boolean.FALSE);
        //Schedule a job for the event dispatchi thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

ApplicationState

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tutoringcalculator;

import javax.swing.border.Border;

/**
 *
 * @author Owner
 */
final public class ApplicationState {
    private static ApplicationState instance = new ApplicationState();
    public static ApplicationState getInstance() {
        return instance;
    }

    private ApplicationState() {

    }

    private Border defaultTextFieldBorder;
    public Border getDefaultTextFieldBorder() {
        return defaultTextFieldBorder;
    }
    public void setDefaultTextFieldBorder(Border b) {
        defaultTextFieldBorder = b;
    }

    private double currentSessionMinutes;
    private boolean isValidSessionMinutes;
    public boolean setCurrentSessionMinutes(String text) {
        isValidSessionMinutes = false;
        try {
            currentSessionMinutes = Double.parseDouble(text);
            isValidSessionMinutes = true;
        }
        catch (NumberFormatException nfe) {
            return false;
        }

        return true;
    }

    private double currentEarnings;
    private boolean isValidCurrentEarnings;
    public boolean setCurrentEarnings(String text) {
        isValidCurrentEarnings = false;
        try {
            currentEarnings = Double.parseDouble(text);
            isValidCurrentEarnings = true;
        }
        catch (NumberFormatException nfe) {
            return false;
        }

        return true;
    }

    public String acceptEarnings() {
        if (!(isValidSessionMinutes && isValidCurrentEarnings)) {
            return "Please enter valid session minutes and current earnings.";
        }

        addEarnings(currentSessionMinutes, currentEarnings);

        return null;
    }

    private double[][] earningsArray = new double[100][2];
    private int newRowIndex = 0;
    private void addEarnings(double sessionMinutes, double earnings) {
        earningsArray[newRowIndex][0] = sessionMinutes;
        earningsArray[newRowIndex][1] = earnings;
        newRowIndex++;
    }
}

DecimalFieldFocusListener

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tutoringcalculator;

import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.BorderFactory;
import javax.swing.JTextField;

/**
 *
 * @author Owner
 */
public class DecimalFieldFocusListener implements FocusListener {
    private IValidDecimalValue _callback;

    public DecimalFieldFocusListener(IValidDecimalValue callback) {
        _callback = callback;
    }

    public void focusGained(FocusEvent e) {
    }

    public void focusLost(FocusEvent e) {
        JTextField txt = (JTextField)e.getSource();
        if (!_callback.callback(txt.getText())) {
            txt.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.red));
        }
        else {
            txt.setBorder(ApplicationState.getInstance().getDefaultTextFieldBorder());
            txt.setBackground(Color.white);
        }
    }
}

IValidDecimalValue

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tutoringcalculator;

/**
 *
 * @author Owner
 */
public interface IValidDecimalValue {
    boolean callback(String val);
}

2 个答案:

答案 0 :(得分:4)

只有一个组件可以显示在BorderLayout.CENTER位置。因此

pane.add(contentPanel, BorderLayout.CENTER);
pane.add(textAreaPanel, BorderLayout.CENTER);

被调用,textAreaPanel有效取代contentPanel。相反,您可以将contentPanel放在NORTH位置:

pane.add(contentPanel, BorderLayout.NORTH);

答案 1 :(得分:2)

每个位置只能有一个组件。当您在BorderLayout.CENTER放置两个面板时,就像将一个面板放在另一个面板上。如果要将组件堆叠在一起,可以使用BorderLayout Manager。它允许组件沿容器的X轴或Y轴堆叠。你可以这样实现它:

pane.setLayout(new BoxLayout(pane,BoxLayout.Y_AXIS));
        pane.add(contentPanel);
        pane.add(textAreaPanel);
        pane.add(buttons);