Results 1 to 10 of 10
  1. #1
    ehochedez is offline Member
    Join Date
    Aug 2009
    Posts
    14
    Rep Power
    0

    Post Layout problem / add components from another class

    In a class Window extends JFrame i have a public static JPanel southPanel with a FlowLayout.
    If i add a JLabel label1 to the southPanel from the Window class, it will be positioned right in the middle of the Jpanel according to the FlowLayout.
    But if i add a JLabel label2 from another class (Window.southPanel.add(label2)), then it will be positionned at the left side of my JPanel southPanel, not centered anymore.

    Does someone know why and how to solve this problem?

  2. #2
    r035198x is offline Senior Member
    Join Date
    Aug 2009
    Posts
    2,388
    Rep Power
    8

    Default

    Use a different Layout.

  3. #3
    ehochedez is offline Member
    Join Date
    Aug 2009
    Posts
    14
    Rep Power
    0

    Default

    I created an exemple so it is easier to understand my problem.

    Java Code:
    // Main Class ----------------------------------------------------
    package test;
    
    public class Main {
    
        public static void main(String[] args) {
            Fenetre fen = new Fenetre();
            fen.show();
        }
    
    }
    -----------------------------------------------------------------
    
    
    
    
    // Fenetre Class -------------------------------------------------
    package test;
    
    import javax.swing.JLabel;
    
    public class Fenetre extends javax.swing.JFrame {
    
        public Fenetre() {
            initComponents();
            JLabel jLabel1 = new JLabel("Fenetre");
            staticPanel.add(jLabel1);
        }
    
        @SuppressWarnings("unchecked")
        // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
        private void initComponents() {
    
            container = new javax.swing.JPanel();
            staticPanel = new javax.swing.JPanel();
            panneau0 = new javax.swing.JPanel();
            goPanneau1 = new javax.swing.JButton();
    
            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
            getContentPane().setLayout(null);
    
            container.setPreferredSize(new java.awt.Dimension(600, 400));
            container.setLayout(null);
    
            staticPanel.setBackground(new java.awt.Color(204, 204, 255));
            container.add(staticPanel);
            staticPanel.setBounds(30, 180, 530, 130);
    
            panneau0.setBackground(new java.awt.Color(204, 255, 204));
            panneau0.setLayout(null);
    
            goPanneau1.setText("Go Panneau 1");
            goPanneau1.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    goPanneau1ActionPerformed(evt);
                }
            });
            panneau0.add(goPanneau1);
            goPanneau1.setBounds(210, 60, 99, 23);
    
            container.add(panneau0);
            panneau0.setBounds(0, 0, 600, 150);
    
            getContentPane().add(container);
            container.setBounds(0, 0, 600, 400);
    
            java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
            setBounds((screenSize.width-600)/2, (screenSize.height-400)/2, 600, 400);
        }// </editor-fold>                        
    
        private void goPanneau1ActionPerformed(java.awt.event.ActionEvent evt) {                                           
            Panneau1 currentPanel = new Panneau1();
            Fenetre.container.add(currentPanel);
            Fenetre.container.remove(panneau0);
            currentPanel.setBounds(0,0,600,150);
        }                                          
    
        // Variables declaration - do not modify                     
        public static javax.swing.JPanel container;
        private javax.swing.JButton goPanneau1;
        private javax.swing.JPanel panneau0;
        public static javax.swing.JPanel staticPanel;
        // End of variables declaration                   
    
    }
    ------------------------------------------------------------------
    
    
    
    
    // Panneau1 Class
    package test;
    
    import javax.swing.JLabel;
    
    public class Panneau1 extends javax.swing.JPanel {
    
        public Panneau1() {
            initComponents();
    
            JLabel jLabel2 = new javax.swing.JLabel();
            jLabel2.setText("LALALA");
            Fenetre.staticPanel.add(jLabel2);
            jLabel2.setSize(100,30);
        }
    
        @SuppressWarnings("unchecked")
        // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
        private void initComponents() {
    
            setBackground(new java.awt.Color(204, 255, 204));
            setPreferredSize(new java.awt.Dimension(600, 150));
            setLayout(null);
     
        }// </editor-fold>                        
                                                         
    
    }


    Can anyone explain why jLabel1 is centered in the staticPanel according to the defaut FlowLayout and not jLabel2?
    Last edited by Fubarable; 08-31-2009 at 02:55 PM. Reason: Code tags added for readability

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by ehochedez View Post
    Does someone know why and how to solve this problem?
    To be able to help you best here, we have to know what you are trying to achieve. If you re-read your posts carefully, you'll see that no where do you tell us why the current situation is wrong nor do you tell us what the right configuration is. You can imagine that it will be very difficult for us to give you anything more than the most general advise (i.e., "use a different layout manager") without knowing more. The ball is back in your court.

  5. #5
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Also,
    1) when adding and removing components, don't forget to call revalidate and repaint:
    Java Code:
      private void goPanneau1ActionPerformed(
          java.awt.event.ActionEvent evt) {
        Panneau1 currentPanel = new Panneau1();
        Fenetre.container.add(currentPanel);
        Fenetre.container.remove(panneau0);
        currentPanel.setBounds(0, 0, 600, 150);
        
        // Added ***
        Fenetre.container.revalidate();
        Fenetre.container.repaint();
      }
    2) I would advise you strongly not to use a null layout here.

  6. #6
    ehochedez is offline Member
    Join Date
    Aug 2009
    Posts
    14
    Rep Power
    0

    Default

    Thanks a lot Fubarable, you were right, my problem was because i did not use revalidate().. shame on me..

    Why do you think it is not advised to use a null Layout please?

  7. #7
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Many use null layout when we must, when no other options are available, but try to avoid it for most tasks as it makes the program layout quite rigid and non-adaptable to different OS's or to changes.

  8. #8
    ehochedez is offline Member
    Join Date
    Aug 2009
    Posts
    14
    Rep Power
    0

    Default

    Ah ok.. so i'll be more careful cause i need to move from windows to debian later..

    Thanls a lot.

  9. #9
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    I'm not sure if you're still following this question, but if so, I often find it is best to illustrate the problem and solution with an example:

    Say you wanted to create a JPanel to go into a dialog window that holds a JLabel that asks a question located at the top, 3 JRadioButton choices in a column in the middle, and an OK JButton at the bottom. If so, you could easily create something with a null layout like so:
    Java Code:
    public class QuestionPanelNullLayout extends JPanel {
      
      public QuestionPanelNullLayout() {
        setLayout(null);
        setPreferredSize(new Dimension(270, 174));
    
        JLabel questionLabel = new JLabel("What color is Washington's white horse");
        JRadioButton blackBtn = new JRadioButton("Black");
        JRadioButton blueBtn = new JRadioButton("Blue");
        JRadioButton whiteBtn = new JRadioButton("White");
        JButton okBtn = new JButton("OK");
    
        questionLabel.setBounds(10, 10, 249, 16);
        blackBtn.setBounds(10, 36, 249, 24);
        blueBtn.setBounds(10, 70, 249, 24);
        whiteBtn.setBounds(10, 104, 249, 24);
        okBtn.setBounds(10, 138, 249, 26);
        
        add(questionLabel);
        add(blackBtn);
        add(blueBtn);
        add(whiteBtn);
        add(okBtn);
      }
    But try to resize this, and you'll find that it's very rigid. Even more frustrating, what if you want to make it so that it can display four answers instead of three? That would mean adding another JRadioButton, moving the button down and increasing the size of the JPanel. What if you wanted to add another button next to the first one? Then you'll have to resize the button, add another one, tweak here and there to make sure all fits right. And lord help you if you want to make it display a variable number of answer JRadioButtons, one that could vary with each Question...

    So you find that any alteration affects many of the components already there and requires more and more work.

    Now what if on the other hand you created your app using layout managers?

    We can make the main JPanel use a BorderLayout and then add the questionLabel to the top via BorderLayout.NORTH:
    Java Code:
        JLabel questionLabel = new JLabel("What color is Washington's white horse");
        setLayout(new BorderLayout(10, 10));
        add(questionLabel, BorderLayout.NORTH);
    The radiobuttons we can add into a JPanel created to hold them that uses GridLayout with one column and variable number of rows: GridLayout(0, 1, 10, 10) (the 10, 10 is to place 10 point vertical and horizontal gaps between all added components):

    Java Code:
        String[] possibleAnswers = {"Black", "Blue", "White"};
        JPanel possibleAnswerPanel = new JPanel(new GridLayout(0, 1, 10, 10));
        for (int i = 0; i < possibleAnswers.length; i++) {
          JRadioButton radioButton = new JRadioButton(possibleAnswers[i]);
          possibleAnswerPanel.add(radioButton);
        }
    and then we can add the possibleAnswerPanel to the main JPanel BorderLayout.CENTER:
    Java Code:
        setLayout(new BorderLayout(10, 10));
        add(questionLabel, BorderLayout.NORTH);
        add(possibleAnswerPanel, BorderLayout.CENTER);
    Finally the button can be added to its own JPanel that uses a GridLayout with one row and variable number of columns: GridLayout(1, 0, 10, 10) (again the 10, 10 for vertical and horizontal gaps):
    Java Code:
        JButton okBtn = new JButton("OK");
        JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 10, 10));
        buttonPanel.add(okBtn);
    And this buttonPanel can be added to the main panel (that uses BorderLayout) in the BorderLayout.SOUTH position:
    Java Code:
        setLayout(new BorderLayout(10, 10));
        add(questionLabel, BorderLayout.NORTH);
        add(possibleAnswerPanel, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.SOUTH);
    So the new panel in fact looks exactly like the first, except now if I add a new answer by extending the string array:
    Java Code:
    String[] possibleAnswers = {"Black", "Blue", "White", "Red"};
    the app will automatically resize to fit the new answer. Likewise, if I add another button,
    Java Code:
        JButton okBtn = new JButton("OK");
        JButton cancelBtn = new JButton("Cancel"); 
        JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 10, 10));
        buttonPanel.add(okBtn);
        buttonPanel.add(cancelBtn);
    the GUI will automatically move things to accommodate it.

    A working class might look something like this:
    QuestionPanelWithLayout.java
    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class QuestionPanelWithLayout extends JPanel{
      private static final String OK = "OK";
      private static final String CANCEL = "Cancel";
      private String[] possibleAnswers;
      private int answerIndex;
      private ButtonGroup btnGrp = new ButtonGroup();
      private boolean okSelected = false;
      private boolean answerCorrect = false;
      private String selectedAnswer = "";
      
      public QuestionPanelWithLayout(String questionString, String[] possibleAnswers, int index) {
        this.possibleAnswers = possibleAnswers;
        this.answerIndex = index;
        
        JPanel questionPanel = new JPanel(new GridLayout(0, 1, 10, 10));
        for (String answer : possibleAnswers) {
          JRadioButton radioBtn = new JRadioButton(answer);
          radioBtn.setActionCommand(answer);
          btnGrp.add(radioBtn);
          questionPanel.add(radioBtn);
        }
        
        JButton okBtn = new JButton(OK);
        JButton cancelBtn = new JButton(CANCEL);
        BtnListener btnListener = new BtnListener();
        okBtn.addActionListener(btnListener);
        cancelBtn.addActionListener(btnListener);
        JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 10, 10));
        buttonPanel.add(okBtn);
        buttonPanel.add(cancelBtn);
        
        setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        setLayout(new BorderLayout(10, 10));
        add(new JLabel(questionString, SwingConstants.LEFT), BorderLayout.NORTH);
        add(questionPanel, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.SOUTH);
      }
      
      public boolean isAnswerCorrect() {
        return answerCorrect;
      }
      
      public boolean isOkSelected() {
        return okSelected;
      }
      
      public String getSelectedAnswer() {
        return selectedAnswer;
      }
      
      private class BtnListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
          String actionCommand = e.getActionCommand();
          if (actionCommand.equals(OK)) {
            okSelected = true;
            ButtonModel bModel = btnGrp.getSelection();
            if (bModel != null) {
              selectedAnswer = bModel.getActionCommand();
              if(possibleAnswers[answerIndex].equals(selectedAnswer)) {
                answerCorrect = true;
              } else {
                answerCorrect = false;
              }
            }
          }
          else {
            okSelected = false;
            answerCorrect = false;
          }
          
          Window win = SwingUtilities.getWindowAncestor(QuestionPanelWithLayout.this);
          win.dispose();
        }
      }
    
    }
    and could be displayed and used like so:
    ShowQuestion.java
    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class ShowQuestion {
      
      private static String questionString = "What color was Washington's white horse?";
      private static String[] answers = {
        "Black", "Blue", "White" //, "Red"
      };
      private static final JFrame frame = new JFrame("Ask Question");
    
      private static void createAndShowGUI() {
        JButton showQuestionBtn = new JButton("Show Question");
        showQuestionBtn.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent arg0) {
            showQuestionActionPerformed();
          }
        });
        
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(200, 100));
        panel.add(showQuestionBtn);
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    
      private static void showQuestionActionPerformed() {
        QuestionPanelWithLayout questionPanel = new QuestionPanelWithLayout(questionString, answers, 2);
        
        JDialog dialog = new JDialog(frame, "Question", true);
        dialog.getContentPane().add(questionPanel);
        dialog.pack();
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);
        
        if (questionPanel.isOkSelected()) {
          System.out.println("Selected Answer: \"" + questionPanel.getSelectedAnswer() + 
              "\"; Correct?: " + questionPanel.isAnswerCorrect());      
        }
        else {
          System.out.println("Question Canceled");
        }
      }
    
      public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            createAndShowGUI();
          }
        });
    
      }
    }

  10. #10
    ehochedez is offline Member
    Join Date
    Aug 2009
    Posts
    14
    Rep Power
    0

Similar Threads

  1. [SOLVED] Layout Problem
    By casid in forum New To Java
    Replies: 4
    Last Post: 06-03-2009, 12:17 AM
  2. JFrame 's components size and location problem
    By petrosgraf in forum Threads and Synchronization
    Replies: 5
    Last Post: 04-18-2009, 03:24 AM
  3. Inconsistent layout w/dynamic resize of components
    By donb2000 in forum AWT / Swing
    Replies: 3
    Last Post: 07-26-2008, 03:40 PM
  4. Problem In Swing Components
    By SANDY_INDIA in forum AWT / Swing
    Replies: 1
    Last Post: 07-19-2008, 11:23 PM
  5. Replies: 0
    Last Post: 06-25-2008, 11:35 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •