How to stop Tkinter Frame from shrinking to fit its contents?

194

By default, both pack and grid shrink or grow a widget to fit its contents, which is what you want 99.9% of the time. The term that describes this feature is geometry propagation. There is a command to turn geometry propagation on or off when using pack (pack_propagate) and grid (grid_propagate).

Since you are using pack the syntax would be:

f.pack_propagate(0)

or maybe root.pack_propagate(0), depending on which widgets you actually want to affect. However, because you haven't given the frame height, its default height is one pixel so you still may not see the interior widgets. To get the full effect of what you want, you need to give the containing frame both a width and a height.

That being said, the vast majority of the time you should let Tkinter compute the size. When you turn geometry propagation off your GUI won't respond well to changes in resolution, changes in fonts, etc. Tkinter's geometry managers (pack, place and grid) are remarkably powerful. You should learn to take advantage of that power by using the right tool for the job.

Share:
194
User
Author by

User

Updated on December 27, 2020

Comments

  • User
    User over 3 years

    The graphics should repaint with a new color after a mouse click, but they don´t.

    I´ve already implemented the MouseListener in the component and in the frame, but in both versions it did´nt work.

    The Frame and MouseListener:

    public class frame extends Frame
     {
         public static void main(String[] args)
            {
    
               JFrame frame = new JFrame();
    
               String string = new String("1  2  3  4  5  6  7");
    
               final int FRAME_WIDTH = 527;
               final int FRAME_HEIGHT = 77;
    
               frame.setAlwaysOnTop(true);
               frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
               frame.setTitle("Praxis");
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               frame.setUndecorated(true);
               // JFrame zentriert positionieren; selbst berechnet:
               Toolkit tk = Toolkit.getDefaultToolkit();
               Dimension d = tk.getScreenSize();
               frame.setLocation((int) ((d.width)-700), (int) (0));
    
               Font font = new Font("Jokerman", Font.BOLD, 35);
               JLabel textLabel = new JLabel(string);
               textLabel.setFont(font);
    
               test component = new test();
               frame.add(component);
    
               MouseListener listen = new MouseListener()
               {
                public void mouseClicked(MouseEvent e) {
                    GlobalVar obj = new GlobalVar();
                    obj.fillColor1 = obj.farben[1];
                    component.repaint();
                }
                @Override
                public void mousePressed(MouseEvent e) {
                    // TODO Auto-generated method stub
    
                }
                @Override
                public void mouseReleased(MouseEvent e) {
                    // TODO Auto-generated method stub
    
                }
                @Override
                public void mouseEntered(MouseEvent e) {
                    // TODO Auto-generated method stub
    
                }
                @Override
                public void mouseExited(MouseEvent e) {
                    // TODO Auto-generated method stub
    
                }
               };
               component.addMouseListener(listen);
    
               frame.setVisible(true);
    
            }
    
     }
    

    The File where they get the Color from:

    public class GlobalVar{
        public static final Color[] farben = new Color[4];{ 
            farben[0] = Color.LIGHT_GRAY;
            farben[1] = Color.RED;
            farben[2] = Color.GREEN;
            farben[3] = Color.PINK;
        }
        Color fillColor1 = farben[0];
        Color fillColor2 = farben[0];
        Color fillColor3 = farben[0];
        Color fillColor4 = farben[0];
        Color fillColor5 = farben[0];
        Color fillColor6 = farben[0];
        Color fillColor7 = farben[0];
    }
    

    The Component which draws the graphics:

    public class test extends JComponent
     { 
            GlobalVar obj = new GlobalVar();
    
         @Override
            public void paintComponent(Graphics g)
            {       
    
              if(g instanceof Graphics2D) {
               // Recover Graphics2D
               Graphics2D g2 = (Graphics2D) g;
    
               // Construct a rectangle and draw it
               Rectangle box1 = new Rectangle(2, 2, 71, 71);
               g2.setColor(Color.BLACK);
               g2.draw(box1);
               g2.setColor(obj.fillColor1);
               g2.fill(box1);
    
               Rectangle box2 = new Rectangle(77, 2, 71, 71);
               g2.setColor(Color.BLACK);
               g2.draw(box2);
               g2.setColor(obj.fillColor2);
               g2.fill(box2);
    
               Rectangle box3 = new Rectangle(152, 2, 71, 71);
               g2.setColor(Color.BLACK);
               g2.draw(box3);
               g2.setColor(obj.fillColor3);
               g2.fill(box3);
    
               Rectangle box4 = new Rectangle(227, 2, 71, 71);
               g2.setColor(Color.BLACK);
               g2.draw(box4);
               g2.setColor(obj.fillColor4);
               g2.fill(box4);
    
               Rectangle box5 = new Rectangle(302, 2, 71, 71);
               g2.setColor(Color.BLACK);
               g2.draw(box5);
               g2.setColor(obj.fillColor5);
               g2.fill(box5);
    
               Rectangle box6 = new Rectangle(377, 2, 71, 71);
               g2.setColor(Color.BLACK);
               g2.draw(box6);
               g2.setColor(obj.fillColor6);
               g2.fill(box6);
    
               Rectangle box7 = new Rectangle(452, 2, 71, 71);
               g2.setColor(Color.BLACK);
               g2.draw(box7);
               g2.setColor(obj.fillColor7);
               g2.fill(box7);
    
               g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    
               Font f = new Font("Dialog", Font.PLAIN, 30);
               g2.setFont(f);
               g2.setColor(Color.BLACK);
               g2.drawString("1", 30, 48);
               g2.drawString("2", 105, 48);
               g2.drawString("3", 180, 48);
               g2.drawString("4", 255, 48);
               g2.drawString("5", 330, 48);
               g2.drawString("6", 405, 48);
               g2.drawString("7", 480, 48);
              }
    
            }
    
            private Color fillColor1;
            private Color fillColor2;
            private Color fillColor3;
            private Color fillColor4;
            private Color fillColor5;
            private Color fillColor6;
            private Color fillColor7;
     }
    

    As I said, I expected the graphics to repaint with the first square to be filled with the color red, but the actual result is, that nothing happens when I click on the frame.

    • Locke
      Locke almost 5 years
      Just add the MouseListener to literally everything. Every single JFrame and JPanel you create. Then remove it from panels until it is stops working to find what the listener should be on.
  • martineau
    martineau over 11 years
    It could also be self.pack_propagate(0) if done in a method like the __init__() of a widget class derived from Frame -- as in the commonly used class Application(Frame): idiom.
  • Bas
    Bas almost 9 years
    The first example doesn't work for me. The window has the right size, but the widgets aren't visible on screen. The second example does work for me everything displays fine in the screen with the given width/height! +1
  • Gary02127
    Gary02127 over 6 years
    @Bas: in the original example, the Frame "height" is not passed and defaults to 0, so when propagation is turned off, the height stays 0 and you don't see the Label. You would have to set the Frame height=20 or something along those lines to see the Label.