Remove window title bar in TKinter Python - python

How do I remove the title bar from a Toplevel() window in Tkinter.
Right now I for my main I have
self.master.title("Subtest")
self.master.geometry("400x200")
self.alertwindow()
Label(self.master,textvariable=self.connected,height=4).grid(row=0,column=0)
Button(self.master,text="Monitor",command= lambda: self.startnewthread(1),width=10).grid(row=6,column=1)
Button(self.master,text="Quit",command=self.haltprogram).grid(row=6,column=0)
And for my alert window function I have
def alertwindow(self):
self.listbox=Listbox(Toplevel(self.master,width=150).overrideredirect(True),width=150).pack)
I was wanting the program to open up a root window, and then a toplevel listbox without a title bar; however, the only thing the program is doing right now is freezing, and when I remove the .overrideredirect(True), the program launches two listbox windows. How can I have the program open only one listbox without a title bar on windows? Thanks

Looking at this line
self.listbox=Listbox(Toplevel(self.master,width=150).overrideredirect(True),width=150).pack)
It's pretty clear you're trying to do WAY too much on 1 line. (Your parenthesis don't even match). Let's break it up, shall we?
new_top = Toplevel(self.master,width=150)
new_top.overrideredirect(True)
self.listbox = Listbox(new_top,width=150)
self.listbox.pack()
Also note that you seem to be using .grid and .pack -- Generally that's ill advised and Tkinter will happily spend all of eternity trying to negotiate a proper placement of a widget when you try to use them together.
My guess about what's happening:
your actual code has properly balanced parenthesis so there is no SyntaxError
Toplevel.overrideredirct returns None
Listbox sees None as the parent widget and substitutes the root widget (Tk)
Then you're using .grid and .pack both on the root widget which causes your program to hang.

Related

How to position a ScrolledWindow (tkinter) scrollbar at the bottom

I am creating a gui with tkinter in python. I have created a scrollbar and this is what the section of code looks like:
beta_frame = Frame(width="500", height="680")
beta_frame.pack()
holder = ScrolledWindow(beta_frame, width=500, height=680)
holder.pack()
alpha_frame = holder.window
I would like to position this scrollbar at the very bottom every time something new is put on the screen (which would obviously be added to the bottom The only things I'm adding to the screen are labels and buttons), though I'm unsure how to do this and I've searched everywhere. All I came up with is the method see, which I am unsure if it is even applicable in this instance. Any help would be appreciated.
.see() is the normal way to get Tkinter to auto-scroll to a given position, but that method only exists on the widgets that have built-in support for scrolling - Listbox, Canvas, Text, and Entry. The Tix ScrolledWindow makes an ordinary Frame scrollable, so no such method will exist.
It appears that this line of code will do what you want:
holder.tk.eval(holder.vsb['command'] + " moveto 1.0")
vsb is the vertical scrollbar component of the ScrolledWindow, 'command' is the scrollbar configuration option that specifies a callback to invoke when the position is changed. This will refer to something deep inside Tix, but we don't care exactly what it is; we just invoke it with the same parameters that the scrollbar itself would, if being moved to the very end.

Unclosable window using tkinter

Hey I am making a program that take a picture using my webcam when I type the wrong password. The program will be open and I want it unclosable.
I need to know how to make a window unclosable using tkinter.
You can try all of the many things #abarnert suggested, but I think the easiest way would be to just ignore the close event.
From this question:
Here you have a concrete example:
import Tkinter as tk
import tkMessageBox as messagebox
root = tk.Tk()
def on_closing():
if messagebox.askokcancel("Quit", "Do you want to quit?"):
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()
(edited code for Windows)
So change on_closing() to
def on_closing():
pass
and that makes it unclosable. I tried Alt+F4, the close button, closing it from the Windows Taskbar, all to no avail. The only way I was able to kill it was to use Task Manager.
Tkinter doesn't have any way to do this directly. But it does have something that may be good enough, or it may be too much overkill: the overrideredirect flag:
If non-zero, this prevents the window manager from decorating the window. In other words, the window will not have a title or a border, and it cannot be moved or closed via ordinary means.
That's not quite up-to-date; it may actually have a title or border on some platforms… but it won't be closable.
This is easy to use: just do root.overrideredirect(True) (or, if you want to do it to a different Toplevel window instead of your root, window.overrideredirect(True)).
But notice that it can't be moved or closed, not just that it can't be closed. (It also can't be resized, if you want that.)
So, the only thing you can do is set the flag, but then bind the mouse-button events to handle moving manually. For example, in your window's __init__ method:
self.overrideredirect(True) # if this is a Toplevel
#self.parent.overrideredirect(True) # if this is a Frame on root
self.bind('<ButtonPress-1>', self.move_start)
self.bind('<ButtonRelease-1>', self.move_end)
self.bind('<B1-Motion>', self.move_move)
And then:
def move_start(self, event):
self.startx, self.starty = event.x, event.y
def move_stop(self, event):
self.move_move(event)
def move_move(self, event):
x = self.winfo_x() + event.x - self.startx
y = self.winfo_y() + event.y - self.starty
self.geometry("+%s+%s" % (x, y))
Obviously, if you want any widgets within the window to accept clicks, you probably don't want to make the whole window a drag area. In fact, you may not want to make the whole window a drag area even if it doesn't have anything to click, because that's not really following Mac or Windows human interface guidelines. You could fake a grip area—a title bar, a border around the window, etc.—just by, e.g., adding a Label pinned to the side(s) you want to grip from and only binding there, or by creating a "child" window inset from the main window that steals the bindings. But this is never going to look like a "native" window.
If you really need a native window, but with the close box (the X in the top-right corner on Windows, the red dot in the top-left on Mac, etc.) disabled or missing (and, on Windows, with the "close" item on the window menu disabled, and Alt+F4, and so on, and similarly for X11…)… As far as I know, there's no cross-platform way to do that in Tkinter. You will have to write code for each platform that gets at the underlying native window objects and does native window things to them. At that point, you probably want to look at using a more powerful windowing library than Tkinter—e.g., I believe Qt, Gtk+, and wx all have much simpler ways of creating a normal window but with the close box disabled.

tkinter menu accelerators and modal dialog boxes

I want to have a menu that shows a modal dialog box. Everything is fine, until I add an accelerator. If I do this and use the accelerator to access to dialog, it hangs. I suspect that wait_window, used inside the modal dialog box is somehow in conflict with the mainloop, when called from a "bind". Here is an example:
import tkinter
from tkinter import simpledialog
class App(tkinter.Tk):
def __init__(self):
tkinter.Tk.__init__(self)
self.bind_all("<Control-f>", lambda event: self.menu_file())
menubar = tkinter.Menu(self)
fileMenu = tkinter.Menu(menubar, tearoff=False)
fileMenu.add_command(label="File", underline=0,
command=self.menu_file, accelerator="Control+f")
# fileMenu.add_command(label="File", underline=0,
# command=self.menu_file)
menubar.add_cascade(label="File",underline=0, menu=fileMenu)
self.config(menu=menubar)
def menu_file(self):
simpledialog.Dialog(self,"Message")
app=App()
app.mainloop()
If in the above code I comment out the line that adds the accelerator and uncomment the subsequent line, there is no hangup (I can of course still use Ctrl+F to access the dialog box). The only problem is that the accelerator string is not shown next to the File menu. According to the tkinter documentations on the web that I have found, adding the accelerator should only change how the menu is shown and nothing else, so I am really puzzled. Anyone any ideas? (I could of course emulate accelerators by modifying the strings to be displayed, but I would not consider this as an elegant solution.)
As I have noticed, this is a Mac-specific bug.
Following the workaround suggested for a known Tk bug on Mac (see link), changing the line which binds the menu method to the keystroke to the following:
self.bind_all("<Command-f>", lambda event: self.after(100,self.menu_file))
is "fixing" the bug. They also suggest to increase 100 to 150 on slower systems. Hmm..

Determining what tkinter window is currently on top

I have written an application in python 2.7 and tkinter. I created a tool bar with several buttons that open up respective top windows that display various options. I used ttk.Checkbutton with the 'toolbutton' style as an indicator to show whether the option windows are open or closed.
The problem is that the option windows will go to the back if another window is selected. Currently, if one selects the toolbutton again, the option window will close. However, I only want to close the window if it is on top. If the option window is not on top, I want the window to moved to the front.
Some of the code I have working:
class MainWindow:
def __init__(self,application):
self.mainframe=tk.Frame(application)
application.geometry("900x600+30+30")
self.otherOptionsSelect=tk.IntVar()
self.otherOptions_Button=ttk.Checkbutton(application,style='Toolbutton',variable=self.otherOptionsSelect,
onvalue=1, offvalue=0,image=self.optionsIcon, command=self.otherOptions)
def otherOptions(self):
if self.otherOptionsSelect.get()==0:
self.otherOptions.destroy()
return
self.otherOptions=tk.Toplevel()
self.otherOptions.title("IsoSurface Options")
self.otherOptions.geometry("200x165+"+str(int(application.winfo_x())+555)+"+"+str(int(application.winfo_y())+230))
self.otherOptApply_button=ttk.Button(self.otherOptions,text="Apply",command=self.showFrame)
self.otherOptApply_button.place(x=20,y=80,width=50,height=30)
self.otherOptClose_button=ttk.Button(self.otherOptions,text="Close",command=self.otherOptionsClose)
self.otherOptClose_button.place(x=80,y=80,width=50,height=30)
def otherOptionsClose(self):
self.otherOptionsSelect.set(0)
self.otherOptions.destroy()
Here is a picture of the entire application I have written:
In the above image, each window has their respective ttk.checkbutton. At the moment, toggling the checkbutton either opens or closes the window. However, what I really want it to do is close the window if the window is in front of the application, or bring the window to the front if it is behind the application.
Hopefully this clears some things up.
Thanks in advance!
It is in fact possible to check stacking order of windows. Using Tkinter, you have to do some funny tcl evals to get at the information. I found the answer at TkDoc in the section on Windows and Dialogs, scroll down until you get to "Stacking Order". The code baffled me until I started playing around with it interactively. My test code was:
import Tkinter as tk
root = tk.Tk()
root.title('root')
one = tk.Toplevel(root)
one.title('one')
two = tk.Toplevel(root)
two.title('two')
I then manipulated the windows so that two was on top, one under that and root below them all. In that configuration, the following weirdness can tell you relative layering of windows:
root.tk.eval('wm stackorder '+str(two)+' isabove '+str(root))
returns 1, meaning "Yes, window two is above window root." While the following:
root.tk.eval('wm stackorder '+str(root)+' isabove '+str(two))
returns 0, meaning "No, window root is not above window two." You can also use the command:
root.tk.eval('wm stackorder '+str(root))
Which gives back the full window stacking order in the form of a weird string something like this:
'. .68400520L .68401032L'
Which starts to make sense when you run the commands:
str(root)
str(one)
str(two)
and figure out that root has the internal name '.', one is '.68400520L' and two is '.68401032L'. You read the output of root.tk.eval('wm stackorder '+str(root)) backwards so it's saying two is on top, one is under that and root is below both.

Checkbuttons with Multiple Tkinter Windows

Specs:
Python2.7.1
Tkinter (Tk version 8.5)
Windows7
IDLE 2.7.1
I'm coding a program that 'spawns' two windows, withdraws both, destroys one and then deiconifies the other (which then enters a mainloop).
This arrangement is interfering with a Checkbutton on the remaining window.
eg:
temp = Tk()
temp.withdraw()
root = Tk()
root.withdraw()
temp.destroy()
root.mainloop()
(It seems unusual, but it is set up this way so that the 'temp' window will display the problems that arose, during building of the root window).
However,
it seems that as soon as a single program deals with two Tkinter windows,
functionality of a Checkbutton (in root) goes out the window.
def ClickAButton():
print Toggle.get()
Toggle = IntVar()
Checkbutton(root, text = "Me is broke", variable = Toggle).pack()
ClickAButton
Toggle.get() should return a 1 if the Checkbutton is ticked, otherwise a 0.
However, since adding the new window, Toggle.get always returns a 0.
(I've tried reformatting code {this brings up strange erros of it's own},
renaming variables, etc.
The Checkbutton works just fine without the 'temp' window.
The 'temp' window is destroyed before the Checkbutton is even assigned, packed,
or 'root' even enters a mainloop!)
Entire eg:
temp = Tk()
temp.withdraw()
root = Tk()
root.withdraw()
if 'certain condition':
root.destroy()
temp.deiconify()
temp.mainloop()
else:
temp.destroy()
Toggle = IntVar()
Checkbutton(root, text = "Why I only return 0?", variable = Toggle).pack()
root.deiconify()
root.mainloop()
For some reason,
the Checkbutton is always returns 0, even when checked.
I suspect it's a multi-threading issue with Tkinter.
Is there anything at all I can do here?
(The actual coding is HUGE. I'm not eager to switch it all to another GUI module)
:|
Greatly appreciated!
(I only started programming the start of this year.
Please forgive me if I've made some horribly noobish mistake!)
Tkinter isn't designed to have two root windows. I'm amazed your code works at all. This has nothing to do with multi-threading -- Tkinter is single threaded and you don't appear to be creating any new threads (though if you are, that might contribute to the problem)/
You need to create a single root window with a single mainloop. If you need another window, create a Toplevel window -- that's precisely what that widget is for.

Categories