Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
131 views
in Technique[技术] by (71.8m points)

python - Trouble using Tkinter grid

I am completely new to Tkinter and I am having problems in placing the widgets where I want them to be. I have been through numerous posts here, but I can't really find a way to solve my problem.

I created a main window and 5 frames to make the problem easier to solve. However, I cannot place them as I would like them to be. As, in Tkinter, cell's width/height change dynamically with the size of the largest widget, my GUI ends up being a total mess. I've added an outline to each frame, so it is easy to see what how widgets are being placed.

Ideally, I would like to fix all cells to a value of, let's say 10, and then just play with span commands (pretty much like an excel sheet with fixed width/height set to all cells).

I thought of playing with "weight" but it doesn't do what I need.

Basic functionality:

  • button "..." in "Open csv file", should read a csv file, create a listBox and fill it in with the contents of the csv file selected.
  • "Show Plot Preview", should display the Matplotlib graph in the frame for the selected element in the listBox.
  • "Show summary", should create a textbox with some data from the csv. For example, min, max, average, etc
  • "Save Plots" should enable the "entry" widget and allow the user to select where to save the images.

By the end, the user can say if he wants to plot, preview and save the plots. It should be allowed any combination.

Do you have any ideas? You can change the layout as you wish. I could not attach text files, so I had to paste the code here. Sorry for that!

Thanks in advance. Best regards, Pedro

My horrible layout! enter image description here

CSV file example gmId_n,vgs_n,Vth_n,Vov_n,Ids_n,Id_n 24.43,2.50E-02,9.37E-01,-9.12E-01,9.49E-15,9.93E-15 24.43,5.00E-02,9.37E-01,-8.87E-01,2.82E-14,2.91E-14 24.42,7.50E-02,9.37E-01,-8.62E-01,6.34E-14,6.47E-14 24.42,1.00E-01,9.36E-01,-8.36E-01,1.29E-13,1.31E-13 24.42,1.25E-01,9.36E-01,-8.11E-01,2.53E-13,2.55E-13 24.41,1.50E-01,9.36E-01,-7.86E-01,4.86E-13,4.89E-13 24.41,1.75E-01,9.35E-01,-7.60E-01,9.27E-13,9.30E-13

# tkinter libraries
import tkinter as tk, tkinter.ttk as ttk
from tkinter import filedialog

# Data science related libraries
import pandas as pd
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np

# OS related library -> functions used - askopenfilename(), askdirectory() and environ
import os

'''
    Functions:
        mainGUI()
        importFromMatPlotLib()
        listSelectedItem()
        chkBtnCB()
        populateListBox()
        createListBox()
        saveFigs()
        hideMe()
        
'''     
        
# ----- Global Variables -----
# ENTRIES
saveImageEntryRow,saveImageEntryCol = 2,1
saveImgEntryColumnSpan=3

csvEntryRow,csvEntryCol = 1,1
csvEntryColumnSpan=3


# BUTTONS
btnSaveImageRow, btnSaveImageCol=2,12
btnCSVfileRow , btnCSVfileCol = 1,12
btnOKRow, btnOKCol = 7,3
btnCancelRow, btnCancelCol=7,4

# FRAMES
frame1Row, frame1Col = 1,0      # Top entry fields with labels and "..." buttons
frame2Row, frame2Col = 1,1      # Checkbuttons
frame3Row, frame3Col = 3,3      # OK and cancel buttons
frame4Row, frame4Col = 2,0      # Matplotlib graphs
frame5Row, frame5Col = 2,1      # Listbox

lst1=[]
sel=0

def importFromMatPlotLib():
    global frame4

    fig = Figure(figsize=(4, 3), dpi=100)
    t = np.arange(0, 3, .01)
    fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))

    canvas = FigureCanvasTkAgg(fig, master=frame4)  # A tk.DrawingArea.
    canvas.draw()
    canvas.get_tk_widget().grid(row=0,column=0,sticky='we',padx=2,pady=2)

def listSelectedItem(*args):
    global sel
    global lst1
    
    sel = lst1.curselection()
    print("Selection -> "+str(sel))
    
def chkBtnCB(buttonID):
    global cbVar1,cbVar2,cbVar3,cbVar4

    # These checkboxes enable/disable widgets and change GUI layout accordingly -> only one implemented
    if (buttonID==1):
        print("Button1 enabled !") if cbVar1.get() else print("Button1  disabled !")
    
    elif (buttonID==2):
        print("Button2 enabled !") if cbVar2.get() else print("Button2  disabled !")    # Should enable/disable the entry field "saveImgEntry"?

    elif (buttonID==3):
        print("Button3 enabled !") if cbVar3.get() else print("Button3  disabled !")

    elif (buttonID==4):
        frame4.grid(row=frame4Row,column=frame4Col,sticky='we',padx=2,pady=2) if cbVar4.get() else frame4.grid_remove()


    else:
        print("Other button pressed!")
    
def populateListBox():
    global lst1
    
    filename =  filedialog.askopenfilename(initialdir = os.environ['HOME'],title = "Select file",filetypes = (("csv files","*.csv"),("all files","*.*")))
    #filename=str(os.environ['HOME'])+"/gmId_5V.csv"
    df=pd.read_csv(filename)
    headers=list(df)
    csvEntry.delete(0,'end')
    csvEntry.insert(0,filename)
    for i in headers:
        lst1.insert('end', i)

def createListBox():

    global lst1,csvEntry,frame5, frame4

    # ----- List Box -----
    #Objects
    lst1 = tk.Listbox(frame5, height=5,selectmode=tk.EXTENDED)
    scrollb = tk.Scrollbar(frame5, orient=tk.VERTICAL, command=lst1.yview)
    lbl1=tk.Label(frame5, text="Select fields to plot/save", anchor='w')
    sizeg=ttk.Sizegrip(frame5)

    # Grid
    lst1.grid(column=1, row=5, sticky='ns',columnspan=2)
    scrollb.grid(column=3, row=5, sticky='ns')
    lbl1.grid(column=1, row=3, sticky='we')

    frame5.grid_columnconfigure(1, weight=1)
    frame5.grid_rowconfigure(2, weight=1)

    lst1['yscrollcommand'] = scrollb.set

    # Binding
    lst1.bind('<<ListboxSelect>>',listSelectedItem)
    frame5.grid(row=2,column=1,sticky='we',padx=2,pady=2)
    
    populateListBox()   

def saveFigs():
    global lst1,saveImgEntry

    dirName =  filedialog.askdirectory()
    
    # Update textbox - entry
    saveImgEntry.delete(0,'end')
    saveImgEntry.insert(0,dirName)
        
def hideMe():
    global mw,saveImgEntry,csvEntry,frame1
    if radioVar.get()=='yes':
        saveImgEntry=tk.Entry(frame1,state=tk.NORMAL)
        saveImgEntry.grid(row=saveImageEntryRow, column=saveImageEntryCol,sticky='we',padx=2,pady=2,columnspan=saveImgEntryColumnSpan)
    else:
        saveImgEntry=frame1.Entry(mw,state=tk.DISABLED)
        saveImgEntry.grid(row=saveImageEntryRow, column=saveImageEntryCol,sticky='we',padx=2,pady=2,columnspan=saveImgEntryColumnSpan)
        
    
def mainGUI():

    global mw,csvEntry, saveImgEntry, frame4, frame5

    mw = tk.Tk()
    mw.title("Plotty")
    mw.resizable(False, False)

    frame1=tk.Frame(mw,bd=2,relief='groove')
    frame2=tk.Frame(mw,bd=2,relief='groove')
    frame3=tk.Frame(mw,bd=2,relief='groove')
    frame4=tk.Frame(mw,bd=2,relief='groove')
    frame5=tk.Frame(mw,bd=2,relief='groove',height=300)
    frame5.grid_propagate(False)
    # LABELS
    tk.Label(mw,text="Main Window").grid(row=0,column=0,sticky='ew',columnspan=5)
    lbl1=tk.Label(frame1,text="Open csv file:")
    lbl2=tk.Label(frame1,text="Save plots:")

    
    # TEXT ENTRIES
    global saveImgEntry
    csvEntry=tk.Entry(frame1,width=30)
    saveImgEntry=tk.Entry(frame1,state=tk.DISABLED,width=30)
    
    # BUTTONS
    btnCSVfile=tk.Button(frame1,text="...",command=createListBox)
    btnSaveImage=tk.Button(frame1,text="...", command=saveFigs)
    btnOK=tk.Button(frame3, text="OK", width=6)
    btnCancel=tk.Button(frame3, text="Cancel", width=6, command=mw.destroy)
    
    # CHECK BUTTONS
    global cbVar1,cbVar2,cbVar3,cbVar4
    cbVar1 = tk.BooleanVar()
    cbVar2 = tk.BooleanVar()
    cbVar3 = tk.BooleanVar()
    cbVar4 = tk.BooleanVar()
    chkBtn1=tk.Checkbutton(frame2,text='Display Plots',variable=cbVar1,command= lambda: chkBtnCB(1))
    chkBtn2=tk.Checkbutton(frame2,text='Save Plots',variable=cbVar2,command= lambda: chkBtnCB(2))
    chkBtn3=tk.Checkbutton(frame2,text='Show Summary',variable=cbVar3,command= lambda: chkBtnCB(3))
    chkBtn4=tk.Checkbutton(frame2,text='Show Plot Preview',variable=cbVar4,command= lambda: chkBtnCB(4))


    # ------  OBJECTS PLACEMENT IN THE GRID -----
    # LABELS
    lbl1.grid(row=1,column=0,sticky='w',padx=2,pady=2)
    lbl2.grid(row=2,column=0,sticky='w',padx=2,pady=2)

    # TEXT ENTRIES
    csvEntry.grid(row=csvEntryRow, column=csvEntryCol,sticky='we',padx=2,pady=2,columnspan=csvEntryColumnSpan)
    saveImgEntry.grid(row=saveImageEntryRow, column=saveImageEntryCol,sticky='we',padx=2,pady=2,columnspan=saveImgEntryColumnSpan)
    
    # BUTTONS
    btnCSVfile.grid(row=1,column=5,sticky='w',padx=2,pady=2)
    btnSaveImage.grid(row=2,column=5,sticky='w',padx=2,pady=2)
    btnOK.grid(row=3,column=4,sticky='e',padx=2,pady=2)
    btnCancel.grid(row=3,column=5,sticky='w',padx=2,pady=2)
    
    # CHECK BUTTONS
    chkBtn1.grid(row=0,column=1,sticky='w',columnspan=1,padx=2,pady=2)
    chkBtn2.grid(row=1,column=1,sticky='w',columnspan=1,padx=2,pady=2)
    chkBtn3.grid(row=0,column=2,sticky='w',columnspan=1,padx=2,pady=2)
    chkBtn4.grid(row=1,column=2,sticky='w',columnspan=1,padx=2,pady=2)

    
    importFromMatPlotLib()  # Genates a matplotlib plot and places it in frame4

    # FRAMES
    frame1.grid(row=frame1Row,column=frame1Col,padx=2,pady=2)
    frame2.grid(row=frame2Row,column=frame2Col,padx=2,pady=2)
    frame3.grid(row=frame3Row,column=frame3Col,padx=2,pady=2)
    #frame4.grid(row=2,column=0,sticky='we',padx=2,pady=2) -> done by function chkBtnCB()
    #frame5.grid(row=2,column=0,sticky='we',padx=2,pady=2) -> done by function createListBox()
    
    mw.mainloop()
    
mainGUI()
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...