【问题标题】:Python 3 - Tkinter button commandsPython 3 - Tkinter 按钮命令
【发布时间】:2016-08-03 16:58:30
【问题描述】:

我也是 Tkinter 和 Python 的新手。我的 Tkinter 框架中有三个带有命令的按钮。按钮 1 调用 open_csv_dialog(),打开文件对话框以选择 .csv 文件并返回路径。按钮 2 调用 save_destination_folder(),打开文件对话框以打开首选目录并返回路径。

我的问题是按钮 3。它调用 modify_word_doc() 需要从按钮 1 和按钮 2 返回的文件路径。

我试过了;

button3 = ttk.Button(root, text="Run", command=lambda: modify_word_doc(open_csv_dialog, save_destination_folder)).pack()

但这显然只是提示文件对话框再次打开 open_csv_dialog() 和 save_destination_folder() 函数,这是不希望的。我想只使用这两个函数已经返回的文件路径并将其传递给 modify_word_doc 而不会被另一个文件对话框提示。我也尝试过使用partial,但我要么用错了,要么仍然有同样的不良后果。

我已经阅读了关于命令的 Tkinter 文档并搜索了一个可能的答案,所以如果之前已经回答过这个问题并且我没有找到它,我们深表歉意。

import tkinter as tk
from tkinter import filedialog
from tkinter import ttk
import os
import csv
import docx
from functools import partial


root = tk.Tk()


def open_csv_dialog():
    file_path = filedialog.askopenfilename(filetypes=(("Database files",
        "*.csv"),("All files", "*.*")))
    return file_path


def save_destination_folder():
    file_path = filedialog.askdirectory()
    return file_path


def modify_word_doc(data, location):
    #data = open_csv_dialog()
    #location = save_destination_folder()
    #long code.  takes .csv file path opens, reads and modifies word doc with 
    #the contents of the .csv, then saves the new word doc to the requested 
    #file path returned from save_destination_folder().


label = ttk.Label(root, text="Step 1 - Choose CSV File.",
    font=LARGE_FONT)
label.pack(pady=10, padx=10)
button = ttk.Button(root, text="Choose CSV",
    command= open_csv_dialog).pack()
label = ttk.Label(root,
    text="Step 2 - Choose destination folder for your letters.",
    font=LARGE_FONT)
label.pack(pady=10, padx=10)
button2 = ttk.Button(root, text="Choose Folder",
    command=save_destination_folder).pack()
label = ttk.Label(root, text="Step 3 - Select Run.", font=LARGE_FONT)
label.pack(pady=10, padx=10)
button3 = ttk.Button(root, text="Run", 
    command=lambda: modify_word_doc(open_csv_dialog, save_destination_folder)).pack()


root.mainloop()

【问题讨论】:

  • 顺便说一句,你有一个语法错误,还有一个(,然后是)

标签: python tkinter


【解决方案1】:

这可能只是输入问题时的错误......但为了完整起见

button3 = ttk.Button(root, text="Run", command=lambda: modify_word_doc(open_csv_dialog, save_destination_folder).pack()

您缺少ttk.Button(*)*.pack() 的右括号

应该是(语法上):

 button3 = ttk.Button(root, text="Run", command=lambda: modify_word_doc(open_csv_dialog, save_destination_folder)).pack()

此外,使用 .pack() 会返回 None,因此将变量设置为小部件 + 几何管理器方法只会将该变量设置为空,而不是对小部件对象的引用。

因此,如果您确实需要对这个小部件的引用,您实际上应该这样做:

 button3 = ttk.Button(*)
 button3.pack()

如果您不需要参考,那么就不要分配任何东西并为自己节省一些输入,因为它是多余的。

对于实际问题:

如果我理解您的问题,您有两个按钮可以设置 .csv 的文件路径和目标文件夹。但是,由于您的两个函数都使用该对话框,即使您可能已经选择了,也会再次提示您。

您可以使用全局变量和其他各种方法来执行此操作,我将在基本根窗口上设置一个属性,因为我认为这在这里最简单...

在下面的代码中,如果选择了file_path,我所做的只是在root 窗口上设置一个属性。您可以使用if 语句检查这一点。

然后我调用check_state 来查看根窗口是否具有这两个属性getattr(object, string, default) 将返回该属性,如果该属性不存在则返回默认值。因此,通过将 file_path 设置为字符串,或者如果重新选择了位置,则设置为 None,状态将始终正确更新。

你可以再清理一下。如果你真的想的话,你实际上可以同时做这两个功能等等。

import tkinter as tk
from tkinter import filedialog, ttk

def check_state():

    if getattr(root, 'csv_path', False) and getattr(root, 'dest_path', False):
        button3['state'] = 'normal'
    else:
        button3['state'] = 'disabled'

def open_csv_dialog():

    file_path = filedialog.askopenfilename(
        filetypes=(("Database files", "*.csv"), ("All files", "*.*")))
    if file_path:
        root.csv_path = file_path
    else:
        root.csv_path = None
    check_state()

def save_destination_folder():

    file_path = filedialog.askdirectory()
    if file_path:
        root.dest_path = file_path
    else:
        root.dest_path = None
    check_state()

def modify_word_doc():
   print(root.csv_path, root.dest_path)

root = tk.Tk()
ttk.Label(root, text="Step 1 - Choose CSV File.",).pack(pady=10, padx=10)
ttk.Button(root, text="Choose CSV", command= open_csv_dialog).pack()
ttk.Label(root, text="Step 2 - Choose destination folder for your letters.").pack(pady=10, padx=10)
ttk.Button(root, text="Choose Folder", command=save_destination_folder).pack()
ttk.Label(root, text="Step 3 - Select Run.").pack(pady=10, padx=10)

#We need a reference to the widget here, for the state func...

button3 = ttk.Button(root, text="Run", state='disabled', command=modify_word_doc)
button3.pack()
root.mainloop()

【讨论】:

  • 完美!这正是我所需要的!感谢您提供如此深入的响应以及清理冗余代码的帮助。是的,我输入问题时出现语法错误。
猜你喜欢
  • 2023-02-24
  • 2015-08-21
  • 1970-01-01
  • 2019-11-29
  • 2021-04-14
  • 2013-04-19
  • 2020-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多