Python crashes upon destroying Tkinter window - python

I'm a student in software development and I'm developing an application (my first application!) in Python for learning purposes.
It works fairly well, and I got almost all of the features working that I want to work.
A short explanation of the program: It's an administrative program to log the members of a sports club. So it has basic functions like adding members, listing members, etc.
For it to be complete, it also needs a function to delete a member. This has always worked fine, but I rarely used the function.
Now after I modified a ttk.Treeview() object so it now sorts by last name, I added a new member to see if it sorts like it should. It did!
Now I wanted to delete that member, but for some reason, it no longer works.
It crashes Python. It doesn't just crash the application, no error, just plain "Pythonw.exe has stopped working".
Here's all the code that belongs to that function:
def dellid(zeid, addwindow):
winsound.PlaySound("SystemHand", winsound.SND_ASYNC)
usure = tkinter.Tk()
print('usure window created')
usure.title('Lid verwijderen')
usure.geometry('{}x{}'.format('300', '150'))
usure.iconbitmap(default='programdata\\icon.ico')
usure.attributes("-topmost", True)
addwindow.grab_set()
#logo2 = PhotoImage(file="warning.png")
#logolabel = tkinter.Label(usure, image = logo2)
#logolabel.grid(row01, columnspan = 2)
usure.columnconfigure(0, weight = 1)
usure.columnconfigure(1, weight = 2)
label01 = tkinter.Label(usure, text = '''
Weet U zeker dat U dit lid wilt verwijderen?
Deze actie kan niet ongedaan worden gemaakt!''').grid(row = 1, columnspan = 2)
emptyrow = tkinter.Label(usure, text = ' ').grid(row = 2, columnspan = 2)
jaknop = ttk.Button(usure, text = 'Ja', command = lambda: delforsure(zeid, usure, addwindow)).grid(row = 3, column = 0, sticky = 'E')
neeknop = ttk.Button(usure, text = 'Nee', command = lambda: nodell(addwindow, usure)).grid(row = 3, column = 1, sticky = 'S')
def nodell(addwindow, usure):
addwindow.grab_release()
usure.destroy()
def delforsure(zeid, usure, addwindow):
#addwindow.grab_release()
addwindow.destroy()
print('addwindow destroyed')
usure.destroy()
print('usure destroyed')
conn = sqlite3.connect('test.db')
c = conn.cursor()
opendb = []
opendb.append(zeid)
print(zeid)
print(opendb)
c.execute("DELETE FROM leden WHERE ids = ?",opendb)
print('c.execute')
conn.commit()
print('c.commit')
#usure.destroy()
done = tkinter.Tk()
done.title('Lid verwijdert')
done.geometry('{}x{}'.format('300', '150'))
done.iconbitmap(default='programdata\\icon.ico')
label01 = tkinter.Label(done, text = '''
Lid verwijdert
''')
label01.pack()
done.update()
time.sleep(2)
on_return(done)
The on_return function closes the said window and reopens the main menu.
Now in delforsure(zeid, usure, addwindow) it locks up on the line usure.destroy()
It doesn't print the line 'usure destroyed' anymore, that I put there to see where it locks up.
It doesn't give any error, Python itself just crashes.
If I move
usure.destroy()
print('usure destroyed')
under on_return(done), all the way at the bottom, it does close the window and return to the main menu, but the main menu will be drawn with graphical distortions and soon still crashes afterwards.
I really don't understand what is going on.
Can anybody help me trace the issue please?

It looks like you are making a yes / no modal window. Is there a reason you don't want to use the version that is built into tkinter?
from tkinter import messagebox
def dellid(zeid, addwindow):
answer = messagebox.askyesno(
'Lid verwijderen',
'Weet U zeker dat U dit lid wilt verwijderen?\n'
'Deze actie kan niet ongedaan worden gemaakt!')
if answer:
addwindow.destroy()
print('addwindow destroyed')

Related

How to retain variable information in Tkinter?

I am trying to convert a text adventure originally made in vanilla Python to a Tkinter format. My attempt at this was to create a dictionary that would be updated whenever information was entered, but the dictionary information isn't saving and seems to revert back to an empty dict every time.
How would I do this ? Apologies if the question is unclear, I am very new to Tkinter and have been struggling with this for a long time.
Here is my code, all it needs to do is figure out if the player wants to activate the tutorial :
from tkinter import *
# Storage
game_text = {}
cmd = {}
root = Tk()
# Configuration
root.geometry ("1000x1000")
root.title("A New Dawn")
icon = PhotoImage(file = "C:/Users/gwynn/Desktop/wcnd_icon.png")
root.iconphoto(False, icon)
root.configure(bg="#006644")
# Parsers
def parse(tag, line):
game_text[tag] = Text(root, width = 200, height = 1)
game_text[tag].insert(INSERT, line)
game_text[tag].pack()
game_text[tag].tag_add(tag, '1.0', 'end')
game_text[tag].tag_config(tag, background = "#006644", foreground = "#8cd98c")
def cmd_parse(cmd_box):
cmd['cmd'] = cmd_box.widget.get()
cmd['cmd'] = cmd['cmd'].lower()
print(cmd['cmd'])
# The Game
parse('tutorial', "Welcome to WC : A New Dawn ! Before we begin - would you like to activate the tutorial ? [Y/N]")
cmd_box = Entry(root, background = '#096', foreground = "#b3e6b3", width = 200, border = 3)
cmd_box.pack()
cmd_box.bind("<Return>", cmd_parse)
print(cmd)
if 'cmd' in list(cmd):
if cmd['cmd'] == "y":
parse('tutorial_y', "Excellent ! The tutorial has been activated.")
elif cmd['cmd'] == "n":
parse('tutorial_n', "Excellent ! The tutorial has been deactivated.")
root.mainloop()
You are trying to manage cmd conditions before the user has even had the chance to type. You have to move your conditions (or call a function of your conditions) after you have actually retrieved the typed data.
def cmd_parse(event):
cmd = event.widget.get().lower()
if cmd == "y":
parse('tutorial_y', "Excellent ! The tutorial has been activated.")
elif cmd == "n":
parse('tutorial_n', "Excellent ! The tutorial has been deactivated.")

Saving and searching data with Tkinter entry boxes

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()

raw_input stops GUI from appearing

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

Python GTK - refreshing a table/scrollwindow

In this simple program I'm drawing a window, adding a search box, getting a search term for the user, looking that up in a postgreSQL DB and displaying the reults. It works up to a point - when the user enters a second query.
I have tried in two different ways but each way gives a different problem. In the first way (lines 32-35 http://pastebin.com/q5bnLxaB) I'm creating the output window in the main and passing that to the search function. It crashes with gtk_scrolled_window_add: assertion 'child_widget == NULL' failed. I think because I'm adding the tree to the window when it has already been done. To fix this, I would need to reset the window somehow.
In the second way (lines 56-58) I have added the output window only in the search function so it no longer has this crashing issue. However, the window itself does not update with the results of a second or subsequent search.
Which, if either, of these methods seems the most sensible? I also need to consider that the next step is adding a clickable button beside each search term which will display extended data for each returned result.
BTW, in both cases the output window does not appear until a search is entered. It doesn't hinder functionality but it strange to me.
#!/usr/bin/python
from gi.repository import Gtk
from gi.repository.GdkPixbuf import PixbufLoader
import urllib2
import psycopg2
import sys
class NotebookWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Rugby Database")
#Create Application Window
self.set_border_width(10)
self.set_default_size(800, 600)
self.set_position(Gtk.WindowPosition.CENTER)
#Add external container (box)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
self.add(vbox)
#Add tabbed window
nbook = Gtk.Notebook()
vbox.pack_start(nbook, True, True, 0)
nbook.show()
#Add Main tab
label = Gtk.Label()
label.set_markup("<b><big>Main</big></b>")
table = Gtk.Table(rows=40, columns=10)
#Add Results field
#results_box = Gtk.ScrolledWindow()
#results_box.set_vexpand(True)
#table.attach(results_box, 0, 1, 1, 39, xpadding=5, ypadding=5)
#Add Search box
entry = Gtk.Entry()
entry.set_property("secondary-icon-stock", Gtk.STOCK_FIND)
entry.connect("icon-press", self.on_search_button)
#entry.connect("activate", self.on_search_enter, results_box)
entry.connect("activate", self.on_search_enter, table)
table.attach(entry, 0, 1, 0, 1, xpadding=5)
nbook.append_page(table, label)
def on_search_button(self, entry, icon, event):
search = entry.get_text()
print("Search for " + search)
def on_search_enter(self, entry, table): #changed from results_box
store = Gtk.ListStore(str, str, str)
tree = Gtk.TreeView(store)
##
results_box = Gtk.ScrolledWindow()
results_box.set_vexpand(True)
table.attach(results_box, 0, 1, 1, 39, xpadding=5, ypadding=5)
##
search = entry.get_text()
search = search.replace("'","''") #deal with apostrophes
entry.set_text("")
print("Search for " + search)
result = self.lookup_player(search)
print result
if len(result) > 0:
for i in range(0, len(result)):
store.append([result[i][0],result[i][1],str(result[i][4])])
print result[i][0],result[i][1],result[i][2],result[i][3],result[i][4],result[i][5],result[i][6],result[i][7],result[i][8]
else:
print "No players found"
#Add column for last name
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Last Name")
column.pack_start(renderer, True)
column.add_attribute(renderer, "text", 0)
tree.append_column(column)
#Add column for first name
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("First Name")
column.pack_start(renderer, True)
column.add_attribute(renderer, "text", 1)
tree.append_column(column)
#Add column for icon
renderer = Gtk.CellRendererPixbuf()
column = Gtk.TreeViewColumn("Show")
column.pack_start(renderer, True)
column.add_attribute(renderer, "stock-id", 2)
tree.append_column(column)
results_box.add(tree)
table.show_all()
tree.show_all()
def on_click_edit(self, button):
print("Editing Player")
def lookup_player(self, pstring):
try:
con = psycopg2.connect(database='Rugby', user='postgres', password = '1234')
cur = con.cursor()
search = "select pl.lastname, pl.firstname, pl.height, pl.weight, to_char(pl.dob, 'DD/MM/YYYY'), cl.name, pl.injury_id, to_char(pl.suspendeduntil, 'DD/MM/YYYY'), pl.photo from player pl inner join club cl on cl.id = pl.currentclub_id where firstname ilike '%s' or lastname ilike '%s'" % (pstring, pstring)
cur.execute(search)
result = cur.fetchall()
return result
except psycopg2.DatabaseError, e:
print 'Error %s' % e
sys.exit(1)
finally:
if con:
con.close()
win = NotebookWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
Note This is a follow-up question to
Python (GTK) : Can someone explain the difference between TreeStore, Listmodel and all the rest?
as the original query has been answered and the scope has thus changed (BTW massive thanks to everyone who helped with that!)
You should do everything you can in __init__(). This includes creating the store (as an instance variable so you can use it in the search handler), creating all widgets (ScrolledWindow and TreeView) and also adding the columns to the treeview.
In the search handler you should only call clear() on the ListStore (to remove any old results) and then append new results to the store.

Tkinter panedwindow not opening

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.

Categories

Resources