Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x Tkinter中的流体设计_Python 3.x_Tkinter_Ttk - Fatal编程技术网

Python 3.x Tkinter中的流体设计

Python 3.x Tkinter中的流体设计,python-3.x,tkinter,ttk,Python 3.x,Tkinter,Ttk,我正试图用ttk(tkinter)创建一个有点“响应性”的设计。小部件的基本布局一点问题都没有,但是让它随着程序的宽度流动是我无法实现的。在CSS中,我知道可以对所有容器说“float:left”,页面会根据屏幕大小进行调整。我在Tkinter和frames中没有发现类似的东西 我的基本测试计划: #!/usr/bin/python3 import tkinter from tkinter import ttk from ttkthemes import ThemedTk, THEMES c

我正试图用ttk(tkinter)创建一个有点“响应性”的设计。小部件的基本布局一点问题都没有,但是让它随着程序的宽度流动是我无法实现的。在CSS中,我知道可以对所有容器说“float:left”,页面会根据屏幕大小进行调整。我在Tkinter和frames中没有发现类似的东西

我的基本测试计划:

#!/usr/bin/python3

import tkinter
from tkinter import ttk
from ttkthemes import ThemedTk, THEMES

class quick_ui(ThemedTk):
    def __init__(self):
        ThemedTk.__init__(self, themebg=True)
        self.geometry('{}x{}'.format(900, 150))
        self.buttons = {}

        self.frame1 = ttk.Frame(self)
        self.frame1.pack(side="left")
        self.frame2 = ttk.Frame(self)
        self.frame2.pack(side="left")

        #------------------------------------------------------- BUTTONS
        i = 0
        while (i < 5):
            i += 1
            self.buttons[i]= ttk.Button(self.frame1,
                                            text='List 1 All ' + str(i),
                                            command=self.dump)
            self.buttons[i].pack(side="left")


        while (i < 10):
            i += 1
            self.buttons[i]= ttk.Button(self.frame2,
                                            text='List 2 All ' + str(i),
                                            command=self.dump)
            self.buttons[i].pack(side="left")

    def dump(self):
        print("dump called")

quick = quick_ui()
quick.mainloop()
#/usr/bin/python3
进口tkinter
从tkinter导入ttk
从TTK主题导入主题,主题
类快速用户界面(TK):
定义初始化(自):
主题Tk.\uuuu初始化(self,themebg=True)
self.geometry(“{}x{}.”格式(900150))
self.buttons={}
self.frame1=ttk.Frame(self)
自我框架1.包装(侧=“左”)
self.frame2=ttk.Frame(self)
自我框架2.包装(侧=“左”)
#-------------------------------------------------------钮扣
i=0
而(i<5):
i+=1
self.buttons[i]=ttk.Button(self.frame1,
text='List 1 All'+str(i),
命令=self.dump)
self.buttons[i].pack(side=“left”)
而(i<10):
i+=1
self.buttons[i]=ttk.Button(self.frame2,
text='List 2 All'+str(i),
命令=self.dump)
self.buttons[i].pack(side=“left”)
def转储(自):
打印(“转储调用”)
quick=quick\u ui()
quick.mainloop()
这将创建一个包含10个按钮的窗口,这些按钮彼此相隔。 当我将窗口缩小到按钮不再适合屏幕时,我希望按钮显示在彼此下方

因此,我所做的是添加一个resize侦听器并设置以下方法:

    def resize(self, event):
        w=self.winfo_width()
        h=self.winfo_height()
        # print("width: " + str(w) + ", height: " + str(h))

        if(w < 830):
            self.frame1.config(side="top")
            self.frame2.config(side="top")
def resize(自身、事件):
w=self.winfo_width()
h=自我。winfo_高度()
#打印(“宽度:+str(w)+”,高度:+str(h))
如果(w<830):
self.frame1.config(side=“top”)
self.frame2.config(side=“top”)
但是
Frame
没有属性
side
,该属性是为方法
pack
指定的参数。所以这也没用

现在我迷路了。我花了很长时间在这方面,尝试网格和其他解决方案,但我觉得我错过了一个简单但非常重要的设置。

我创建了一个(黑客)解决方案,这是一个很好的解决方案,因为它是一个非常内部的程序。由于同时没有给出答案,我将在这里提供我的解决方案。它可能有很大的改进空间,但我希望这能给未来的人一些关于如何自己解决这个问题的建议

#/usr/bin/python3
进口稀土
导入系统
进口tkinter
从tkinter导入文件对话框
从tkinter导入ttk
从TTK主题导入主题,主题
导入子流程
导入操作系统
从tkinter.constants导入单位
导入json
从functools导入部分
类快速用户界面(TK):
定义初始化(自):
主题Tk.\uuuu初始化(self,themebg=True)
自我管理(600250)
self.elems={}
self.resize\u after\u id=None
#-------------------------------------------------------窗口菜单栏内容
self.menubar=tkinter.Menu(self)
self.menubar.add_命令(label=“Open”,command=self.dump)
self.menubar.add_命令(label=“Refresh”,command=self.dump)
self.config(menu=self.menubar)
#主题菜单
self.themeMenu=tkinter.Menu(self.menubar,tearoff=0)
self.menubar.add\u级联(label=“Theme”,menu=self.themeMenu)
self.themeMenu.add_命令(label=“DEFAULT”,command=partial(self.dump,“DEFAULT”))
#----------------------------------------------------------------------顶框
self.top_frame=ttk.frame(self)
self.top\u frame.pack(side=tkinter.top,expand='YES',fill='both',padx=10)
self.top\u top\u frame=ttk.frame(self.top\u frame)
self.top\u top\u frame.pack(side=tkinter.top,expand='YES',fill='both')
self.top\u bottom\u frame=ttk.frame(self.top\u frame)
自.顶部\底部\框架包装(侧面=底部)
self.top\u bottom\u top\u frame=ttk.frame(self.top\u frame)
self.top\u bottom\u top\u frame.pack(side=tkinter.top)
self.top\u bottom\u bottom\u frame=ttk.frame(self.top\u frame)
self.top\u bottom\u bottom\u frame.pack(side=tkinter.bottom)
#-------------------------------------------------------------------底框
self.bottom_frame=ttk.frame(self,relief=“sunken”)
自底包装(侧面=底部),
展开“是”,
“两个都填”,
padx=10,
帕迪=10)
#-------------------------------------------------------钮扣
i=0
而(i<15):
self.elems[i]=ttk.按钮(self.top\u bottom\u top\u框架,
text='List All'+str(i),
命令=self.dump)
i+=1
self.label\u test\u strings1=ttk.label(self.top\u top\u frame,text='test strings1')
self.label\u test\u strings2=ttk.label(self.top\u bottom\u框架,text='test strings2')
self.label\u test\u strings4=ttk.label(self.top\u bottom\u bottom\u框架,text='test strings4')
自贴标签测试线1.pack(侧面=顶部)
自贴标签\u测试\u strings2.pack(侧边=tkinter.TOP)
自贴标签测试线4.包装(侧面=顶部)
self.placeElems()
#设置在配置(窗口大小)更改时触发的挂钩
self.bind(“”,self.resize)
def placeElems(自身):
对于self.elems中的索引:
self.elems[index].grid(行=0,列=ind
#!/usr/bin/python3

import re
import sys
import tkinter
from tkinter import filedialog
from tkinter import ttk
from ttkthemes import ThemedTk, THEMES

import subprocess
import os
from tkinter.constants import UNITS
import json
from functools import partial


class quick_ui(ThemedTk):

    def __init__(self):
        ThemedTk.__init__(self, themebg=True)
        self.minsize(600, 250)
        self.elems = {}
        self.resize_after_id = None


        #------------------------------------------------------- Window menu bar contents
        self.menubar = tkinter.Menu(self)
        self.menubar.add_command(label="Open", command = self.dump)
        self.menubar.add_command(label="Refresh", command = self.dump)
        self.config(menu=self.menubar)

        # Theme menu
        self.themeMenu = tkinter.Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Theme", menu=self.themeMenu)
        self.themeMenu.add_command(label="DEFAULT", command=partial(self.dump, "default"))


        #---------------------------------------------------------------------- top_frame
        self.top_frame = ttk.Frame(self)
        self.top_frame.pack( side = tkinter.TOP, expand='YES', fill='both', padx=10)

        self.top_top_frame = ttk.Frame(self.top_frame)
        self.top_top_frame.pack(side=tkinter.TOP, expand='YES', fill='both')

        self.top_bottom_frame = ttk.Frame(self.top_frame)
        self.top_bottom_frame.pack(side=tkinter.BOTTOM)

        self.top_bottom_top_frame = ttk.Frame(self.top_frame)
        self.top_bottom_top_frame.pack(side=tkinter.TOP)


        self.top_bottom_bottom_frame = ttk.Frame(self.top_frame)
        self.top_bottom_bottom_frame.pack(side=tkinter.BOTTOM)

        #------------------------------------------------------------------- bottom_frame
        self.bottom_frame = ttk.Frame(self, relief="sunken")
        self.bottom_frame.pack( side = tkinter.BOTTOM, 
                                expand='YES', 
                                fill='both', 
                                padx=10, 
                                pady=10 )

        #------------------------------------------------------- BUTTONS
        i = 0
        while (i < 15):
            self.elems[i]=ttk.Button(self.top_bottom_top_frame,
                                                text='List All ' + str(i),
                                                command=self.dump)
            i += 1


        self.label_test_strings1 = ttk.Label(self.top_top_frame, text='Test strings1')
        self.label_test_strings2 = ttk.Label(self.top_bottom_frame, text='Test strings2')
        self.label_test_strings4 = ttk.Label(self.top_bottom_bottom_frame, text='Test strings4')

        self.label_test_strings1.pack(side = tkinter.TOP)
        self.label_test_strings2.pack(side = tkinter.TOP)
        self.label_test_strings4.pack(side = tkinter.TOP)


        self.placeElems()
        # Setup a hook triggered when the configuration (size of window) changes
        self.bind('<Configure>', self.resize)


    def placeElems(self):
        for index in self.elems:
            self.elems[index].grid(row=0, column=index, padx=5, pady=5)


    # ------------------------------------------------------ Resize event handler
    def resize(self, event):
        # Set a low "time-out" for resizing, to limit the change of "fighting" for growing and shrinking
        if self.resize_after_id is not None:
            self.after_cancel(self.resize_after_id)
        self.resize_after_id = self.after(200, self.resize_callback)


    # ------------------------------------------------------ Callback for the resize event handler
    def resize_callback(self):
        # The max right position of the program
        windowMaxRight = self.winfo_rootx() + self.winfo_width()

        # Some basic declarations
        found = False
        willAdd = False
        maxColumn = 0
        currIndex = 0
        currColumn = 0
        currRow = 0
        counter = 0
        last_rootx = 0
        last_maxRight = 0

        # Program is still starting up, so ignore this one
        if(windowMaxRight < 10):
            return

        # Loop through all the middle bar elements
        for child in self.top_bottom_frame.children.values():
            # Calculate the max right position of this element
            elemMaxRight = child.winfo_rootx() + child.winfo_width() + 10

            # If we already found the first 'changable' child, we need to remove the following child's also
            if(found == True):
                # Is the window growing?
                if(willAdd == True):
                    # Check to see if we have room for one more object
                    calcMaxRight = last_maxRight + child.winfo_width() + 20
                    if(calcMaxRight < windowMaxRight):
                        maxColumn = counter + 1
                # Remove this child from the view, to add it again later
                child.grid_forget()

            # If this child doesn't fit on the screen anymore
            elif(elemMaxRight >= windowMaxRight):
                # Remove this child from the view, to add it again later
                child.grid_forget()
                currIndex = counter
                maxColumn = counter
                currRow = 1
                found = True

            else:
                # If this child's x position is lower than the last child
                # we can asume it's on the next row
                if(child.winfo_rootx() < last_rootx):
                    # Check to see if we have room for one more object on the first row
                    calcMaxRight = last_maxRight + child.winfo_width() + 20
                    if(calcMaxRight < windowMaxRight):
                        child.grid_forget()
                        currIndex = counter
                        currColumn = counter
                        maxColumn = counter + 1
                        found = True
                        willAdd = True

            # Save some calculation data for the next run
            last_rootx = child.winfo_rootx()
            last_maxRight = elemMaxRight
            counter += 1

        # If we removed some elements from the UI
        if(found == True):
            counter = 0
            # Loop through all the middle bar elements (including removed ones)
            for child in self.top_bottom_frame.children.values():
                # Ignore the elements still in place
                if(counter < currIndex):
                    counter += 1
                    continue

                # If we hit our maxColumn count, move to the next row
                if(currColumn == maxColumn):
                    currColumn = 0
                    currRow += 1

                # Place this element on the UI again
                child.grid(row=currRow, column=currColumn, padx=5, pady=5)
                currColumn += 1
                counter += 1


    def dump(self):
        print("dump called")


quick = quick_ui()
quick.mainloop()