简体   繁体   English

Tkinter滚动条不填充框架

[英]Tkinter scrollbar doesn't fill frame

I'm trying to make a GUI that changes based on the user's resolution. 我正在尝试根据用户的分辨率更改GUI。 I'm still fairly new to Python but I have managed to accomplish this somewhat. 我对Python还是很陌生,但已经设法做到了这一点。 I am struggling to find why the scrollbar(s) do not use all of the space given to them. 我正在努力寻找为什么滚动条未使用分配给它们的所有空间的原因。 This leads to the frame behind them being visible. 这导致它们后面的框架可见。

root = Tk()

screen_height = root.winfo_screenheight()
screen_width = root.winfo_screenwidth()

h = (screen_height / 800)
w = (screen_width / 1300)

frame = ['topleft', 'topmid', 'topright',
     'bottomleft', 'bottommid']
multiplier = [300, 200, 800, 500, 100]
height = [0,
      Decimal(h*(multiplier[0]))
      .quantize(Decimal('1.'), rounding=ROUND_UP),
      Decimal(h*(multiplier[1]))
      .quantize(Decimal('1.'), rounding=ROUND_UP),
      Decimal(h*(multiplier[2]))
      .quantize(Decimal('1.'), rounding=ROUND_UP),
      Decimal(h*(multiplier[3]))
      .quantize(Decimal('1.'), rounding=ROUND_UP),
      Decimal(h*(multiplier[4]))
      .quantize(Decimal('1.'), rounding=ROUND_UP)
     ]
width = [0,
     Decimal(w*(multiplier[0]))
     .quantize(Decimal('1.'), rounding=ROUND_UP),
     Decimal(w*(multiplier[1]))
     .quantize(Decimal('1.'), rounding=ROUND_UP),
     Decimal(w*(multiplier[2]))
     .quantize(Decimal('1.'), rounding=ROUND_UP),
     Decimal(w*(multiplier[3]))
     .quantize(Decimal('1.'), rounding=ROUND_UP),
     Decimal(w*(multiplier[4]))
     .quantize(Decimal('1.'), rounding=ROUND_UP),
     Decimal(w*(multiplier[4]))
     .quantize(Decimal('1.'), rounding=ROUND_UP),
    ]

topleft = Frame(root,
            bg = 'black', bd='3',
            height = height[1], width = width[1],
            relief='flat'
            ).grid(row = height[0], column = width[0],
                   rowspan = height[1], columnspan = width[1])
topmid = Frame(root,
           bg = 'yellow', bd='3',
           height = height[2], width = width[2],
           relief='flat'
           ).grid(row = height[0], column = width[1],
                  rowspan = height[2], columnspan = width[2])
bottommid = Frame(root,
              bg = 'pink', bd ='3',
              height = height[5], width = width[5],
              relief='flat'
              ).grid(row = height[2], column = width[1],
                     rowspan = height[5], columnspan = width[5])
bottomright = Frame(root,
                bg = 'blue', bd='3',
                height = height[5], width = width[5],
                relief='flat'
                ).grid(row = height[2], column = width[1]+width[5],
                       rowspan = height[5], columnspan = width[5])

class file_selector:
def __init__(self):
    global fs_scrollbar, fs_listbox, check
    bottomleft = Frame(root,
               bg = 'white', bd='3',
               height = height[4], width = width[4],
               relief='flat'
               ).grid(row= height[1], column= width[0],
                      rowspan= height[4], columnspan= width[4])

    self.fs_scrollbar = Scrollbar(bottomleft,
                          orient = VERTICAL
                          )

    self.fs_listbox = Listbox(bottomleft,
                      bg = 'white',
                      relief = 'flat',
                      yscrollcommand = self.fs_scrollbar.set
                      )

    self.check = print(self.fs_listbox.curselection())

    self.fs_listbox.bind('<ButtonRelease-1>', self.check)

    self.fs_scrollbar['command'] = self.fs_listbox.yview

    file_selector.widgets(self)

def widgets(self):        

    self.fs_scrollbar.grid(row = height[1], column = (width[4]-(width[4]*Decimal(0.05)).quantize(Decimal('1.'), rounding=ROUND_UP)),
                           rowspan = height[4], columnspan = ((width[4]*Decimal(0.05)).quantize(Decimal('1.'), rounding=ROUND_UP)),
                           sticky= N+E+S+W
                           )

    for file in os.listdir(os.curdir):
        if file.endswith(".txt"):
            self.fs_listbox.insert(END, file)

    self.fs_listbox.grid(row = height[1], column = width[0],
                         rowspan = height[4], columnspan = (width[4]-(width[4]*Decimal(0.05)).quantize(Decimal('1.'), rounding=ROUND_UP)),
                         sticky = N+E+S+W
                         )



class text_editor:
def __init__(self):
    global te_scrollbar, te_text
    topright = Frame(root,
             bg = 'red', bd='3',
             height = height[3], width = width[3],
             relief='flat'
             ).grid(row=height[0], column= width[4],
                    rowspan= height[3], columnspan= width[3])

    self.te_scrollbar = Scrollbar(topright,
                                  orient = VERTICAL
                                  )

    self.te_text = Text(topright,
                bg = 'white',
                yscrollcommand = self.te_scrollbar.set
                )

    self.te_scrollbar['command'] = self.te_text.yview

    text_editor.widgets(self)

def widgets(self):
    with open('test1.txt', 'r') as self.file:
         self.file = self.file.read()

    self.te_scrollbar.grid(row = height[0], column = (width[4]+width[3]-(width[3]*Decimal(0.05)).quantize(Decimal('1.'), rounding=ROUND_UP)),
                           rowspan = height[3], columnspan = ((width[3]*Decimal(0.05)).quantize(Decimal('1.'), rounding=ROUND_UP)),
                           sticky = N+S
                           )

    self.te_text.insert(END, self.file)

    self.te_text.grid(row = height[0], column = width[4],
                      rowspan = height[3], columnspan = (width[3]-(width[3]*Decimal(0.05)).quantize(Decimal('1.'), rounding=ROUND_UP)),
                      sticky = N+E+S+W
                      )

file_selector()
text_editor()

Sorry in advance for the poor code, Tkinter isn't very well documented (and i'm not very good at it). 事先对糟糕的代码表示抱歉,Tkinter的文档记录不是很好(我也不是很擅长)。

You don't need to be making all of those calculations -- tkinter is very good at computing geometry for you. 您无需进行所有这些计算-tkinter非常适合您计算几何。

You're making a couple of very common mistakes in your use of grid. 您在使用网格时犯了两个非常常见的错误。 When there is extra space in a container (eg: Frame), grid will allocate extra space to rows and columns with a positive "weight". 当容器中有多余的空间(例如:框架)时,网格将为“权重”为正的行和列分配额外的空间。 By default, grid rows and columns have a weight of 0 (zero), meaning they don't get any extra space. 默认情况下,网格行和列的权重为0(零),这意味着它们不会获得任何额外的空间。

As a rule of thumb, every frame for which the internal widgets use grid needs to have at least one row and one column with a positive weight. 根据经验,内部小部件使用网格的每一帧都必须至少具有正权重的一行和一列。 You do that with the grid_rowconfigure and grid_columnconfigure commands. 您可以使用grid_rowconfiguregrid_columnconfigure命令来执行此操作。 In your case you need to give at least one row (probably the bottom row) a weight of 1 (one). 在您的情况下,您需要给至少一行(可能是最下面一行)赋予1(一)的权重。

You also have another very common problem. 您也有另一个非常普遍的问题。 Consider this line of code and others similar to it: 考虑下面这行代码和其他类似的代码:

topleft = Frame(...).grid(...)

The above will always set topleft to None because that is what grid returns. 上面将始终将topleft设置为None因为这是grid返回的内容。 Therefore, any widget you think is going into topleft is actually going into the root window since specifying None as a parent or master is the same as supplying the root window. 因此,您认为进入topleft任何小部件实际上都将进入根窗口,因为将None指定为父级或母版与提供根窗口相同。

In my opinion, however, you have even bigger problems. 但是,我认为您还有更大的问题。 Using one grid for an entire application with multiple widgets is extremely difficult to get right. 对具有多个小部件的整个应用程序使用一个网格非常困难。 Instead, you need to take a "divide and conquer" approach. 相反,您需要采取“分而治之”的方法。

For example, your GUI clearly has two main regions: a left side and a right side. 例如,您的GUI显然有两个主要区域:左侧和右侧。 So I would start by making two frames, one for each side. 因此,我将从制作两个框架开始,每侧一个框架。 With that, any grid or pack commands on the right won't affect the grid or pack commands on the left, and vise versa. 这样,右边的任何grid或pack命令都不会影响左边的grid或pack命令,反之亦然。

It also appears that the left side is divided into two sections: the top part with the colored frames, and a bottom part which is a listbox and a scrollbar. 似乎左侧也被分为两个部分:带有彩色框架的顶部和底部是列表框和滚动条的底部。 I recommend dividing the left side in half. 我建议将左侧分成两半。 Again, the use of grid or pack in the bottom left won't affect the use of grid or pack in the top left. 同样,左下角的网格或包装的使用不会影响左上角的网格或包装的使用。 This will make solving your layout problems much, much easier. 这将大大简化您的布局问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM