I have written a program in Python that allow me to change the names of many files all at once. I have one issue that is quite odd.
When I use raw_input to get my desired extension, the GUI will not launch. I don't get any errors, but the window will never appear.
I tried using raw_input as a way of getting a file extension from the user to build the file list. This program will works correctly when raw_input is not used.The section of code that I am referring to is in my globList function. For some reason when raw_imput is used the window will not launch.
import os
import Tkinter
import glob
from Tkinter import *
def changeNames(dynamic_entry_list, filelist):
for index in range(len(dynamic_entry_list)):
if(dynamic_entry_list[index].get() != filelist[index]):
os.rename(filelist[index], dynamic_entry_list[index].get())
print "The files have been updated!"
def drawWindow(filelist):
dynamic_entry_list = []
my_row = 0
my_column = 0
for name in filelist:
my_column = 0
label = Tkinter.Label(window, text = name, justify = RIGHT)
label.grid(row = my_row, column = my_column)
my_column = 1
entry = Entry(window, width = 50)
dynamic_entry_list.append(entry)
entry.insert(0, name)
entry.grid(row = my_row, column = my_column)
my_row += 1
return dynamic_entry_list
def globList(filelist):
#ext = raw_input("Enter the file extension:")
ext = ""
desired = '*' + ext
for name in glob.glob(desired):
filelist.append(name)
filelist = []
globList(filelist)
window = Tkinter.Tk()
user_input = drawWindow(filelist)
button = Button(window, text = "Change File Names", command = (lambda e=user_input: changeNames(e, filelist)))
button.grid(row = len(filelist) + 1 , column = 1)
window.mainloop()
Is this a problem with raw_input?
What would be a good solution to the problem?
This is how tkinter is defined to work. It is single threaded, so while it's waiting for user input it's truly waiting. mainloop must be running so that the GUI can respond to events, including internal events such as requests to draw the window on the screen.
Generally speaking, you shouldn't be mixing a GUI with reading input from stdin. If you're creating a GUI, get the input from the user via an entry widget. Or, get the user input before creating the GUI.
A decent tutorial on popup dialogs can be found on the effbot site: http://effbot.org/tkinterbook/tkinter-dialog-windows.htm
Related
I have been trying to use tkinter CheckButton widget to edit items in a list - each item of the list is a new checkbutton. I want a save method to save the data to a text file, and a load method to load the info from the text file and mark the checkbutton boxes depending on the items in the list.
Here is my code so far, but the list doesn't seem to change when I check the buttons and update the list/file
Here is my code, I need to know why the list isn't updating when I check the boxes:
import tkinter.messagebox as box
modulesMain = Tk()
moduleChecks = []
def SaveChanges():
# Clear the text file
modules = open("modules.txt", "w") #Write mode to overwrite the whole file
modules.write("") # Put in blank text
modules.close()
modules = open("modules.txt", "a") # Append mode to append the file
for item in moduleChecks:
modules.write(item + "\n")
print(moduleChecks)
appButton = Checkbutton(modulesMain, text = "Test", variable = moduleChecks[0]).grid()
searchButton = Checkbutton(modulesMain, text = "Test", variable = moduleChecks[1]).grid()
Save = Button(modulesMain, text = "Save Changes", command = SaveChanges).grid()
The variable for each of your checkboxes needs to be an IntVar. Your moduleCheck list is currently un-initialised so when you try to access the elements inside it, you'll get an error.
In the below code (modified from yours), I've initialised the moduleCheck to contain two IntVars.
When you press the save button, it will print to the console the current state of the check boxes.
import tkinter as tk
modulesMain = tk.Tk()
moduleChecks = [tk.IntVar() for i in range(2)]
def SaveChanges():
for idx,item in enumerate(moduleChecks):
print(f"{idx} = {item.get()}")
appCheck = tk.Checkbutton(modulesMain, text = "App", variable = moduleChecks[0])
appCheck.grid()
searchCheck = tk.Checkbutton(modulesMain, text = "Check", variable = moduleChecks[1])
searchCheck.grid()
saveButton = tk.Button(modulesMain, text = "Save Changes", command = SaveChanges)
saveButton.grid()
modulesMain.mainloop()
Here is a basic solution.
import tkinter as tk
root = tk.Tk()
#list of options. doubles as checkbox label text
#appending to this list is all that is necessary to create more options
opts = ['App', 'Search']
#create an StringVar for every option
#this way there doesn't have to be type conversions for reading/writing files
vars = [tk.StringVar(value='0') for _ in opts]
#create checkboxes for every option
for opt, var in zip(opts, vars):
tk.Checkbutton(root, text=opt, variable=var, onvalue='1', offvalue='0').grid(sticky='w')
#write the checkbox values to file
def save_options_state():
with open("modules.txt", "w") as file:
file.write(''.join([v.get() for v in vars]))
#set checkbox values from file
def load_options_state():
with open("modules.txt", "r") as file:
for n, var in zip(list(file.read().strip()), vars):
var.set(n)
#save/load buttons
tk.Button(root, text="save", command=save_options_state).grid()
tk.Button(root, text="load", command=load_options_state).grid(row=2, column=1)
root.mainloop()
Here's a runnable example which I think shows how to do everything you've asked about. It assumes the modules.txt file contains data in the following format, where each line consists of a module's name and whether it's checked or not.
Mod1,0
Mod2,0
Mod3,0
The data in the file is used to create a list of Checkbuttons — one for each module — and initially sets to its current status as indicated in the file.
Here's the sample code:
from tkinter import *
import tkinter.messagebox as box
dataFilename = "modules.txt"
moduleChecks = []
def ReadModules():
with open(dataFilename, "r") as file:
for line in (line.strip() for line in file):
moduleName, moduleState = line.split(',')
moduleChecks.append((moduleName, int(moduleState)))
print('read:', moduleChecks)
def SaveChanges():
print('writing:', moduleChecks)
with open(dataFilename, "w") as file:
for checkButton in moduleCheckbuttons:
moduleName = checkButton.cget('text')
moduleState = checkButton.var.get()
file.write(','.join((moduleName, str(moduleState))) + '\n')
ReadModules()
modulesMain = Tk()
moduleCheckbuttons = []
# Create a Checkbutton for each module based on moduleChecks values.
for moduleName, moduleState in moduleChecks:
intVar = IntVar(value=moduleState)
checkButton = Checkbutton(modulesMain, text=moduleName, variable=intVar)
checkButton.var = intVar # Attach reference to variable.
checkButton.grid()
moduleCheckbuttons.append(checkButton)
saveButton = Button(modulesMain, text="Save Changes", command=SaveChanges)
saveButton.grid()
modulesMain.mainloop()
I've got a function in a class in which I am creating several tkinter buttons within, where the number of buttons and the button properties depends on a file (so I can't create a specific number of variables to hold the buttons).
The code I have looks like this (sparing the complexities of the whole code):
import os
import tkinter as tk
Class(GUI):
def ButtonCreator(self):
self.HomeworkList = open("Files\HWNameList.txt", "r")
x = self.HomeworkList.readline()
while not x == "END":
x = x[0:-1]
HomeworkFileName = str("Files\HW-" + x + ".txt")
locals()["self.Button" + x] = tk.Button(master, text = x, command = lambda: self.DisplayHomeworkFile(FileName))
locals()["self.Button" + x].pack()
x = self.HomeworkList.readline()
self.HomeworkList.close()
def DisplayHomeworkFile(self, filename):
os.startfile(filename)
The file I am opening looks like this...
HomeworkName1
HomeworkName2
HomeworkName3
END
When the code runs, it displays the buttons with the correct text written on them but when i click on them they only ever display the file who's file name is written last in the HomeworkList file. Not sure what I've done wrong.
If there is another way to achieve what I'm trying I'm open to all suggestions.
Thanks.
This is a classic beginners problem that comes from misunderstanding how lambda works. For this case you need to use functools.partial.
You also need to forget about modifying locals(). Make a list or dictionary to hold the button instances.
from functools import partial
def ButtonCreator(self):
self.HomeworkList = open("Files\HWNameList.txt", "r")
x = self.HomeworkList.readline()
self.buttons = []
while not x == "END":
x = x[0:-1]
HomeworkFileName = str("Files\HW-" + x + ".txt")
btn = tk.Button(master, text = x, command = partial(self.DisplayHomeworkFile, HomeworkFileName))
btn.pack()
self.buttons.append(btn)
x = self.HomeworkList.readline()
self.HomeworkList.close()
This might be a strange question because I am new to Python.
I am trying to create form in Python which data can be entered into boxes and saved, then opened again. I'm currently using Tkinter to create a Gui which has entry boxes and buttons:
import sys
from tkinter import *
def mstore():
pass
return
def msearch():
file_path = filedialog.askopenfilename()
return
mGui=Tk()
mGui.geometry('450x450+200+200')
mGui.title('Form Test')
#Top
mTitle = Label (mGui,text='Heading Text',bg='white').grid(row=1,column=1)
mDetail = Label (mGui,text='Flavour you can see',bg='white').grid(row=2,column=1)
#Entry Boxes
mFName = Label (mGui,text='Barcode',bg='white').grid(row=3,column=1)
mEntryname = Entry().grid(row=3,column=2)
#Buttons
mSave = Button (mGui,text='Save',bg='white', command = mstore).grid(row=4,column=1)
mSearch = Button (mGui,text='Search',bg='white', command = msearch).grid(row=5,column=1)
mGui.mainloop()
The search was going to be used to open up a file which has been saved before and fill in the boxes with that data, however before that I need help saving the data in a way it will be retrievable - All the information I find is about web-forms. I have also tried saving information with SQLite3 but I found that to not be quite what I was looking for.
Any help/guidance will be appreciated.
Thanks,
Hello Gregulimy!
I have simplified your code and made it do what you want it to do. I have left comments explaining what the code does. If you have any questions about what I have done feel free to ask!
from tkinter import *
def mstore(text):
file = open("file.txt", "w") # Create file.txt
file.write(text) # Write contents of mEntryname to file
file.close() # Closes text file
def msearch():
file = filedialog.askopenfilename() # Stores file directory that user chose
open_file = open(file, 'r') # Opens file user chose
print(open_file.read()) # Displays contents in console
open_file.close() # Closes text file
# Window Creation and Settings
window = Tk()
window.geometry('450x500')
window.title('Form Test')
# Create Widgets
mTitle = Label (window,text='Heading Text',bg='white')
mDetail = Label (window,text='Flavour you can see',bg='white')
mFName = Label (window,text='Barcode',bg='white')
mEntryname = Entry(window)
# Runs mstore function when pressed (passing the contents of the entry box)
mSave = Button (window,text='Save',bg='white', command = lambda: mstore(mEntryname.get()))
# Runs msearch function when pressed
mSearch = Button (window,text='Search',bg='white', command = lambda: msearch())
# Render Widgets
mTitle.pack()
mDetail.pack()
mFName.pack()
mEntryname.pack()
mSave.pack()
mSearch.pack()
window.mainloop()
I have had an issue with this piece of code from awhile back, it's part of a GCSE mock and I have currently finished the working code (with text only) but I would like to expand it so that it has a nice GUI. I'm getting some issues with updating my sentence variables within the code. Anyone with any suggestions for me please do explain how I can fix it.
#GCSE TASK WITH GUI
import tkinter
from tkinter import *
from tkinter import ttk
var_sentence = ("default")
window = tkinter.Tk()
window.resizable(width=FALSE, height=FALSE)
window.title("Sentence")
window.geometry("400x300")
window.wm_iconbitmap("applicationlogo.ico")
file = open("sentencedata.txt","w")
file = open("sentencedata.txt","r")
def update_sentence():
var_sentence = sentence.get()
def submit():
file.write(sentence)
print ("")
def findword():
messagebox.showinfo("Found!")
print ("Found")
sentencetext = tkinter.Label(window, fg="purple" ,text="Enter Sentence: ")
sentence = tkinter.Entry(window)
sentencebutton = tkinter.Button(text="Submit", fg="red" , command=update_sentence)
findword = tkinter.Label(window, fg="purple" ,text="Enter Word To Find: ")
wordtofind = tkinter.Entry(window)
findwordbutton = tkinter.Button(text="Find!", fg="red" ,command=findword)
usersentence = sentence.get()
usersentence = tkinter.Label(window,text=sentence)
shape = Canvas (bg="grey", cursor="arrow", width="400", height="8")
shape2 = Canvas (bg="grey", cursor="arrow", width="400", height="8")
#Packing & Ordering Moduales
sentencetext.pack()
sentence.pack()
sentencebutton.pack()
shape.pack()
findword.pack()
wordtofind.pack()
findwordbutton.pack()
usersentence.pack()
shape2.pack()
window.mainloop()
If I understand your question right, you want to display the entered text in the usersentence label.
Changing update_sentence() function to what is shown below will archive the desired effect.
def update_sentence():
var_sentence = sentence.get()
usersentence.config(text=var_sentence)
usersentence never gets updated because you only set it once when the program starts this was the problem.
I have created a panedwindow in python tkinter with two panes. It will open fine on it's own but within an if statement it no longer opens
First I had just the code for the panedwindow on it's own but I wanted to use it within another section of code. It won't work within an if statement, it appears to be ignored. Where have I gone wrong?
from tkinter import *
import time
ticketCost=6
username="Rob"
code = input("Enter code: ")
if code == "123":
year=str(time.localtime()[0])
month=str(time.localtime()[1])
day=str(time.localtime()[2])
hour=str(time.localtime()[3])
minute=str(time.localtime()[4])
ticketTime=str(hour+":"+minute)
ticketDate=str(day+"/"+month+"/"+year)
ticketInfo="Bus ticket\nSingle\nDate: "+ticketDate+"\nTime: "+ticketTime+"\nPassengers: "+
...str(int(ticketCost/3))+"\nPrice: "+str(ticketCost)+" credits"
ticketWindow = PanedWindow(orient=VERTICAL,bg="white")
ticketWindow.pack(fill=BOTH, expand=1)
top = Label(ticketWindow, text="top pane")
photo = PhotoImage(file='Coach 1.gif')
top.config(image=photo,bg="white")
top.image = photo
ticketWindow.add(top)
bottom = Label(ticketWindow, text="bottom pane")
bottom.config(text=ticketInfo)
bottom.config(bg="white")
ticketWindow.add(bottom)
print("\nThank you", username)
else:
print("no")
You do not appear to be making a root window, and are not starting the event loop.