【问题标题】:create dynamically widgets python tkinter and adding scroll bar in canvas动态创建小部件 python tkinter 并在画布中添加滚动条
【发布时间】:2018-05-02 16:35:22
【问题描述】:

我是 Python 和 stackoverFlow 的新手。 我正在尝试从输入的第一列 CSV 文件自动创建 Checkbox 小部件。我怎样才能让滚动条处于正确的位置。下图在输入CSV文件之前,滚动条在正确的地方

enter image description here

下图输入CSV文件后,复选框小部件无法滚动

enter image description here

使用 python 3.5 编写代码

import tkinter as tk
from tkinter import ttk
import start
from tkinter.filedialog import askopenfilename
import numpy as np
import pandas as pd

LARGE_FONT=("Verdana", 12)

class MainPage(tk.Frame):
"""docstring for MainPage"""
def __init__(self, parent,controller):
    tk.Frame.__init__(self,parent)
    self.controller = controller
    self.getColumn = []
    self.createWidgets()


def createWidgets(self):
    self.createPanel()

def createPanel(self):
    nb = ttk.Notebook(self)
    nb.grid(row=1,column=0,columnspan=50,rowspan=49,sticky="NEWS")
    self.createMainPageTab(nb)
    self.createClassifyTab(nb)


def createMainPageTab(self,nb):
    self.featureSelection = tk.IntVar()

    page1 = ttk.Frame(nb)
    nb.add(page1,text="Preprocessing")

    selectFileFrame = tk.LabelFrame(page1,text = "Select File")
    selectFileFrame.grid(row=0,column=0,sticky="W",padx=5,pady=5,ipady=5,columnspan=10)

    selectRoleFrame = tk.LabelFrame(page1,text = "select Role")
    selectRoleFrame.grid(row=1,column=0,sticky="W",padx=5,pady=5,ipady=5,columnspan=1,rowspan=1)

    text = tk.Label(selectFileFrame,text="Select The File")
    text.grid(row=0,column=0, sticky="E")

    textSelectFile = tk.Text(selectFileFrame,width = 20, height = 1)
    textSelectFile.grid(row=0,column=1,sticky="WE",pady=3,padx=5)

    buttonSelectFile = tk.Button(selectFileFrame,text="browse...",command=lambda : self.load_file(textSelectFile,frameCheckBox))
    buttonSelectFile.grid(row=0,column=2,sticky="w")

    checkButtonFeatureSelection = tk.Checkbutton(selectFileFrame, text= "Feature Selection",variable = self.featureSelection)
    checkButtonFeatureSelection.grid(row=1,column=0,sticky="w") 

    buttonCek = tk.Button(selectFileFrame, text='Show', command= lambda : self.var_states())
    buttonCek.grid(row=2,column=0,sticky="W")


    #create canvas for scroll bar 
    canvasScroll = tk.Canvas(selectRoleFrame,bg="Yellow")
    canvasScroll.grid(row=0,column=0)

    vBar = tk.Scrollbar(selectRoleFrame,orient="vertical",command=canvasScroll.yview)
    vBar.grid(row=0,column=1, sticky="ns")
    canvasScroll.configure(yscrollcommand=vBar.set)

    frameCheckBox = tk.Frame(canvasScroll,bg="blue",bd=2,relief=tk.GROOVE)
    canvasScroll.create_window((0,0), window=frameCheckBox,anchor="nw")

    frameCheckBox.bind("<Configure>",self.resize(canvasScroll))


def resize(self,canvasScroll): 
    canvasScroll.configure(scrollregion=canvasScroll.bbox("all"),width=235,height=90)   


def readingCsv(self,fname):
    readCsv = pd.read_csv(fname)
    return readCsv

#event input csv file
def load_file(self,textSelectFile,frameCheckBox):
    fname = askopenfilename(filetypes=(("*.csv","Template files"),
                                       ("HTML files", "*.html;*.htm"),
                                       ("All files", "*.*") ))
    print(fname)
    mlabel = tk.Label(self,text="%s" % fname)
    mlabel.grid(row=0,column=3)
    # getText=self.textSelectFile.get()
    textSelectFile.configure(state=tk.NORMAL)
    textSelectFile.delete(1.0,tk.END)
    textSelectFile.insert(tk.END,fname)
    textSelectFile.configure(state=tk.DISABLED)
    read = self.readingCsv(fname)
    self.getColumn = self.getColumnFromCsv(read)
 #create checkbox
    if self.getColumn:
        for Column in self.getColumn:
            v = tk.StringVar()
            l = tk.Checkbutton(frameCheckBox,text=Column,variable=v)
            l.grid(sticky="w")


def getColumnFromCsv(self,readCsv):
    numeric_variables = list(readCsv.dtypes[readCsv.dtypes != "object"].index)
    return numeric_variables

def var_states(self):
    alabel = tk.Label(self,text="%s" % self.featureSelection.get())
    alabel.grid(row=3,column=0)
    print("tes : %d" %(self.featureSelection.get()))    

def feature_selection(self,chcekFeatureSelection):
    if self.featureSelection.get() == 1:
        pass



def createClassifyTab(self,nb):
    page2 = ttk.Frame(nb)
    nb.add(page2,text="Classify")

【问题讨论】:

  • 使用按钮{} 正确格式化代码。并创建更短的示例。
  • 顺便说一句:bind() 需要回调 - 这意味着没有 () 的函数名。现在你从执行的self.resize() 中分配结果,即None - 你有这样的result = self.resize(canvasScroll)frameCheckBox.bind("&lt;Configure&gt;", result)
  • 感谢您的快速回答@furas,我做了您的建议,结果 = self.resize(canvasScroll),但还是一样
  • 您使用frameCheckBox.bind("&lt;Configure&gt;", self.resize) 还是必须发送参数frameCheckBox.bind("&lt;Configure&gt;", lambda event: self.resize(canvasScroll))
  • 谢谢,它工作正常,你拯救了我的一天!!! @furas

标签: python tkinter tkinter-canvas


【解决方案1】:

你有

frameCheckBox.bind("<Configure>",self.resize(canvasScroll))

意思是

result = self.resize(canvasScroll)
frameCheckBox.bind("<Configure>", result)

所以您没有分配函数,而是执行了resize 并分配了它的结果。

但是resize 返回None 所以你终于得到了

frameCheckBox.bind("<Configure>", None)

bind()(类似于command=)需要回调 - 这意味着没有() 和参数的函数名 - 像这样

frameCheckBox.bind("<Configure>", self.resize)

因为你想发送额外的参数(并且默认跳过event发送bind)你必须使用lambda

frameCheckBox.bind("<Configure>", lambda event: self.resize(canvasScroll))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-04
    • 2016-06-06
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 2014-06-04
    • 2011-03-06
    相关资源
    最近更新 更多