Python Tkinter: Remove window border - python

How do you remove the border of a TopLevel without using overrideredirect?
TopLevel.overrideredirect(True)
It would be great if a sample code can be provided.
Python 2.7.3, Linux, Tkinter version $Revision: 81008 $

With the help of Bryan Oakley, I have realized a solution that would allow me to use 'overrideredirect' while solving my problem, and that is using 'Unmap' event.
The following example code shows that when the additional window can be minimized with the main window when using 'Map' and 'Unmap':
import Tkinter
class App:
def __init__(self):
self.root = Tkinter.Tk()
Tkinter.Label(self.root, text="main window").pack()
self.window = Tkinter.Toplevel()
self.window.overrideredirect(True)
Tkinter.Label(self.window, text="Additional window").pack()
self.root.bind("<Unmap>", self.OnUnMap)
self.root.bind("<Map>", self.OnMap)
self.root.mainloop()
def OnMap(self, e):
self.window.wm_deiconify()
def OnUnMap(self, e):
self.window.wm_withdraw()
app=App()

Related

Don't know how to apply mainloop() in my app

I have programmed a 2600 lines application which worked great when running from the IDE. Now I have created an executable via Pyinstaller and now the GUI does not start. The application starts and disappears quickly. I do not get any errors (anymore, solved them), however this problem remains. I think it has to do with missing the mainloop() in my application, which I don't know how to apply in this particular case. Usually its like this:
root = tk.Tk()
root.mainloop()
In my case I created a class for my window adding a menubar and label as statusbar (the latter not shown in my code below). This makes me assigning this class being a Tk() to main_window. Where do I put the mainloop() without getting an error?
I already tried:
main_window.mainloop()
since main_window is the window where all frames put on to, but then I get the following error in the IDE:
main_window.mainloop() AttributeError: 'AppWindow' object has no attribute 'mainloop'
How do I apply the mainloop() into my application without getting the above mentioned error? Or how do I get my GUI to be working in a different manner? Both answers are welcome.
Here is the necessary code to know:
import tkinter as tk
class AppWindow():
def __init__(self, master):
self.master = master
master.title("Basic Application")
master.geometry("1060x680")
master.grid_propagate(False)
#create drop down menu
self.menubar = tk.Menu(master) # main menubar
#Add filemenu
self.filemenu = tk.Menu(self.menubar, tearoff=0) #sub menu
self.filemenu.add_separator() #create a bar in the menu
self.filemenu.add_command(label="Quit", command=master.destroy) #Add submenu item
self.menubar.add_cascade(label="File", menu=self.filemenu) #Add submenu to menubar
self.master.config(menu=self.menubar) #Show menu
class FrameOne(tk.Frame):
def __init__(self, parent):
super().__init__()
self["borderwidth"]=5
self["relief"]="ridge"
self.create_widgets() #Function which creates all widgets
self.position_widgets() #Function which position all widgets
def create_widgets(self): #Function which creates all widgets
pass
def position_widgets(self): #Function which position all widgets
pass
#Create a window as defined in the AppWindow class
main_window = AppWindow(tk.Tk())
#Create a Frame as defined in class FrameOne
first_frame = FrameOne(main_window)
first_frame.grid(row=0, column=0) #Positioning Frame on Window
main_window.mainloop() #THIS PROVIDES AN ERROR | GUI DOES NOT START WITHOUT
mainloop is a method on the tkinter root window and on tkinter itself. Like the error says, it's not a method of your AppWindow class.
In your case you should do it like this:
root = tk.Tk()
main_window = AppWindow(root)
root.mainloop()

Creating a modal dialog box in tkinter

This question is not a duplicate: see below.
I want to create a modal dialog box in tkinter. In other words, a dialog box which, while it is active, prevents the user from interacting with the parent window. There is an existing question on SO answering this, and there is a full example illustrating the concept.
However, making the dialog box a Toplevel and calling grab_set() on it simply doesn't work, on either Windows 7 or Ubuntu 16.04.4 LTS. The user is still able to close, resize, and in general interact with the parent window.
Is there a way of creating a modal dialog box in Tkinter that actually works?
Here is a minimal usage example of dialog.grab_set() failing to prevent interaction with the parent window:
import os
try:
import Tkinter as tkinter
except ImportError:
import tkinter
class MyToplevel(tkinter.Toplevel, object):
def __init__(self, parent):
tkinter.Toplevel.__init__(self, parent)
self.title("Main window")
MyDialog(self)
self.protocol("WM_DELETE_WINDOW", parent.destroy)
class MyDialog(tkinter.Toplevel, object):
def __init__(self, parent):
tkinter.Toplevel.__init__(self, parent)
self.transient(parent)
self.title("Dialog")
self.grab_set()
self.protocol("WM_DELETE_WINDOW", self.destroy)
if __name__ == "__main__":
root = tkinter.Tk()
root.withdraw()
app = MyToplevel(root)
app.mainloop()
I should point out that using grab_set_global() (as in this answer) does work, but is not a viable solution because it blocks access to all windows, for the entire system.
This is (at least on windows) a version specific problem. To make it work on python2.7, just add self.focus_force() before self.grab_set():
def __init__(self, parent):
tkinter.Toplevel.__init__(self, parent)
self.transient(parent)
self.title("Dialog")
self.focus_force() # added
self.grab_set()
self.protocol("WM_DELETE_WINDOW", self.destroy)

Python Tkinter hide and show window via hotkeys

I'm trying to write a program that I can hide and show via hotkeys. I managed to get the application to show and hide using the library "keyboard", however due to the "wait" function of the library, it prevents the Text box from functioning correctly. I have tried using the key bindings within Tkinter, however I had a different problem, whereby once the program was hidden or another application was selected, I couldn't return the focus to the hidden window via the hotkey.
import Tkinter as Tk
import keyboard
class MyApp(object):
def __init__(self, parent):
self.root = parent
self.root.title("Main frame")
self.frame = Tk.Frame(parent)
self.frame.pack()
self.editor = Tk.Text(self.frame)
self.editor.pack()
self.editor.config(font="Courier 12")
self.editor.focus_set()
keyboard.add_hotkey('ctrl+alt+s', self.show)
keyboard.add_hotkey('ctrl+alt+h', self.hide)
keyboard.wait()
self.root.withdraw()
def show(self):
self.root.update()
self.root.deiconify()
def hide(self):
self.root.withdraw()
if __name__ == "__main__":
root = Tk.Tk()
root.geometry("800x600")
app = MyApp(root)
root.mainloop()
Any assistance would be great :)
Just drop this wait command, its an additional mainloop, which is not needed as Tkinter does its job. I tried to fix your problem with threading, but as I wanted to check exactly what is NOT working, I accidentially made what I suppose you wanted to. So the Code is:
import tkinter as tk
import keyboard
class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry("800x600")
self.title("Main frame")
self.editor = Tk.Text(self)
self.editor.pack()
self.editor.config(font="Courier 12")
self.editor.focus_set()
keyboard.add_hotkey('ctrl+alt+s', self.show)
keyboard.add_hotkey('ctrl+alt+h', self.hide)
def show(self):
self.update()
self.deiconify()
def hide(self):
self.update()
self.withdraw()
if __name__ == "__main__":
App().mainloop()
I hope this works for you. I'd also recommend changing this key settings. Testing with those in PyZo is IMPOSSIBLE! It always tries to "save as...", which I don't want to...

Python Tkinter menu bars don't display

I'm trying to make a GUI using Tkinter and have come to implementing a menu bar. I've looked at a few tutorials and written some code for it, but a menu bar never seems to appear - just a blank frame with a white background. This doesn't just happen for my code though; on copying and pasting the code of one of the aforementioned tutorials into a new script, the same behaviour is exhibited.
I'd appreciate it if anyone could shed any light on what's causing this. My system is OS X 10.5, Python 2.7, Tk 8.4. Here's the code from the tutorial that doesn't appear to work:
#!/usr/local/bin/python2.7
from Tkinter import *
from ttk import *
class App(Frame):
def __init__(self):
Frame.__init__(self)
self.master.geometry('400x300')
self.master.title(__file__)
self.pack()
self.menu = Menu(tearoff=False)
self.master.config(menu = self.menu)
fm = self.file_menu = None
fm = Menu(self.menu, tearoff=False)
self.menu.add_cascade(label='File', menu = fm)
fm.add_command(label='Say Hello', command = self.say_hello)
fm.add_separator()
fm.add_command(label='Quit', command = self.quit)
self.mainloop()
def say_hello(self, *e):
self.label = Label(self.master, text='Hello there!')
self.label.pack(anchor=CENTER, fill=NONE, expand=YES, side=LEFT)
if __name__ == '__main__':
App()
and my code is here:
from Tkinter import *
class App(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
parent.title("Cluedo Solver 1.0")
menubar = Menu(root)
menubar.add_command(label="File")
menubar.add_command(label="Quit", command=root.quit())
root.config(menu=menubar)
root=Tk()
root.geometry("300x250+300+300")
app=App(root)
root.mainloop()
Based on some comments you made to one of the answers, you are apparently running this on a Macintosh. The code works fine, but the menu appears in the mac menubar rather than on the window like it does on Windows and Linux. So, there's nothing wrong with your code as far as the menubar is concerned.
Code with Explanation
From personal experience, I have found that it is usually easier to manage all widgets in a widgets method. That is what I did here, and it worked. Also, instead of parent, I used master. I will now walk you through the code step-by-step.
from Tkinter import *
We import Tkinter (GUI stuff)
class App(Frame):
We create a class called App, which is the Frame where widgets are held.
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.widgets()
We create a method called __init__. This initializes the class, and runs another method called widgets.
def widgets(self):
menubar = Menu(root)
menubar.add_command(label="File")
menubar.add_command(label="Quit", command=root.quit())
root.config(menu=menubar)
We create the widgets method. This is where the widget, menubar is added. If we were to create anymore widgets, they would also be here.
root=Tk()
root.title("Menubar")
app=App(root)
root.mainloop()
Lastly, we give the entire window some properties. We give it a title, Menubar, and run the App class. lastly, we start the GUI's mainloop with root.mainloop.
I am trying the code as above, but all I get is "Python" on the macOS menubar and it's usual pulldown. tkinter just doesn't seem to work menus on macOS 10.14.1
I think what is happening is that there are mac specific fixups that are changing the event codes so certain menu items will end up under the Python menu item instead of where expected, I saw some of this in my own experiments. When I expanded my code and used some of the reserved FILE event codes instead of the standard ones, things worked better.
#!/Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7
# -*- coding: utf-8 -*-# -*- coding: utf-8 -*-
from tkinter import *
class App(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.widgets()
def widgets(self):
menubar = Menu(root)
menubar.add_command(label = 'File')
menubar.add_command(label = 'quit', command = root.quit())
root.config(menu = menubar)
root = Tk()
root.title('Menubar')
app = App(root)
root.mainloop()
Check your mac menu bar if you are doing any GUI that involves menubar which you will like to view or test. Its subtle and you may think you code is not to working. Click on the app(in this case python window), it will show a drop down menubar.
guys to solve the problem
look the file part that's where the menubar for mac is located

simple key pressed event in python tkinter app

I'm new to python and Tkinter. I'm looking for a small GUI app which contains a textbox on it and if any change occurs in the textbox content then it fires up an event for me to do something. I tried but failed to write such an event.
Any help will be appreciated.
You can use bind the <Key> event to a callback like this:
import Tkinter as tk
class MyApp(object):
def __init__(self, master):
self.text = tk.Text(master)
self.text.bind('<Key>', self.callback)
self.text.pack()
self.text.focus()
def callback(self, event):
print('{k!r}'.format(k = event.char))
root = tk.Tk()
app = MyApp(root)
root.mainloop()
(Like Steven Rumbalski, I'm not quite sure what you intended by 'textbox'. Happily, the above code will still work if you change tk.Text to tk.Entry.)

Categories