python3 tkinter gui not responding - python

Hi I am new to programming and I apologize if this is an obvious mistake. I am writing a gui on tkinter using python 3.5 on Mac OsX El Capitan. Here is the code so far:
from tkinter import *
from tkinter import ttk
class GUI(object):
def __init__(self, master):
master.title("Title")
master.resizable(False, False)
self.frame1 = ttk.Frame(master)
self.frame1.pack()
ttk.Label(text="Organism").grid(row=1, column=0)
self.organism_picker = ttk.Combobox(self.frame1, values=("Drosophila melanogaster",
"Danio rerio",
"Caenorhabditis elegans",
"Rattus norvegicus",
"Mus musculus",
"Homo sapiens"))
self.organism_picker.grid(row=2, column=0)
ttk.Label(text="Core gene symbol:").grid(row=3, column=0)
self.core = ttk.Entry(self.frame1)
self.core.grid(row=4, column=0)
root = Tk()
gui = GUI(root)
root.mainloop()
When I run this the program enters the main loop, but the gui window never appears and the launcher is not reponding.
I tried to reinstall python 3, installed ActiveTcl, tried using ActivePython instead. Nut none of it worked.
Thank you all in advance for your answers.

You should not use pack() and grid() as this will generate a geometry manager conflict as pointed out in this error:
_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack
try changing:
self.frame1.pack()
to:
self.frame1.grid()
In this case I would suggest using pack overall, since this is a fairly simple layout. please refer to this guide:
When to use the Pack Manager
Compared to the grid manager, the pack manager is somewhat limited,
but it’s much easier to use in a few, but quite common situations:
Put a widget inside a frame (or any other container widget), and have
it fill the entire frame Place a number of widgets on top of each
other Place a number of widgets side by side
AND FINALLY:
Note: Don’t mix grid and pack in the same master window. Tkinter will
happily spend the rest of your lifetime trying to negotiate a solution
that both managers are happy with. Instead of waiting, kill the
application, and take another look at your code. A common mistake is
to use the wrong parent for some of the widgets.

The only problem with your code is that you forgot to attach the two labels to the the main widget self.frame1.
To fix that, modify them as follow:
#Attach the 2 labels to self.frame1
ttk.Label(self.frame1,text="Organism").grid(row=1, column=0)
ttk.Label(self.frame1,text="Core gene symbol:").grid(row=3, column=0)
Demo
After doing that, you will get this:

Related

RPI Issue with entry boxes tkinter?

Struggling to get a simple form to work in a tkinter instance. Is
there a known issue with not being able to click on tk.Entry boxes?
I'll take the key parts of the code out to see if anyone can spot
something i'm doing wrong?
class CreateWindow():
def __init__(self):
self.root = tk.Tk()
self.root.overrideredirect(True)
***Then I do a whole load of importing images, setting background and other stuff ***
self.messageText = tk.StringVar()
self.MessageBox = tk.Entry(self.root, textvariable = self.messageText)
self.MessageBox.place(x=100, y=100)
self.root.mainloop()
This code is then called from if main = name
Does anyone see anything I'm doing wrong??
The reason why I cannot click on the entry box is that root.overrideredirect(True) prevents the entry box from getting focus. I have listed a new question RPI Tkinter Window, I want to use a command like overrideredirect and maintain entry box functionality to focus on how to work around this.

Adding Tix Widget to Tkinter Container

I'm working with Tkinter in Python 2.7 on Windows 7, and found the need to create a popup box with a tree-style list of checkboxes. I could not find this in Tkinter, or ttk. I did, however, find it in Tix in the CheckList widget. I got a working standalone example using Tix, but I cannot figure out how to add my Tix.CheckList to my ttk.Frame that controls my main program.
Surely I am not forced to use Tix framework from the ground up?
import Tix
import pandas as pd
import Tkinter as tk
class TreeCheckList(object):
def __init__(self, root):
self.root = root
self.cl = Tix.CheckList(self.root)
self.cl.pack(fill=Tix.BOTH, expand=Tix.YES)
self.cl.hlist.config(bg='white', bd=0, selectmode='none', selectbackground='white', selectforeground='black', drawbranch=True, pady=5)
self.cl.hlist.add('ALL', text='All Messages')
self.cl.hlist.add('ALL.First', text='First')
self.cl.setstatus('ALL.First', "off")
self.cl.hlist.add('ALL.Second', text='Second')
self.cl.setstatus('ALL.Second', "off")
self.cl.autosetmode()
def main():
root = Tix.Tk()
top = Tix.Toplevel(root)
checklist = TreeCheckList(top)
root.update()
top.tkraise()
root.mainloop()
if __name__ == '__main__':
main()
The above code works in a standalone program using all Tix widgets. However, when I try to implement this into my larger program, I receive a TclError: invalid command name "tixCheckList"
To simulate this in the standalone, I changed the lines:
root = Tix.Tk()
top = Tix.Toplevel(root)
to
root = tk.Tk()
top = tk.Toplevel(root)
I was hoping I could just implement a Tix.Toplevel, placing it on a tk.Tk() root, but same issue.
Am I only allowed to use Tix frames when using a Tix widget, or am I misunderstanding something? If anyone has good Tix documentation, I would LOVE whatever I can get. It seems good docs on it are few and far between. Or is this same functionality included in ttk and I've just overlooked it? It seems to be one of the only things left out.
I have just learned that apparently only root needs to be a Tix class. Since Tk, and therefore ttk, classes appear to be added to the Tix root just fine (since most of them extend the Tkinter classes anyway), this appears to be a "fix". So my problem may have been solved by changing just
root = tk.Tk()
to
root = Tix.Tk()
This did require that I pull Tix into a part of my program I wasn't wanting for encapsulation purposes, but I guess there's no other way.

Tkinter add Widgets (a Button) to a new second Frame

I created a Frame, gave it a menubar. Works just fine. The purpose of the entry in the menubar is to open a new frame, in which u can change some settings. The creation of the new Window works also. However I can't create widgets on the new created window. I tried it with a Button and got a
TclError: can't invoke "button" command: application has been destroyed
I tried to google it and found Cannot invoke button command: application has been destroyed which didn't quite helped me.
Further I found a solution were u have to create a parent class (which inherrits from Frame) and than create all other Frames within it, but on the first view it looked pretty complicated. Especially because the creation of the second window seems to work in the first place.
I know this is probably a really basic question, so thanks in advance for your time
def perfSettings():
perfFrame = Tk(className=" Performanz Einstellungen")
perfFrame.configure(bg='#F2F2F2')
perfFrame.geometry("300x300")
perfFrame.mainloop()
btn = Button(master=perfFrame, text='Speichern', command=myPerfSettingValue.getValues, width=37)
btn.pack()
# Button(perfFrame, text='Abbrechen', command=perfFrame.destroy, width=37).grid(row=0 ,column=1 )
class perfSettingsValue:
def __init__(self):
self.bvhSteps = 0
def getValues(self):
pass
#Hauptfenster
root = Tk(className="BoneMapping & SkeletonEstimation")
root.configure(bg='#F2F2F2')
root.geometry("1300x600")
myPerfSettingValue = perfSettingsValue()
menubar = Menu(root)
sdmenu = Menu(menubar, tearoff=0)
sdmenu.add_command(label="Performanz", command=perfSettings)
menubar.add_cascade(label='Einstellungen',menu=sdmenu)
root.config(menu=menubar)
The key problem here is that you are trying to add a button after starting the mainloop which effectively blocks the execution of the program. The error you are getting is because the line that adds the button gets executed after the window has been closed.
Your problem will be solved if you modify your function like this:
def perfSettings():
perfFrame = Tk(className=" Performanz Einstellungen")
perfFrame.configure(bg='#F2F2F2')
perfFrame.geometry("300x300")
btn = Button(master=perfFrame, text='Speichern', command=myPerfSettingValue.getValues, width=37)
btn.pack()
perfFrame.mainloop()
This is not the only problem though. Instead of creating a new instance of Tk, you should create a new Toplevel instance, which will, in your case, act just as a Tk instance, but have a lot less tendency to cause trouble.
Finally, you should consider reading on the object oriented approach to designing tkinter applications. There are far too many variants of that to be appropriately elaborated here but I certainly recommend you take the effort to learn to use one of them. It will make your code more comprehensible and maintainable. My usual approach is to create a class that inherits from Toplevel or Tk for every type of window I am going to use.

tkinter's .pack_propagate() method

I am experimenting with Tkinter, as I was trying to figure out is there a way to set the tkinter's window size without using canvas. I came upon this how to set frame size question on SO's Question & Answer. So I went ahead and test it by writing a very small program to display a text label. But I found out it is "missing", or disappear when I use frame.pack_propagate(0)
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, width=400, height=400)
# Does not work at the moment, textBox is missing
# frame.pack_propagate(0)
frame.pack()
textBox = tk.Label(frame, text="(x,y): ")
textBox.pack()
root.mainloop()
So my question is, can you explain why my textBox (Label) is not appearing when I use the frame.pack_propagate(0) instead of frame.pack() method? And secondly, is there a way to set the window size without using a canvas? I want to know because I am writing a series of small programs to teach my friend about tkinter, before introducing canvas to him. It would be nice if the window size are all the same across my tkinter samples. And I am just wondering as well (curious). Thank you very much.
I am using python 3.2.2 on MAC OS 10.5.8.
pack_propagate only sets a flag, it doesn't cause the frame to be placed in the widget. It is not a substitute for calling pack.
In other words you must do this:
# put the frame in its parent
frame.pack()
# tell frame not to let its children control its size
frame.pack_propagate(0)
# put the textbox in the frame
textBox.pack()
To answer your second question: Yeah, there is a way.
tkinters Tk do have the Tk.geometry function. When you just call it without arguments, you will get the current geometry in form of 'widthxheight+x+y', so for example (on Windows 10) '200x200+26+26' when you create your first Tk window. Using that format you can resize the Tk by, e.g., writing: root.geometry('400x500+60+60') to set the width to 400, the height to 500 and place it at the coordinates (60|60).
This works for Tk alswell as for Toplevel. But Toplevel also takes the arguments height and width when initialized or configured. If you want them to keep their size when packing something inside just use root.pack_propagate(False) on them.
By the way there is something similar for the grid manager: root.grid_propagate(False)

Notebook widget in Tkinter

Having played around a little with both Tkinter and wxPython, I like Tkinter much better in terms of how clean my source code looks. However, it doesn't seem to have as many features; in particular it doesn't have tabs (as in, the tabs at the top of a Firefox window).
A little Googling on the subject offers a few suggestions. There's a cookbook entry with a class allowing you to use tabs, but it's very primitive. There's also Python megawidgets on SourceForge, although this seems very old and gave me errors during installation.
Does anyone have experience making tabbed GUIs in Tkinter? What did you use? Or is it simply the case that anyone who needs more powerful windowing components has to use wxPython?
On recent Python (> 2.7) versions, you can use the ttk module, which provides access to the Tk themed widget set, which has been introduced in Tk 8.5.
Here's how you import ttk in Python 2:
import ttk
help(ttk.Notebook)
In Python 3, the ttk module comes with the standard distributions as a submodule of tkinter.
Here's a simple working example based on an example from the TkDocs website:
from tkinter import ttk
import tkinter as tk
from tkinter.scrolledtext import ScrolledText
def demo():
root = tk.Tk()
root.title("ttk.Notebook")
nb = ttk.Notebook(root)
# adding Frames as pages for the ttk.Notebook
# first page, which would get widgets gridded into it
page1 = ttk.Frame(nb)
# second page
page2 = ttk.Frame(nb)
text = ScrolledText(page2)
text.pack(expand=1, fill="both")
nb.add(page1, text='One')
nb.add(page2, text='Two')
nb.pack(expand=1, fill="both")
root.mainloop()
if __name__ == "__main__":
demo()
Another alternative is to use the NoteBook widget from the tkinter.tix library. To use tkinter.tix, you must have the Tix widgets installed, usually alongside your installation of the Tk widgets. To test your installation, try the following:
from tkinter import tix
root = tix.Tk()
root.tk.eval('package require Tix')
For more info, check out this webpage on the PSF website.
Note that tix is pretty old and not well-supported, so your best choice might be to go for ttk.Notebook.
If anyone still looking, I have got this working as Tab in tkinter. Play around with the code to make it function the way you want (for example, you can add button to add a new tab):
from tkinter import *
class Tabs(Frame):
"""Tabs for testgen output"""
def __init__(self, parent):
super(Tabs, self).__init__()
self.parent = parent
self.columnconfigure(10, weight=1)
self.rowconfigure(3, weight=1)
self.curtab = None
self.tabs = {}
self.addTab()
self.pack(fill=BOTH, expand=1, padx=5, pady=5)
def addTab(self):
tabslen = len(self.tabs)
if tabslen < 10:
tab = {}
btn = Button(self, text="Tab "+str(tabslen), command=lambda: self.raiseTab(tabslen))
btn.grid(row=0, column=tabslen, sticky=W+E)
textbox = Text(self.parent)
textbox.grid(row=1, column=0, columnspan=10, rowspan=2, sticky=W+E+N+S, in_=self)
# Y axis scroll bar
scrollby = Scrollbar(self, command=textbox.yview)
scrollby.grid(row=7, column=5, rowspan=2, columnspan=1, sticky=N+S+E)
textbox['yscrollcommand'] = scrollby.set
tab['id']=tabslen
tab['btn']=btn
tab['txtbx']=textbox
self.tabs[tabslen] = tab
self.raiseTab(tabslen)
def raiseTab(self, tabid):
print(tabid)
print("curtab"+str(self.curtab))
if self.curtab!= None and self.curtab != tabid and len(self.tabs)>1:
self.tabs[tabid]['txtbx'].lift(self)
self.tabs[self.curtab]['txtbx'].lower(self)
self.curtab = tabid
def main():
root = Tk()
root.geometry("600x450+300+300")
t = Tabs(root)
t.addTab()
root.mainloop()
if __name__ == '__main__':
main()
While it may not help you at the moment, tk 8.5 comes with an extended set of widgets. This extended set is available with tk 8.4 by way of an extension known as "tile". Included in the extended set of widgets is a notebook widget. Unfortunately, at this time Tkinter by default uses a fairly old version of Tk that doesn't come with these widgets.
There have been efforts to make tile available to Tkinter. Check out http://tkinter.unpythonic.net/wiki/TileWrapper. For another similar effort see http://pypi.python.org/pypi/pyttk. Also, for a taste of how these widgets look (in Ruby, Perl and Tcl) see http://www.tkdocs.com/.
Tk 8.5 is a huge improvement over stock Tk. It introduces several new widgets, native widgets, and a theming engine. Hopefully it will be available by default in Tkinter some day soon. Too bad the Python world is lagging behind other languages.
update: The latest versions of Python now include support for the themed widgets out of the box. _
"Or is it simply the case that anyone who needs more powerful windowing components has to use wxPython?"
Short answer: yes.
Long answer:
It may take some practice for your wxPython code to feel "clean," but it is nicer and much more powerful than Tkinter. You will also get better support, since more people use it these days.
What problems did you have with pmw? It's old, yes, but it's pure python so it should work.
Note that Tix doesn't work with py2exe, if that is an issue for you.

Categories

Resources