简体   繁体   English

Python Tkinter 网格设置

[英]Python Tkinter grid set up

My first coding project, and I am trying to create an app to use as a dashboard on an old laptop.我的第一个编码项目,我正在尝试创建一个应用程序,用作旧笔记本电脑上的仪表板。

Weather app concept天气应用程序概念

Can I use tkinters grid to create boxes like in the picture?我可以使用 tkinter 网格来创建图片中的框吗?

I have stumbled for two days and I cannot come up with a good result at all nor have I managed to create a good box yet.我已经跌跌撞撞了两天,我根本无法想出一个好的结果,也没有设法创造出一个好的盒子。

Here is my code:这是我的代码:

import requests
from tkinter import *
from PIL import ImageTk, Image



def weather():
    city=city_listbox.get()
    url="https://api.openweathermap.org/data/2.5/weather?q={}&appid=*myappid*&units=metric".format(city)
    res=requests.get(url)
    output=res.json()

weather_status=output['weather'][0]['description']
temperature=output['main']['temp']
feelslike=output['main']['feels_like']
humidity=output['main']['humidity']
wind_speed=output['wind']['speed']

weather_status_label.configure(text="Weather status : "+ weather_status)

if weather_status=="few clouds":
    partial_cloud_label=Label(image=partial_cloud)
    partial_cloud_label.grid(row=3, column=4)
    

temperature_label.configure(text="Temperature : "+ str(temperature) +"°C")

feelslike_label.configure(text="Feels like : "+ str(feelslike) +"°C")

humidity_label.configure(text="Humidity : "+ str(humidity) +"%")

wind_speed_label.configure(text="Wind speed  : "+ str(wind_speed) +"m/s")




window=Tk()
window.geometry("1920x1080")
window.iconbitmap('localfile')
window.title('Show dis weather')

partial_cloud=ImageTk.PhotoImage(Image.open("local file"))
day_clear=ImageTk.PhotoImage(Image.open("localfile"))
cloudy=ImageTk.PhotoImage(Image.open("localfile"))

city_name_list=["City1", "City2"]

city_listbox=StringVar(window)
city_listbox.set("select the city")
option=OptionMenu(window,city_listbox,*city_name_list)
option.grid(row=2,column=6,padx=150,pady=10)

b1=Button(window,text="Select",width=15,command=weather)
b1.grid(row=5,column=6,padx=150)

weather_status_label=Label(window, font=("didot",15,"bold"))
weather_status_label.grid(row=10,column=6)

temperature_label=Label(window,font=("didot",15,"bold"))
temperature_label.grid(row=16,column=6)

feelslike_label=Label(window,font=("didot",15,"bold"))
feelslike_label.grid(row=22,column=6)

humidity_label=Label(window,font=("didot",15,"bold"))
humidity_label.grid(row=28,column=6)

wind_speed_label=Label(window,font=("didot",15,"bold"))
wind_speed_label.grid(row=34,column=6)


window.mainloop()

Seeking advice towards Tkinter gui.寻求对 Tkinter gui 的建议。 I was thinking that you could possibly create boxes and set all the "widgets" or data inside them.我在想,您可以创建框并在其中设置所有“小部件”或数据。

For ex, creating a box and put it to the left and have the weather status and information inside there.例如,创建一个框并将其放在左侧并在其中包含天气状态和信息。 A box NW for the buttons to choose city.用于选择城市的按钮的 NW 框。 Box N to show big text for which city it is showing information for.框 N 显示它正在显示信息的城市的大文本。

Is this possible in Tkinter?这在 Tkinter 中可能吗?

If I have left insufficient information or if this is a too loose thread to being helped through, please write and tell me about it, I am very new in this, so I appreciate all help.如果我没有留下足够的信息,或者如果这是一个太松散的线索而无法获得帮助,请写信告诉我,我对此很陌生,所以我感谢所有帮助。

With Regards!带着敬意!

I would use Frames in order to organize the view.我会使用框架来组织视图。 And instead of using random bigger numbers to try spacing things out(empty rows and columns stay at size zero until filled with content), you should take a look into the weight option of grid.row(or column)configure as well as the row(or column)span option of grid itself.而不是使用随机更大的数字来尝试将事物grid.row(or column)configure空行和列保持大小为零,直到填充内容),您应该查看grid.row(or column)configureweight选项以及row(or column)span grid本身的row(or column)span选项。

in order to achieve your view you might wanna start with something like this:为了实现你的观点,你可能想从这样的事情开始:

import tkinter as tk

class Application(tk.Tk):
    
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        
        #Window config
        tk.Tk.wm_title(self, "WeatherApp")
        self.geometry("1920x1080")
        
        #Main Layout
        self.mainframe = tk.Frame(self)
        self.mainframe.pack(fill="both", expand = True)
        self.mainframe.grid_rowconfigure(0, weight=1)
        self.mainframe.grid_rowconfigure(1, weight=1)
        self.mainframe.grid_columnconfigure(0, weight=1)
        self.mainframe.grid_columnconfigure(1, weight=1)
        self.mainframe.grid_columnconfigure(2, weight=1)
        self.mainframe.grid_columnconfigure(3, weight=1)
        
        #Top Container
        self.top = tk.Frame(self.mainframe)
        #placing in the main frame
        self.top.grid(row = 0, column = 0, columnspan = 4)
        
        #configure layout for top view
        self.top.grid_rowconfigure(0, weight=1)
        self.top.grid_columnconfigure(0, weight=1)
        
        #content of top view
        self.toplabel = tk.Label(self.top, text = "City: ")
        self.toplabel.grid(row = 0, column = 0)
        
        #day1
        self.day1 = tk.Frame(self.mainframe)
        #placing in the main frame
        self.day1.grid(row = 1, column = 0)
        
        #configure layout for top view
        self.day1.grid_rowconfigure(0, weight=1)
        self.day1.grid_columnconfigure(0, weight=1)
        
        #content of day1 frame
        self.label1 = tk.Label(self.day1, text="saturday")
        self.label1.grid(row = 0, column = 0)
        
        
        #day2
        self.day2 = tk.Frame(self.mainframe)
        #placing in the main frame
        self.day2.grid(row = 1, column = 1)
        
        #you don't have to configure if all cells should have equal size
        
        #content of day1 frame
        self.label2 = tk.Label(self.day2, text="sunday")
        self.label2.grid(row = 0, column = 0)
        
        
        #day3
        self.day3 = tk.Frame(self.mainframe)
        #placing in the main frame
        self.day3.grid(row = 1, column = 2)
        
        #content of day1 frame
        self.label3 = tk.Label(self.day3, text="monday")
        self.label3.grid(row = 0, column = 0)
        
        
        #day4
        self.day4 = tk.Frame(self.mainframe)
        #placing in the main frame
        self.day4.grid(row = 1, column = 3)
        
        #content of day1 frame
        self.label4 = tk.Label(self.day4, text="tuesday")
        self.label4.grid(row = 0, column = 0)
        
app = Application()
app.mainloop()

EDIT:编辑:

The __init__ function is always getting called when a class is being used, see . __init__函数总是在使用类时被调用,请参阅 You can use other functions from within each other, but you can't just toss it in there and expect it to run without beeing called, you might wanna take a look at inner Functions .您可以在彼此内部使用其他函数,但您不能将它扔在那里并期望它在没有被调用的情况下运行,您可能想看看内部 Functions

But that isn't what I would do in your case.但这不是我在你的情况下会做的。

I would create 2 new other classes (1 for top frame, 1 for bottom frame) and inhereting from the tk.Frame class for 2 reasons:我会创建 2 个新的其他类(1 个用于顶部框架,1 个用于底部框架)并从tk.Frametk.Frame ,原因有两个:

  1. readability since everything is where it belongs and nicely grouped togehter可读性,因为一切都在它所属的地方并且很好地组合在一起
  2. reuseability because the content of all your bottom frames is the same(widget wise) so you can just pass the values to change:可重用性,因为所有底部框架的内容都相同(小部件明智),因此您只需传递值即可更改:
import tkinter as tk

class Application(tk.Tk):
    
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        
        #Window config
        tk.Tk.wm_title(self, "WeatherApp")
        self.geometry("1920x1080")
        
        #Main Layout
        self.mainframe = tk.Frame(self)
        self.mainframe.pack(fill="both", expand = True)
        self.mainframe.grid_rowconfigure(0, weight=1)
        self.mainframe.grid_rowconfigure(1, weight=1)
        self.mainframe.grid_columnconfigure(0, weight=1)
        self.mainframe.grid_columnconfigure(1, weight=1)
        self.mainframe.grid_columnconfigure(2, weight=1)
        self.mainframe.grid_columnconfigure(3, weight=1)
        
        #Top Container
        #note the changed declaration, since we're now calling 
        #our own Frame class
        self.top = TopFrame(self.mainframe)
        #placing in the main frame
        self.top.grid(row = 0, column = 0, columnspan = 4)
        
        
        #day1
        # note the passthrough of the day argument
        self.day1 = DayFrame(self.mainframe, "saturday")
        #placing in the main frame
        self.day1.grid(row = 1, column = 0)
        
        
        #day2
        self.day2 = DayFrame(self.mainframe, "sunday")
        #placing in the main frame
        self.day2.grid(row = 1, column = 1)
        
        
        #day3
        self.day3 = DayFrame(self.mainframe, "monday")
        #placing in the main frame
        self.day3.grid(row = 1, column = 2)
        
        
        #day4
        self.day4 = DayFrame(self.mainframe, "tuesday")
        #placing in the main frame
        self.day4.grid(row = 1, column = 3)
        
     
     
class TopFrame(tk.Frame):
    
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        
        #add code for your widgets in top frame here
        label = tk.Label(self, text="Top Frame")
        label.grid(row = 0, column = 0)
        
        
class DayFrame(tk.Frame):
    
    def __init__(self, parent, day):
        tk.Frame.__init__(self, parent)
        
        # add code for bottom frame widgets here
        # pass nessecary variables through to reuse the code
        self.day = day
        self.daylabel = tk.Label(self, text = day)
        self.daylabel.grid(row = 0, column = 0)
        
        
        
app = Application()
app.mainloop()

Also please note what thelizzard said about my sloppiness when it comes to using .grid(row=0, column=0) in the same row, because you will run into errors with this as soon as you want to change anything about the variable!还请注意 thelizzard 在同一行中使用.grid(row=0, column=0)时对我的草率所说的话,因为只要您想更改有关变量的任何内容,就会遇到错误!

Thank you Newb, and you others, for different answers.谢谢 Newb 和其他人的不同答案。

I have used Newb's code and made some changes, like making it a 12 grid big and changing the order of where the frames should be.我使用了 Newb 的代码并进行了一些更改,例如将其设置为 12 格大并更改帧的位置顺序。

I have also tried to implement the "weather" code from the original code, and there is where I got stuck.我还尝试从原始代码中实现“天气”代码,但我遇到了困难。

Can you put a function inside another function?你能把一个函数放在另一个函数中吗?

I still cannot understand what init is for, but that I can learn on the side.我仍然无法理解 init 的用途,但我可以一边学习。

Here is the updated code:这是更新后的代码:

import tkinter as tk
#from tkinter import *
from PIL import ImageTk, Image

class Application(tk.Tk):
   
    
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        
        #Window config
        tk.Tk.wm_title(self, "WeatherApp")
        self.geometry("1920x1080")
        self.iconbitmap('localfile')
        #This part I have added
        self.partial_cloud=ImageTk.PhotoImage(Image.open("localfile"))
        self.day_clear=ImageTk.PhotoImage(Image.open("localfile"))
        self.cloudy=ImageTk.PhotoImage(Image.open("localfile"))


        #This part I have added
        def weather():
            self.city=city_listbox.get()
            self.url="https://api.openweathermap.org/data/2.5/weather?q={}&appid=*myappid*&units=metric".format(city)
            self.res=requests.get(url)
            self.output=res.json()

            self.weather_status=output['weather'][0]['description']
            self.temperature=output['main']['temp']
            self.feelslike=output['main']['feels_like']
            self.humidity=output['main']['humidity']
            self.wind_speed=output['wind']['speed']

            self.weather_status_label.configure(text="Weather status : "+ weather_status)

                if weather_status=="few clouds":
                    partial_cloud_label=Label(image=partial_cloud)
                    partial_cloud_label.grid(row=3, column=4)
        


            temperature_label.configure(text="Temperature : "+ str(temperature) +"°C")

            feelslike_label.configure(text="Feels like : "+ str(feelslike) +"°C")

            humidity_label.configure(text="Humidity : "+ str(humidity) +"%")

            wind_speed_label.configure(text="Wind speed  : "+ str(wind_speed) +"m/s")




        #Main Layout
        self.mainframe = tk.Frame(self)
        self.mainframe.pack(fill="both", expand = True)
        self.mainframe.grid_rowconfigure(0, weight=1)
        self.mainframe.grid_rowconfigure(1, weight=1)
        self.mainframe.grid_rowconfigure(2, weight=1)
        self.mainframe.grid_columnconfigure(0, weight=1)
        self.mainframe.grid_columnconfigure(1, weight=1)
        self.mainframe.grid_columnconfigure(2, weight=1)
        self.mainframe.grid_columnconfigure(3, weight=1)
        
        #Top Left Container
        self.tl = tk.Frame(self.mainframe)
        #placing in the main frame
        self.tl.grid(row = 0, column = 0)
        
        #configure layout for top view
        self.tl.grid_rowconfigure(0, weight=1)
        self.tl.grid_columnconfigure(0, weight=1)
        



        #This part I have added

        #content of top view
        self.city_name_list=["city1", "city2"]

        self.city_listbox=StringVar(self.tl)
        self.city_listbox.set("select the city")
        self.option=OptionMenu(self.tl,city_listbox,*city_name_list)
        self.option.grid(row=0,column=0,padx=150,pady=10)

        self.b1=Button(self.tl, text="Select",width=15,command=weather)
        self.b1.grid(row=0,column=0,padx=150)
        #self.tllabel = tk.Label(self.tl, text = "Button ", font=("Sentinel", 20, "bold"))
        #self.tllabel.grid(row = 0, column = 0)







        #Top Middle Container (tm)
        self.tm = tk.Frame(self.mainframe)
        #placing in the main frame
        self.tm.grid(row = 0, column = 1) #Leaving comment for my self columnspan = 4
        
        #configure layout for top view
        self.tm.grid_rowconfigure(0, weight=1)
        self.tm.grid_columnconfigure(0, weight=1)
        
        #content of top view
        self.tmlabel = tk.Label(self.tm, text = "City: ", font=("Sentinel", 36, "bold"))
        self.tmlabel.grid(row = 0, column = 0)


        #Left Container
        self.left = tk.Frame(self.mainframe)
        #placing in the main frame
        self.left.grid(row = 1, column = 0)
        
        #configure layout for top view
        self.left.grid_rowconfigure(0, weight=1)
        self.left.grid_columnconfigure(0, weight=1)
        
        #content of top view
        self.leftlabel = tk.Label(self.left, text = "Weather ", font=("Sentinel", 20, "bold"))
        self.leftlabel.grid(row = 0, column = 0)


        

        
        #day1
        self.day1 = tk.Frame(self.mainframe) # Tried to make a border, leaving comment for my self width=3, height=100, highlightbackground="black", highlightthickness=1) #bd=100)#relief=tk.RIDGE)
        #placing in the main frame
        self.day1.grid(row = 2, column = 0)
        
        #configure layout for top view
        self.day1.grid_rowconfigure(0, weight=1)
        self.day1.grid_columnconfigure(0, weight=1)
        
        #content of day1 frame
        self.label1 = tk.Label(self.day1, text="Saturday", font=("Sentinel", 26, "bold")).grid(row = 0, column = 0)
        
        
        #day2
        self.day2 = tk.Frame(self.mainframe)
        #placing in the main frame
        self.day2.grid(row = 2, column = 1)
        
        #you don't have to configure if all cells should have equal size
        
        #content of day1 frame
        self.label2 = tk.Label(self.day2, text="Sunday", font=("Sentinel", 26, "bold")).grid(row = 0, column = 0)
        
        
        #day3
        self.day3 = tk.Frame(self.mainframe)
        #placing in the main frame
        self.day3.grid(row = 2, column = 2)
        
        #content of day1 frame
        self.label3 = tk.Label(self.day3, text="Monday", font=("Sentinel", 26, "bold")).grid(row = 0, column = 0)
        
        
        #day4
        self.day4 = tk.Frame(self.mainframe)
        #placing in the main frame
        self.day4.grid(row = 2, column = 3)
        
        #content of day1 frame
        self.label4 = tk.Label(self.day4, text="Tuesday", font=("Sentinel", 26, "bold")).grid(row = 0, column = 0)
        
app = Application()
app.mainloop()

You have already helped me a lot, but if you feel to help me how to implement this, feel free to do it.你已经帮了我很多,但如果你想帮助我如何实现这一点,请随时去做。

Thanks and have a great day!谢谢,祝你有美好的一天!

EDIT:编辑:

Hi there!你好呀! Sorry for bumping an old thread, I am still working to make this application working!很抱歉碰到旧线程,我仍在努力使此应用程序正常工作!

When I am trying to run the following code, I get the NameError: "name 'city_listbox' is not defined code" at line 172当我尝试运行以下代码时,我在第 172 行收到 NameError: "name 'city_listbox' is not defined code"

Anyone has any energy and clue what I can do to implement the Weather code inside the grid code supplied from Newb?任何人都有任何能量和线索我可以做些什么来实现 Newb 提供的网格代码中的天气代码?

import requests
import tkinter as tk
#from tkinter import *
from PIL import ImageTk, Image

class Application(tk.Tk):
   
    
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)


        def weather():
           def __init__(self, TopLFrame):
               city=city_listbox.get()
               url="https://api.openweathermap.org/data/2.5/weather?q={}&appid=ID&units=metric".format(city)
               res=requests.get(url)
               output=res.json()

               weather_status=output['weather'][0]['description']
               temperature=output['main']['temp']
               feelslike=output['main']['feels_like']
               humidity=output['main']['humidity']
               wind_speed=output['wind']['speed']

               weather_status_label.configure(text="Weather status : "+ weather_status)

               if weather_status=="few clouds":
                   partial_cloud_label=tk.Label(image=partial_cloud)
                   partial_cloud_label.grid(row=3, column=4)
        


               temperature_label.configure(text="Temperature : "+ str(temperature) +"°C")

               feelslike_label.configure(text="Feels like : "+ str(feelslike) +"°C")

               humidity_label.configure(text="Humidity : "+ str(humidity) +"%")

               wind_speed_label.configure(text="Wind speed  : "+ str(wind_speed) +"m/s") 

        #Window config
        tk.Tk.wm_title(self, "WeatherApp")
        self.geometry("1920x1080")
        #self.iconbitmap('linktopicture')
        
        #self.partial_cloud=ImageTk.PhotoImage(Image.open("linktopicture"))
        #self.day_clear=ImageTk.PhotoImage(Image.open("linktopicture"))
        #self.cloudy=ImageTk.PhotoImage(Image.open("linktopicture"))
        
  
        #Main Layout
        self.mainframe = tk.Frame(self)
        self.mainframe.pack(fill="both", expand = True)
        self.mainframe.grid_rowconfigure(0, weight=1)
        self.mainframe.grid_rowconfigure(1, weight=1)
        self.mainframe.grid_rowconfigure(2, weight=1)
        self.mainframe.grid_columnconfigure(0, weight=1)
        self.mainframe.grid_columnconfigure(1, weight=1)
        self.mainframe.grid_columnconfigure(2, weight=1)
        self.mainframe.grid_columnconfigure(3, weight=1)
        
  
        #Top Left Container
        self.tl = TopLFrame(self.mainframe, weather)
        self.tl.grid(row = 0, column = 0)

        #self.tl.grid_rowconfigure(0, weight=1)
        #self.tl.grid_columnconfigure(0, weight=1)


        #Top Middle Container (tm)
        self.tm = TopMFrame(self.mainframe)
        self.tm.grid(row = 0, column = 1)
        
        #self.tm.grid_rowconfigure(0, weight=1)
        #self.tm.grid_columnconfigure(0, weight=1)
        

        #Left Container
        self.left = MidFrame(self.mainframe)
        self.left.grid(row = 1, column = 0)
        
        #self.left.grid_rowconfigure(0, weight=1)
        #self.left.grid_columnconfigure(0, weight=1)
       
        
        
        #day1
        self.day1 = BottomFrame(self.mainframe, "Monday") 
        self.day1.grid(row = 2, column = 0)
        
        #self.day1.grid_rowconfigure(0, weight=1)
        #self.day1.grid_columnconfigure(0, weight=1)
        
   
        #day2
        self.day2 = BottomFrame(self.mainframe, "saturday")
        #placing in the main frame
        self.day2.grid(row = 2, column = 1)
        

        #day3
        self.day3 = BottomFrame(self.mainframe, "test")
        self.day3.grid(row = 2, column = 2)
        
        #day4
        self.day4 = BottomFrame(self.mainframe, "test2")
        self.day4.grid(row = 2, column = 3)
        
    



class TopMFrame(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        #add code for your widgets in top frame here
        self.label = tk.Label(self, text="Top Mid Frame")
        self.label.grid(row = 0, column = 0)
 


class TopLFrame(tk.Frame):

    def __init__(self, parent, Application):
        tk.Frame.__init__(self, parent)


        self.city_name_list=["City1", "City2"]

        self.city_listbox=tk.StringVar(self)
        self.city_listbox.set("select the city")
        
        self.option=tk.OptionMenu(self, city_listbox, *city_name_list)
        self.option.grid(row=0,column=0,padx=150,pady=10)

        self.b1=tk.Button(self, text="Select",width=15,command=weather)
        self.b1.grid(row=0,column=0,padx=150)

class MidLFrame(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        
        self.label = tk.Label(self, text="Left Frame")
        self.label.grid(row = 0, column = 0)

        self.weather_status_label=tk.Label(self, font=("didot",15,"bold"))
        self.weather_status_label.grid(row=10,column=6)

        self.temperature_label=tk.Label(self,font=("didot",15,"bold"))
        self.temperature_label.grid(row=16,column=6)

        self.feelslike_label=tk.Label(self,font=("didot",15,"bold"))
        self.feelslike_label.grid(row=22,column=6)

        self.humidity_label=tk.Label(self,font=("didot",15,"bold"))
        self.humidity_label.grid(row=28,column=6)

        self.wind_speed_label=tk.Label(self,font=("didot",15,"bold"))
        self.wind_speed_label.grid(row=34,column=6)

class BottomFrame(tk.Frame):
    
    def __init__(self, parent, day):
        tk.Frame.__init__(self, parent)
        
        # add code for bottom frame widgets here
        # pass nessecary variables through to reuse the code
        self.day = day


        self.label1 = tk.Label(self, text = day, font=("Sentinel", 26, "bold"))
        self.label1.grid(row = 0, column = 0)


app = Application()
app.mainloop()

With Regards, Joggster!问候,乔格斯特!

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

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