So I'm writing a tKinter GUI for this project I'm working on, and I've run into a problem with one of my button methods. In the method for this button, the code prints a list of coordinates to a text file. It works great the first time, but if I press the button again before closing the root tKinter window, it doesn't truncate the file - it just adds the next set off coordinates to the end. Here is my code:
#print to file
reportFile = open('gridCenters.txt','w')
reportFile.write('In movement order:\n')
for x in xrange(0,len(coordinates)):
reportFile.write('%s\n' % str(coordinates[x]))
reportFile.close()
Now, this is within a button method, so to my understanding it should execute every time the button is pressed. The really strange part is that in the output after pressing the button again, it prints JUST the loop values. For some reason it skips over the "In movement order" part.
It won't let me upload images but here's an idea of how it looks:
In movement order:
(0,1)
(0,2.5)
(0.3.5)
(0,4.5)
Then if I press the button again before closing the root window:
In movement order:
(0,1)
(0,2.5)
(0.3.5)
(0,4.5)
(0,1)
(0,2.5)
(0.3.5)
(0,4.5)
(Those blocks aren't code, just text output)
I'm just really confused. My understanding is that every time I press the button, it should overwrite the file, then close it.
Thanks for the help.
In when your button re-opens the file it doesn't print the "In movement order:" a second time.
This looks like you aren't clearing your variable coordinates. You should make sure that you are starting with a clean variable before adding to it to get the data you are looking for.
You could reset it after the file closes unless you need to retain it for use un the GUI at that point.
I am not shure why it doesnt works for you but here is what i had wrote.
from Tkinter import *
def wtf(coordinates):
reportFile = open('gridCenters.txt','w')
reportFile.write('In movement order:\n')
for x in xrange(0,len(coordinates)):
reportFile.write('%s\n' % str(coordinates[x]))
reportFile.close()
def main():
coordinates = [(0,1),(0,2.5),(0,3.5),(0,4.5)]
root = Tk()
btn = Button(root,text='click me',command = lambda:wtf(coordinates))
btn.pack()
root.mainloop()
main()
in wtf function if 'w' is flag (reportFile = open('gridCenters.txt','w')) the gridCenters.txt is rewritten every time,but if the flag is 'a' instead of 'w' than result is just appending one below another.I hope this is what u want.
from Tkinter import *
coords = [1, 2, 3, 4, 5]
def write():
global coords
fileName = "testButton.txt"
fileObj = open(fileName, 'w')
fileObj.write("Some words\n")
for i in xrange(0, len(coords)):
fileObj.write("%d\n" %coords[i])
fileObj.close()
for i in range(5):
coords[i] += 1
root = Tk()
f = Frame(root).pack()
b = Button(root, text = "OK", command = write).pack(side = LEFT)
root.mainloop()
This works for me, overwriting the file every time and the values are updated every time as well. Something must be going on elsewhere in your program.
Related
I have a button which inserts text into a 'scrolltext' box when it is clicked.
I want to delay parts of the text being inserted into the text box. As in, one line of text is insert, there a 3 second delay, the next line of text is inserted and so on...
The I attempted using 'time' to make this work. However, this just delays all the text being inserted by the combined value and then all the text is inserted at once. Is there a way to make it work how I wish? And is it possible to delay it, so that each letter is inserted one at a time?
This is a much simplified version of what I've tried:
import tkinter as tk
from tkinter import *
from tkinter import scrolledtext
import time
# This is the GUI
trialGUI = Tk()
trialGUI.geometry('710x320')
trialGUI.title("Test GUI")
#This is the text that should be inserted when the button is pressed
def insertText():
trialBox.insert(tk.INSERT, 'This line should be inserted first.\n')
time.sleep(1)
trialBox.insert(tk.INSERT, 'This line should be inserted after a 1 second delay.\n')
time.sleep(3)
trialBox.insert(tk.INSERT, 'This line should be inserted after a 3 second delay.\n')
time.sleep(3)
trialBox.insert(tk.INSERT, 'This line should be inserted after a 3 second delay.\n')
#This is the scrolling text box
trialBox = scrolledtext.ScrolledText(trialGUI, wrap = tk.WORD, width = 42, height = 10, font=(14))
trialBox.grid(row = 0, column = 0, columnspan = 4, pady = 3)
#This button runs the code to insert the text
trialButton = Button(trialGUI, text = "Run Code", command = insertText)
trialButton.grid(row = 1)
trialGUI.mainloop()
Here's a solution using the .after() method:
def insertText():
global previousDelay
previousDelay = 0
delayedInsert('This line should be inserted first.\n',0)
delayedInsert('This line should be inserted after a 1 second delay.\n',1)
delayedInsert('This line should be inserted after a 3 second delay.\n',3)
delayedInsert('This line should be inserted after a 3 second delay.\n',3)
def delayedInsert(text, delay):
global previousDelay
trialGUI.after((delay + previousDelay) * 1000, lambda: trialBox.insert(tk.INSERT,text))
previousDelay += delay
It uses a delayedInsert function which takes the text and delay in seconds and the global variable previousDelay to make the delays appear asynchronous (they are still happening at the same time but the delays are changed to make it appear like they are not). If the delays were not changed, each delay would start at the same time, not one after the other. The delayedInsert function waits for the delay specified plus the previous delay before inserting the text. This gives the same effect as time.sleep() but it works with Tkinter.
I'm trying to see if there's a way to type a number between 1 and 4 into an entry box, then go to the next entry box (with the number entered into the box; the code below skips to the next entry without entering anything)
I'm creating a program that will take item-level data entry to be computed into different subscales. I have that part working in different code, but would prefer not to have to hit tab in between each text entry box since there will be a lot of them.
Basic code:
from tkinter import *
master = Tk()
root_menu = Menu(master)
master.config(menu = root_menu)
def nextentrybox(event):
event.widget.tk_focusNext().focus()
return('break')
Label(master, text='Q1',font=("Arial",8)).grid(row=0,column=0,sticky=E)
Q1=Entry(master, textvariable=StringVar)
Q1.grid(row=0,column=1)
Q1.bind('1',nextentrybox)
Q1.bind('2',nextentrybox)
Q1.bind('3',nextentrybox)
Q1.bind('4',nextentrybox)
Label(master, text='Q2',font=("Arial",8)).grid(row=1,column=0,sticky=E)
Q2=Entry(master, textvariable=StringVar)
Q2.grid(row=1,column=1)
Q2.bind('1',nextentrybox)
Q2.bind('2',nextentrybox)
Q2.bind('3',nextentrybox)
Q2.bind('4',nextentrybox)
### etc for rest of questions
### Scale sums, t-score lookups, and report generator to go here
file_menu = Menu(root_menu)
root_menu.add_cascade(label = "File", menu = file_menu)
file_menu.add_separator()
file_menu.add_command(label = "Quit", command = master.destroy)
mainloop()
Thanks for any help or pointers!
The simplest solution is to enter the event keysym before proceeding to the next field.
In the following example, notice how I added a call to event.widget.insert before moving the focus:
def nextentrybox(event):
event.widget.insert("end", event.keysym)
event.widget.tk_focusNext().focus()
return('break')
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 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
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.