How to save the return value of a function attached to a tkinter Button?

Viewed 71

Background info

I am writing a set of tools to crack Vigenere cipher for a school project. There is a problem that I know I can solve if I could pass pointers like in C but I started this in Python and I don't want to rewrite everything. Code is on https://github.com/DarkFireGuy/cracking-vigenere if you want to see

The Problem

freq_analysis.py has a function _plot() that is used to plot and save the image. After pyplot has created the graph I check to see if the file has an extension. If it doesn't then I call simple_popup() from tools.py (small collection of nifty little functions). This call sends three pieces of information to a function that makes it easier for me to simplify tkinter use:

  1. A message to tell the user that the file name is bad and doesn't have an extension,
  2. Button labels to tell the user which one does what.
  3. Functions to tell each button what they're supposed to do.

If the user presses the button to enter a new name I would call simple_popup_input() (not written yet) to take the new input. But I cannot do that until I figure out how I would get the input into the fext (file extension). For now I am using exec to take user input and putting it into fext (txt on cml no fancy pants tkinter yet) but this fext is not the same fext from before. To fix all of this I need to be to write to the address at which fext is located. Google told me it wasn't possible in python so I have come to the council of smart people to see what I should do.

Solutions?

  1. Rewrite the whole thing in C

  2. Figure out how to get the memory address of fext

  3. (just came to me while writing this) write the new file extension to a temporary file and then read it after the simple_popup_input() call --- Don't want to do this because there has be a more elegant solution

  4. Don't know how it would work but to include two tuples which will contain arguments that get passed into func1 and func2. simple_popup header would become:

    def simple_popup(message="Error", f1=lambda: True, f2=lambda: True, args1: tuple = (),
                     args2: tuple = (), option1: str = "Yes", option2: str = "No")
    

req_analysis.py problematic code snippet:

# Rename file if it does not contain an extension
output, fext = os.path.splitext(output)
if not fext:
    simple_popup(message="The file name you have chosen does not contain an extension",
                 f1=lambda: exec("fext = str(input(\"New extension: \"))"),
                 option1="Enter new name",
                 option2="Save without extension"
                     )
output = output+fext
print(output)

tools.py problematic code snippet:

def simple_popup(message="Error",
                 f1=lambda: True,
                 f2=lambda: True,
                 option1: str = "Yes",
                 option2: str = "No"):

    def func1():
        f1()
        popup.quit()


    def func2():
        f2()
        popup.quit()

    popup = tk.Tk()
    label = tk.Label(popup, text=message)
    button1 = tk.Button(popup, text=option1, command=func1)
    button2 = tk.Button(popup, text=option2, command=func2)

    for tmp in [label, button1, button2]:
        tmp.pack()

    popup.mainloop()
1 Answers

You are asking the wrong question. Your question should be "Is there a better way to do this?". There is. Use a messagebox.

import tkinter as tk
from tkinter import messagebox
import os

root = tk.Tk()

path = r'C:\Some\Path'
_, ext = os.path.splitext(path)

if not ext and not messagebox.askyesno('Missing Extension', 'Save without extension?'):
    #the user may provide a dot ~ strip it out and rely on our static dot
    path = f"{path}.{input('submit new extension: ').lstrip('.')}"
          
print(path)

root.mainloop()
Related