切换jpanels对角线移动内容



我有btnshowlibrary,其中显示了保存在库中的书。然后,我有一个按钮btnretrurn,它在其中重新创建了以前的jpanel,其中包括btnshowlibrary。

初始化contentpane:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new MigLayout("", "[124px,grow,fill][124px,grow,fill][124px,grow,fill]", "[30px,grow,fill][30px,grow,fill][30px,grow,fill][30px,grow,fill][30px,grow,fill][30px,grow,fill][30px,grow,fill]"));

btnshowlibrary:

JButton btnShowLibrary = new JButton("Show Library");
btnShowLibrary.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        contentPane.removeAll();
        contentPane.add(new ShowLibrary().getPane());
        contentPane.updateUI();
    }
});
contentPane.add(btnShowLibrary, "cell 1 5");

showlibrary contentpane:

contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new MigLayout("", "[grow]", "[grow,fill][grow][]"));

btnreturn:

Button btnReturn = new JButton("Return");
btnReturn.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        contentPane.removeAll();
        contentPane.add(new Library().getPane());
        contentPane.updateUI();
    }
});
contentPane.add(btnReturn, "cell 0 1,alignx center,aligny bottom");

现在发生的事情:

初始化

首先单击btnshowlibrary

首先单击btnreturn

第二个点击BSL

第二个点击BR

第三单击BSL

第三单击br

从图片中您可以如何"移动",我不知道为什么。有人可以解释为什么会发生这种情况并建议如何修复它?

管理多个面板的一种简单方法是使用CardLayout布局。这种布局使您可以一次显示许多面板之一,从而轻松从一个窗口中的一个移动到另一个面板。这是一个演示,其中一些事件在GUI面板和主要的"控制器"之间传递。理想情况下,GUI类将在自己的文件中。另请参见https://docs.oracle.com/javase/tutorial/uiswing/layout/card.html。

package Q47644243;
import java.awt.AWTEvent;
import java.awt.CardLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GraphicsConfiguration;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
/**
 * Demonstrate multiple panels in a window using CardLayout
 *
 */
@SuppressWarnings("serial")
public class MultiplePanels extends JFrame implements VetoableChangeListener {
    public static void main(String[] args) {        
        new MultiplePanels();
    }
    // GUI components
    private MainMenuPanel mainMenuPanel = null;
    private DataEntryPanel dataEntryPanel = null;
    private JPanel contentPanel;
    private CardLayout cardLayout = new CardLayout();
    final static String MENUPANEL = "Main Menu";
    final static String DATAPANEL = "Enter Data";
    // State variables
    private int m_data = 0;
    public MultiplePanels() {
        try {
            // Initialize
            jbInit();
        } catch(Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
        try {
            setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            showCenterScreen(this);
            setCursor(Cursor.getDefaultCursor());
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }   
    }
    private void jbInit() {
        enableEvents(AWTEvent.WINDOW_EVENT_MASK);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // Create the GUI panels
        mainMenuPanel = new MainMenuPanel();
        dataEntryPanel = new DataEntryPanel();
        // Use property changes to communicate with the GUI
        addPropertyChangeListener(DataEntryPanel.PROPERTY_Data, dataEntryPanel);
        // Use vetoable changes to listen to the GUI
        mainMenuPanel.addVetoableChangeListener(this);
        dataEntryPanel.addVetoableChangeListener(this);
        this.setTitle("Multiple Panes Example");    
        cardLayout.setHgap(5);
        cardLayout.setVgap(5);
        // Add the panels
        contentPanel = (JPanel) this.getContentPane();
        contentPanel.setLayout(cardLayout);
        contentPanel.add(mainMenuPanel, MENUPANEL);
        contentPanel.add(dataEntryPanel, DATAPANEL);
        // Bring the menu to the front
        cardLayout.show(contentPanel, MENUPANEL);       
    }
    /**
     * Receive events from the GUI and process them. There are two expected:<br>
     * <ol>
     * <li>a change to the total seconds field. This is validated and accepted or vetoed 
     * if the new value is not an integer >=0; and <br>
     * <li>a request to perform the calculation.
     * </ol>
     */
    @Override
    public void vetoableChange(PropertyChangeEvent pce)
            throws PropertyVetoException {
        // The GUI is signaling a change that the "controller/model" needs
        // to deal with
        if (DataEntryPanel.PROPERTY_Data.equals(pce.getPropertyName())) {
            // Test to see if the data is valid
            int newData = 1;
            try {
                     newData = Integer.parseInt((String) pce.getNewValue());
            } catch (NumberFormatException e) {
                newData = -1;
            }
            if (newData <= 0) {
                // Signals the GUI to reject the entered value.
                throw new PropertyVetoException("Please enter a valid integer that is greater than zero.", pce);
            }
            // Save the state or data - bind with a database or
            // some other action.  Here we'll just update a "state" variable
            m_data = newData;
        }
        // Data entry completed - validate and switch back to main menu
        if (DataEntryPanel.PROPERTY_Done.equals(pce.getPropertyName())) {
            if (m_data <= 0) {
                // Request better data
                throw new PropertyVetoException("Please enter a valid integer that is greater than zero.", pce);
            }
            // Switch back to the Main menu
            cardLayout.show(contentPanel, MENUPANEL);
        }
        // Button pressed on the main menu
        if (MainMenuPanel.PROPERTY_MenuButton.equals(pce.getPropertyName())) {
            // This is a command to do something.  Using a vetoable change event
            // provides a nice mechanism to pass a message back to the GUI 
            // if required.
            cardLayout.show(contentPanel, DATAPANEL);
        }
    }
    /**
     *  Show in the center of the screen.
     *  (pack, set location and set visibility)
     *  @param window Window to position
     */
    private void showCenterScreen(Window window) {
        positionScreen (window);
        window.setVisible(true);
        window.toFront();
    }   //  showCenterScreen
    /**
     *  Position window in center of the screen
     *  @param window Window to position
     */
    private void positionScreen (Window window)
    {
        window.pack();
        // take into account task bar and other adornments
        GraphicsConfiguration config = window.getGraphicsConfiguration();
        Rectangle bounds = config.getBounds();
        Dimension sSize = bounds.getSize();
        Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config);
        sSize.width -= (insets.left + insets.right);
        sSize.height -= (insets.top + insets.bottom);
        Dimension wSize = window.getSize();
        //  fit on window
        if (wSize.height > sSize.height)
            wSize.height = sSize.height;
        if (wSize.width > sSize.width)
            wSize.width = sSize.width;
        window.setSize(wSize);
        //  Center
        int x = (sSize.width - wSize.width) / 2;
        int y = (sSize.height - wSize.height) / 2;
        //
        window.setLocation(bounds.x + x + insets.left, bounds.y + y + insets.top);
    }   //  positionScreen
/*****************************************************************************/
    /**
     * A simple demo GUI for the a main menu with a button.  This should be in its own file
     * but for stack overflow, its presented as a subclass.
     *
     */
    public class MainMenuPanel extends JPanel implements ActionListener, PropertyChangeListener {
        /**
         *  Constructor
         */
        public MainMenuPanel () {
            try {
                jbInit();
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
        public final static String PROPERTY_MenuButton = "MenuButton";
        private GridBagLayout gridBagLayout = new GridBagLayout();
        private JLabel      lTitle = new JLabel();
        private JButton     bOption1 = new JButton();
        private void jbInit() {
            setLayout(gridBagLayout);
            // Label
            lTitle.setToolTipText("Click a Menu Button");
            lTitle.setText("Main Menu");
            // Menu Button
            bOption1.setToolTipText("Show the Data Entry Panel");
            bOption1.setText("Enter Data");
            bOption1.addActionListener(this);
            // Layout the fields
            this.add(lTitle,    new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
                ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 2, 5), 0, 0));
            this.add(bOption1,      new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0
                ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(2, 5, 2, 5), 0, 0));
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == bOption1) {
                try {
                    fireVetoableChange(PROPERTY_MenuButton,0,1);
                } catch (PropertyVetoException e1) {
                    e1.printStackTrace();
                }
            }
        }
        // Property Change receives events from the controller
        // Doesn't do anything in this case but could be used to
        // change the menu based on state, show different entries
        // etc...
        @Override
        public void propertyChange(PropertyChangeEvent pce) {
            /* Example
            if (PROPERTY_APropertyName.equals(pce.getPropertyName())) {
                // do something relevant
            }
            */
        }
    }

/*****************************************************************************/
    /**
     * A simple demo GUI for the a data entry with a button.  This should be in its own file
     * but for stack overflow, its presented as a subclass.
     *
     */
    public class DataEntryPanel extends JPanel implements ActionListener, PropertyChangeListener {
        /**
         *  Constructor
         */
        public DataEntryPanel () {
            try {
                jbInit();
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
        // Property definitions
        public final static String PROPERTY_Done = "DoneButton";
        public final static String PROPERTY_Data = "myData";
        private GridBagLayout gridBagLayout = new GridBagLayout();
        private JLabel              lData = new JLabel();
        private JFormattedTextField fData = new JFormattedTextField("0");
        private JButton             bDone = new JButton();
        private String lastGoodData = "0";
        private boolean m_settingValue;
        private void jbInit() {
            setLayout(gridBagLayout);
            // Label
            lData.setToolTipText("Enter a positive integer");
            lData.setText("Enter number:");
            // Field
            fData.setText(lastGoodData);
            fData.setEditable(true);
            fData.setHorizontalAlignment(SwingConstants.RIGHT);
            fData.addPropertyChangeListener("value", this);
            fData.setColumns(15);
            // Button
            bDone.setToolTipText("Save the data and return to the menu.");
            bDone.setText("Save/Done");
            bDone.addActionListener(this);
            // Layout the fields
            this.add(lData,    new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
                ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
            this.add(fData,    new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
                    ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
            //grab extra space when window is maximized
            JPanel filler = new JPanel();
            filler.setOpaque(false);
            filler.setBorder(null);
            this.add(filler,        new GridBagConstraints(0, 1, 1, 1, 0.0, 1.0
                    ,GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(0, 0, 0, 0), 0, 0));
            this.add(bDone,        new GridBagConstraints(1, 2, 2, 1, 0.0, 0.0
                ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(15, 5, 10, 5), 0, 0));
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            // Ignore button events while a field is setting its value
            // This can happen if the field focus is lost to a button click
            if (e.getSource() == bDone && !m_settingValue) {
                try {
                    fireVetoableChange(PROPERTY_Done,0,1);
                } catch (PropertyVetoException pve) {
                    JOptionPane.showMessageDialog(null,
                              pve.getMessage(), "Error Massage",
                              JOptionPane.ERROR_MESSAGE);
                }
            }
        }
        // Property Change receives events from the controller or fields
        @Override
        public void propertyChange(PropertyChangeEvent pce) {
            m_settingValue = true;
            // The "value" property signals a change in a field value
            // Send the new value to the controller/model for validation
            if (fData.equals(pce.getSource()) && "value".equals(pce.getPropertyName())) {
                // Record the old value in case the change is vetoed. Don't use 
                // the pce.getOldValue(), it isn't always accurate.
                String oldValue = lastGoodData;             
                String newValue = (String) pce.getNewValue();
                try {
                    fireVetoableChange(PROPERTY_Data, oldValue, newValue);
                    lastGoodData = newValue;
                } catch (PropertyVetoException e) {
                    JOptionPane.showMessageDialog(null,
                              e.getMessage(), "Error Massage",
                              JOptionPane.ERROR_MESSAGE);
                    // Reset fData outside of the "value" event thread/loop
                    // Otherwise the value is not updated to the oldValue
                    EventQueue.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            fData.setText(lastGoodData);
                        }
                    });
                }
                m_settingValue = false;
            }
        }
    }   
}

最新更新