I am new to Python and obviously missing something important when working with checkbuttons. Here's the idea behind my program: I select a file manually and then, depending on whether the checkbox is checked or not, trigger either one calculation sequence or another using a button. To achieve this, I wanted to verify the state of the checkbox using the .get() command.
What I've found is that only one sequence is triggered all the time independently of the state of the checkbox. .get() is not updated when I click on the checkbox. What am I doing wrong? Any help will be greatly appreciated.
from tkinter import *
from tkinter import filedialog
import tkinter as tk
master = Tk()
root = tk.Tk()
col_sep = "\t"
col_h_b = [] # field column for background
col_m_b = [] # magnetization column for background
def choose_b_file():
root.fileName_b = filedialog.askopenfilename(filetypes=((".dat files", "*.dat"), ("All files", "*.*")))
with open(root.fileName_b, 'r') as f:
for line in f:
if line[0] != "#":
linedata = [float(line.split(col_sep)[i]) for i in range(len(line.split(col_sep)))]
col_h_b.append(linedata[4])
col_m_b.append(linedata[5])
print(f.name)
offset = BooleanVar()
checkbox = tk.Checkbutton(root, text="offset subtraction", variable=offset,onvalue=1, offvalue=0)
checkbox.pack()
def plot():
if offset.get() == 1:
#some mathematical operations and graph plotting
else:
#other mathematical operations and graph plotting
def close_window():
exit()
b_data = Button(master, text="Background", width=20, command=choose_b_file)
m_minus_b = Button(master, text="Plot", width=5, command=plot)
quit = Button(master, text="Quit", width=5, command=close_window)
b_data.pack()
m_minus_b.pack()
quit.pack()
root.mainloop()
You are mostly messing parents widgets root and master.
Do you need to have a separate window for the checkbox ?
Otherwise the quick fix is to replace root by master in the checkbox creation :
checkbox = tk.Checkbutton(root, text="offset subtraction" ...)
You can also simplify the boolean stuff, the default behavior for the checkbutton is to use 0 and 1, and remove the master or the root, choose only one.
from tkinter import *
from tkinter import filedialog
root = Tk()
col_sep = "\t"
col_h_b = [] # field column for background
col_m_b = [] # magnetization column for background
def choose_b_file():
root.fileName_b = filedialog.askopenfilename(filetypes=((".dat files", "*.dat"), ("All files", "*.*")))
with open(root.fileName_b, 'r') as f:
for line in f:
if line[0] != "#":
linedata = [float(line.split(col_sep)[i]) for i in range(len(line.split(col_sep)))]
col_h_b.append(linedata[4])
col_m_b.append(linedata[5])
print(f.name)
def plot():
if offset.get() == 1:
print('True')
#some mathematical operations and graph plotting
else:
print('False')
#other mathematical operations and graph plotting
def close_window():
exit()
offset = IntVar()
checkbox = Checkbutton(root, text="offset subtraction", variable=offset)
checkbox.pack()
b_data = Button(root, text="Background", width=20, command=choose_b_file)
m_minus_b = Button(root, text="Plot", width=5, command=plot)
quit = Button(root, text="Quit", width=5, command=close_window)
b_data.pack()
m_minus_b.pack()
quit.pack()
root.mainloop()
Related
I want to refresh the the password Label every time the refresh button is pressed.
I tried the .config but it doesn't work.
import random
import string
import tkinter.messagebox
from tkinter import *
def get_all_passwords():
with open('Passwords.txt') as f:
global password_Text
password_Text = f.read()
f.close()
def main_window():
def all_passwords_text():
global password_Text
All_passwords_label.config(text=password_Text)
All_passwords_label = tkinter.Label(
window,
text=password_Text,
foreground="black",
background="white",
width=25,
)
password_label = tkinter.Label(
text=password,
foreground="white",
background="black",
width=20,
)
save_button = tk.Button(
text='save',
width=10,
cursor='hand1',
bg='light gray',
command=lambda:[write_password_to_txt(), All_passwords_label, window.update()]
)
refresh_button = tk.Button(
text='Refresh',
width=20,
bg="white",
fg="black",
command=all_passwords_text
)
All_passwords_label.pack(side='right')
password_label.pack()
safe_entry.pack()
save_button.pack()
refresh_button.pack()
window.mainloop()
random_password()
main_window()
import tkinter as tk # avoid star imports; this can lead to namespace pollution
import tkinter.messagebox
# other imports, etc.
# declare a StringVar to store the label text
password_var = tk.StringVar()
def get_all_passwords():
with open('Passwords.txt') as f:
password_Text = f.read()
password_var.set(password_text) # update 'password_var'
# f.close() - you don't need this when using 'with'
# see link below
"Context Managers and Python's with Statement"
# add a 'textvariable' binding to your label
# the label text will update whenever the variable is set
All_passwords_label = tk.Label(
window,
text=password_Text,
textvariable=password_var # add this!
foreground="black",
background="white",
width=25,
)
Now any time you call get_all_passwords() the label text of All_passwords_label should update.
Note that you no longer need the all_passwords_text function at all, and you don't need to use globals either.
I want to set the answer using the set() method without writing it in the text attribute in the Label and also I want to change the message without displaying the messages over each other.
I want the new message to appear and the one before it to disappear. I tried to use the set() and get() methods but it used to return its default value without using the value in the set() method and I don't know why.
from tkinter import *
from tkinter import messagebox
from PIL import ImageTk,Image
root= Tk()
root.title("Project")
root.geometry('500x600')
root.title('Choose Answer')
var = IntVar()
textt = StringVar()
print(textt.set('Clicked..........'))
def Result():
print(textt.set('You Clicked....................'))
if(var.get() == 1):
print(var.get())
print(textt)
textt.set('You Clicked')
resultText = Label(root, text=textt , fg='white',bg='gray', width=40)
resultText.place(x=100,y=200)
else:
textt.set('You did\'t Click')
resultText = Label(root, text=textt, fg='white',bg='grey', width=40)
resultText.place(x=100,y=200)
checkBox = Checkbutton(root, text='Did you Study Math', variable=var, bg='grey')
checkBox.place(x=50,y=50)
button = Button(root, text='Select', fg='white', bg='grey',font='sans-serif',command=Result)
button.place(x=50,y=100)
root.mainloop()
This should work:
from tkinter import *
root = Tk()
root.title("Project")
root.geometry('500x600')
root.title('Choose Answer')
var = IntVar()
textt = StringVar()
resultText = Label(root, textvariable=textt , fg='white',bg='gray', width=40)
resultText.place(x=100,y=200)
def Result():
print(var.get())
if var.get() == 1:
textt.set('You Clicked')
else:
textt.set('You didn\'t Click')
checkBox = Checkbutton(root, text='Did you Study Math', variable=var, bg='grey')
checkBox.place(x=50,y=50)
button = Button(root, text='Select', fg='white', bg='grey',font='sans-serif',command=Result)
button.place(x=50,y=100)
root.mainloop()
When you create resultText, instead of setting the text argument to textt, you need to set the textvariable argument to text. That way, the text of the variable is automatically changed when you change textt.
I removed all the lines where resultText was recreated and re-placed, and just created it once before defining Result(). Also, I removed from tkinter import messagebox, because you already import it when you call from tkinter import *. Just a note: wildcard imports are discouraged, so try to avoid using them in the future.
So for this larger program I'm making I want it so when a user presses a button it closes the dialog windows and updates all the values the user input. Therefore, I have one button do these two things: update the values and close the program. However, trying to combine these two functions doesn't work as when I use both of them only the update() command is called, not the close command. Either works separately btw. Any way to fix this?
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkinter import *
from tkinter.ttk import *
propDiameterInch = 10.5
propDiameterMetric = propDiameterInch*0.0254
class Counter_program():
def __init__(self):
self.window = tk.Tk()
self.window.title("Test")
style = ttk.Style()
style.configure("BW.TLabel", foreground="black", background="white")
#default unit color
unitColor = "slategrey"
boxWidth = 5
# Create some room around all the internal frames
self.window['padx'] = 5
self.window['pady'] = 5
propeller_frame = ttk.LabelFrame(self.window, text="Propeller", relief=tk.RIDGE)
propeller_frame.grid(row=1, column=1, sticky=tk.E + tk.W + tk.N + tk.S)
#propeller diameter
propellerDiameter_label = ttk.Label(propeller_frame, text="Propeller Diameter")
propellerDiameter_label.grid(row=1, column=1, sticky=tk.W + tk.N +tk.S)
propellerDiameter_Units = ttk.Label(propeller_frame, text="inches",foreground=unitColor)
propellerDiameter_Units.grid(row=1, column=3, sticky=tk.W)
propellerDiameter_entry = ttk.Entry(propeller_frame, width=boxWidth)
propellerDiameter_entry.grid(row=1, column=2, sticky=tk.W, pady=3)
propellerDiameter_entry.insert(tk.END, "10")
#now set all global variables from entries - update function
def update():
global propDiameter
propDiameter = propellerDiameter_entry.get()
# Finish button in the lower right corner
#finish_button = ttk.Button(self.window, text = "Submit Input", command = self.window.destroy)
finish_button = ttk.Button(self.window, text = "Submit Input", command=lambda:[update(),self.window.destroy])
finish_button.grid(row=2, column=2)
# Create the entire GUI program
program = Counter_program()
# Start the GUI event loop
program.window.mainloop()
propDiameter
Since your using lambda, its safe to use () with the functions, so just change finish_button to:
finish_button = ttk.Button(self.window, text = "Submit Input", command=lambda:[update(),self.window.destroy()])
Or you could make a new function that does both of this for you, like:
def both():
update()
self.window.destroy()
finish_button = ttk.Button(self.window, text = "Submit Input", command=both)
TIP:
Also its not recommended to use global with OOP, so I recommend you change your code and use proper "methods" and self with OOP for a better experience.
Here is how I think your class should like:
class Counter_program():
def __init__(self):
self.window = tk.Tk()
self.window.title("Test")
style = ttk.Style()
style.configure("BW.TLabel", foreground="black", background="white")
#default unit color
unitColor = "slategrey"
boxWidth = 5
# Create some room around all the internal frames
self.window['padx'] = 5
self.window['pady'] = 5
self.propeller_frame = ttk.LabelFrame(self.window, text="Propeller", relief=tk.RIDGE)
self.propeller_frame.grid(row=1, column=1, sticky=tk.E + tk.W + tk.N + tk.S)
#propeller diameter
self.propellerDiameter_label = ttk.Label(self.propeller_frame, text="Propeller Diameter")
self.propellerDiameter_label.grid(row=1, column=1, sticky=tk.W + tk.N +tk.S)
self.propellerDiameter_Units = ttk.Label(self.propeller_frame, text="inches",foreground=unitColor)
self.propellerDiameter_Units.grid(row=1, column=3, sticky=tk.W)
self.propellerDiameter_entry = ttk.Entry(self.propeller_frame, width=boxWidth)
self.propellerDiameter_entry.grid(row=1, column=2, sticky=tk.W, pady=3)
self.propellerDiameter_entry.insert(tk.END, "10")
# Finish button in the lower right corner
#finish_button = ttk.Button(self.window, text = "Submit Input", command = self.window.destroy)
self.finish_button = ttk.Button(self.window, text = "Submit Input", command=self.both)
self.finish_button.grid(row=2, column=2)
def update(self):
self.propDiameter = self.propellerDiameter_entry.get()
def both(self):
self.update()
self.window.destroy()
Hope this solved the issue, do let me know if any errors or doubts.
Cheers
I have a problem when I'm trying to autocreate a file when I introduce a route in an Entry. The thing is if the program asks you where to save it, it saves it perfectly, but I would like that my program firstly saves the file if I indicate a previous route in an Entry and ONLY ask me where I want to save it if I don't entry any specific route (which as I said, does it perfectly)
I'm new at Python and don't know what I'm doing wrong, don't know if the problem is that I'm linking wrongly the route in the code and it can't recognize where I'm asking to save it.
When I'm introducing an ID and a route, it gives this error:
PermissionError: [Errno 13] Permission denied: 'Desktop';
and when I'm ONLY introducing an ID (leaving route empty), it gives this error:
FileNotFoundError: [Errno 2] No such file or directory: ''
and what I want is that when I only introduce an ID, I'd like it to ask me where I want to save this file.
from tkinter import *
from tkinter import filedialog
window = Tk()
window.title("app")
idcheck = StringVar()
route = StringVar()
def function():
if route:
**idchecklist = open(route, "w")**
else:
idchecklist = filedialog.asksaveasfile(mode='w',defaultextension=".txt")
idchecklist.write(idcheck.get())
idchecklist.close()
Label(window, text="ID").grid(padx=10 ,pady=10, row=0, column=0)
Entry(window, textvariable=idcheck).grid(padx=5, row=0, column=1, sticky=E+W)
Label(window, text="Saving route").grid(padx=10 ,pady=10, row=1, column=0)
Entry(window, textvariable=route, width=50).grid(padx=5, row=1, column=1)#, sticky=E+W)
Button(window, text="Generate", command=function).grid(padx=10,pady=10,row=2,column=0,columnspan=2,sticky=E+W)
window.mainloop()
To finish, is there any way to save the route Entry I introduced just in case that I want to use the program more than once and not having to introduce this entry every time? It would be great.
Thank you so much.
ps. Sorry if I did some writing mistakes.
You shouldn't use route, but route.get() in your code.
route in your case is just a container for a string, a StringVar object, so the if considers it being True. route.get(), on the other hand, is a string, which is retrieved from the Entry. So, the final code could look similar to this:
from tkinter import *
from tkinter import filedialog
window = Tk()
window.title("app")
idcheck = StringVar()
route = StringVar()
def function():
if route.get():
idchecklist = open(route.get(), "w")
else:
idchecklist = filedialog.asksaveasfile(mode='w',defaultextension=".txt")
idchecklist.write(idcheck.get())
idchecklist.close()
Label(window, text="ID").grid(padx=10 ,pady=10, row=0, column=0)
Entry(window, textvariable=idcheck).grid(padx=5, row=0, column=1, sticky=E+W)
Label(window, text="Saving route").grid(padx=10 ,pady=10, row=1, column=0)
Entry(window, textvariable=route, width=50).grid(padx=5, row=1, column=1)#, sticky=E+W)
Button(window, text="Generate", command=function).grid(padx=10,pady=10,row=2,column=0,columnspan=2,sticky=E+W)
window.mainloop()
If I'm getting you correct (see comments), here's even better version:
from tkinter import *
from tkinter import filedialog
import os
# create window
window = Tk()
window.title("app")
# create some containers for inputs
idcheck = StringVar()
route = StringVar()
# create input entrys
Label(window, text="ID").grid(padx=10 ,pady=10, row=0, column=0)
Entry(window, textvariable=idcheck).grid(padx=5, row=0, column=1, sticky=E+W)
Label(window, text="Saving route").grid(padx=10 ,pady=10, row=1, column=0)
Entry(window, textvariable=route, width=50).grid(padx=5, row=1, column=1)#, sticky=E+W)
# Update function
def function():
if route.get(): # if route is not '' then use it else ask for it
idcheckpath = route.get()
else:
idcheckpath = filedialog.askdirectory()
route.set(idcheckpath)
# create and fill the file
idchecklist = open(idcheckpath+os.sep+idcheck.get()+'.txt', 'w')
idchecklist.write(idcheck.get())
idchecklist.close()
# generate new id:
alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
# get the old id and split it into a number and a string
old_id = idcheck.get()
if len(old_id) != 8:
old_id='000000AA'
letters = old_id[6:]
number = int(old_id[:6])
# check if the last letter is Z
if letters[1] == alphabet[-1]:
if letters[0] == alphabet[-1]: # if both letters are Z, update the number
letters = 'AA'
number += 1
else:
letters = alphabet[1+alphabet.find(letters[0])]+'A' # if only the last letter is Z, update both letters
else:
letters = letters[0]+alphabet[1+alphabet.find(letters[1])] # update the last letter
idcheck.set(str(number).zfill(6)+letters) # save a new id
Button(window, text="Generate", command=function).grid(padx=10,pady=10,row=2,column=0,columnspan=2,sticky=E+W)
window.mainloop()
I am writing a simple bulk file utility. I have two listboxes in the GUI. Listbox1 contains a list of files that exist in whichever directory the user selects. The user can then add selected items in listbox1, to listbox2. Currently this allows duplicate items to be added. I would like to figure out how to check if selected items already exist in listbox2, and only add items that aren't already present.
Here is my code:
from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog, tkMessageBox
import os, sys
class FileZap():
def __init__(self, root):
def getDir():
dir = tkFileDialog.askdirectory(initialdir="C:/")
self.user1.delete(0,END)
self.user1.insert(0,dir)
files = (file for file in os.listdir(dir)
if os.path.isfile(os.path.join(dir, file)))
for file in files:
self.listbox1.insert(0,file)
def selectAdd():
selection1 = self.listbox1.curselection()
for i in selection1:
selectedFiles = self.listbox1.get(i)
self.listbox2.insert(0, selectedFiles)
root.title("Test_App 1.0")
root.geometry("860x450")
self.listbox1 = Listbox(root, width=50, selectmode="multiple")
self.listbox1.grid(row=2, column=2)
self.scrollbar = Scrollbar(orient=VERTICAL, command=self.listbox1.yview)
self.listbox1.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.grid(row=2, column=3, sticky="ns")
self.listbox2 = Listbox(root, width=50)
self.listbox2.grid(row=2, column=4)
self.label1 = Label(root, text="Select a folder: ")
self.label1.grid(row=1, column=1)
self.user1 = Entry(root, width="50")
self.user1.grid(row=1, column=2)
self.browse = Button(root, text="Browse", command=getDir)
self.browse.grid(row=1, column=3)
self.button2 = Button(root, text="Add to Selection", command=selectAdd)
self.button2.grid(row=3, column=3)
self.quit = Button(root, text="Exit", command=root.quit)
self.quit.grid(row=8, column=4)
root = Tkinter.Tk()
file_zap = FileZap(root)
root.mainloop()
In the above code the function selectAdd() performs the item manipulation. I was hoping to do this by adding another for loop within the function that returns the values in listbox2, and adding items if not in listbox2. However I can only seem to return selected values using .get, I can't figure out how to select all values. Also I'm not sure that this is even the best way to do this. Any help would be much appreciated!
How about just getting all values currently in the second listbox with listbox2.get(0,END) and if there are no duplicates add the selectedFiles:
def selectAdd():
selection1 = self.listbox1.curselection()
for i in selection1:
selectedFiles = self.listbox1.get(i)
list2files = self.listbox2.get(0, END)
if selectedFiles not in list2files:
self.listbox2.insert(0, selectedFiles)