2017-12-05 7 views
0

Ich habe btnShowLibrary, die die Bücher in der Bibliothek gehalten zeigt. Und dann habe ich eine Schaltfläche btnReturn, die vorherige JPanel mit der btnShowLibrary zwischen ihnen neu erstellt.Das Wechseln von JPanels verschiebt Inhalte diagonal

Initializing 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"); 

nun für das, was passiert:

Initialization

First click on the btnShowLibrary

First click on the btnReturn

2nd click on the bSL

2nd click on the bR

3rd click on the bSL

3rd click on the bR

Von den Abbildungen können Sie so, wie es „bewegt“ und ich habe keine Ahnung, warum. Kann jemand erklären, warum dies passiert und wie man es beheben kann?

+0

Rufen Sie nicht 'updateUI' an, es tut nicht, was Sie denken, dass es ist. Verwenden Sie stattdessen "revalidate" und "repaint" – MadProgrammer

+0

Ich habe es gerade versucht, aber die diagonale Verschiebung passiert immer noch. – SkyAnthrax94

+0

1) Um eine bessere Hilfe zu erhalten, geben Sie ein [MCVE] oder [Short, Self Contained, Correct Example] (http://www.sscce.org/) ein. 2) Verwenden Sie ein ['CardLayout'] (http://download.oracle.com/javase/8/docs/api/java/awt/CardLayout.html), um Komponenten zu tauschen, wie in [diese Antwort] (http: //stackoverflow.com/a/5786005/418556). –

Antwort

0

Eine einfache Möglichkeit, mehrere Panels zu verwalten, ist das CardLayout-Layout. Mit diesem Layout können Sie mehrere Panels gleichzeitig anzeigen, sodass Sie in einem Fenster leicht von einem Fenster zum anderen wechseln können. Hier ist eine Demo mit einigen Ereignissen, die zwischen den GUI-Panels und dem Haupt "Controller" passieren. Im Idealfall befinden sich die GUI-Klassen in ihren eigenen Dateien. Siehe auch 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; 
      } 
     } 
    } 
} 
+0

Das ist wirklich nett. Vielen Dank! Das wollte ich tun. – SkyAnthrax94