Is it possible to edit/remove the "Tk" characters (inside green circle) from a tkinter window?
The red scripty Tk is the app icon.
On some platforms, you can replace that by using the iconbitmap or iconphoto functions. On others, you can't override the icon specified in the exe/bundle/etc. So, to do this cross-platform, you'll need to do it in your code, and also in your packaging (assuming you're planning to package and distribute binaries).
If you only care about Windows, iconbitmap with a Windows .ico file is the right solution. IIRC, on most *nix systems it's iconbitmap with a .xbm or iconphoto with a .xpm, while on Mac, it's… well, the app icon (which has to come from the bundle) isn't shown on the window at all, the document icon is shown there, and calling iconbitmap on a window sets the document icon to the Finder icon for the specified file.
See this thread for an explanation of how to do it from Python.
As far as I know, Tk has no way to remove the app icon. Which is probably a good thing, because many platforms/window managers would end up showing some hideous "default app" in that place. But you can replace it with a 100%-transparent icon, which may be what you want.
The plain black tk is just window title. Give it any other window title, and the "tk" won't appear.
If you've already created a window and want to change its title, just call the title method:
my_frame.title('My new title, with no tk (except that one)')
Related
I am trying to change the icon that appears on my tk application for Mac OS. The last time I checked this code worked for windows. The goal is for this solution to work across all platforms.
root = tk.Tk()
app = Application(master=root)
app.master.iconbitmap("my_icon.ico")
app.mainloop()
The code is adding the default icon for a .pdf file which is not what I intended. The path to the my_icon.ico is correct. Why won't this work for Mac OS? Is there an ultimate solution that will work cross-platform?
According to the tk tcl documentation you may want to try wm iconphoto. It appears it may support OSX and it also mentions to set the file to around a 512x512 for smooth rendering in MAC.
I do not have MAC so I cannot test this but give this a shot and let me know if it helped.
Update:
As #l'L'l pointed out you may want to try root.iconphoto(True, img). I am unable to test it myself due to not having Mac.
import tkinter as tk
root = tk.Tk()
img = tk.Image("photo", file="icon.gif")
# root.iconphoto(True, img) # you may also want to try this.
root.tk.call('wm','iconphoto', root._w, img)
root.mainloop()
Here is the relevant text from the documentation here:
wm iconphoto window ?-default? image1 ?image2 ...? Sets the titlebar
icon for window based on the named photo images. If -default is
specified, this is applied to all future created toplevels as well.
The data in the images is taken as a snapshot at the time of
invocation. If the images are later changed, this is not reflected to
the titlebar icons. Multiple images are accepted to allow different
images sizes (e.g., 16x16 and 32x32) to be provided. The window
manager may scale provided icons to an appropriate size. On Windows,
the images are packed into a Windows icon structure. This will
override an ico specified to wm iconbitmap, and vice versa.
On X, the images are arranged into the _NET_WM_ICON X property, which
most modern window managers support. A wm iconbitmap may exist
simultaneously. It is recommended to use not more than 2 icons,
placing the larger icon first.
On Macintosh, the first image called is loaded into an OSX-native icon
format, and becomes the application icon in dialogs, the Dock, and
other contexts. At the script level the command will accept only the
first image passed in the parameters as support for multiple
sizes/resolutions on macOS is outside Tk's scope. Developers should
use the largest icon they can support (preferably 512 pixels) to
ensure smooth rendering on the Mac.
I did test this on windows to make sure it at least works there. I used a blue square image to test.
If the above documentations is accurate it should also work on MAC.
If you are using Mac OS you have to use a .icns image instead a .ico image.
you can use:
from tkinter import Tk
from platform import system
platformD = system()
if platformD == 'Darwin':
logo_image = 'images/logo.icns'
elif platformD == 'Windows':
logo_image = 'images/logo.ico'
else:
logo_image = 'images/logo.xbm'
root = Tk()
root.title("My App")
root.iconbitmap(logo_image)
root.resizable(0, 0)
root.mainloop()
Important Note: This method is long and a lot of work for the task at hand. However, it does come with some unrelated benefits. Note that there might be a better way, but this will work.
Anyway, moving on....
You can use py2app.
Py2app will turn your program into a .app, meaning it runs as an application (because it is). When using tkinter this is usually what you want in the end because GUIs are usually turned into apps for ease of use. You can read the py2app documentation here, or read a non-official but easier to understand (in my opinion) tutorial here. I will also sum up how to do the process.
First install py2app:
Enter this into the command prompt:
sudo pip install -U py2app
If successful, you should get py2app.
If not, one problem might be you don’t have pip. You can download it with another command:
sudo easy_install pip
Step one:
Create a file called setup.py in the same dictionary
as the program.
Step two:
Put this into the file.
from setuptools import setup
#APP would be the name of the file your code is in.
APP = ['example.py']
DATA_FILES = []
#The Magic is in OPTIONS.
OPTIONS = {
'argv_emulation': False,
'iconfile': 'app.icns', #change app.icns to the image file name!!!
}
setup(
app=APP,
name='Your app’s name', #change to anything
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
Step 3:
Then open the bash terminal in the dictionary the file is in and type this command:
python setup.py py2app -A
The -A makes the app respond to updates in the code, but makes the app unsharable. When you are done developing, rerun the command, this time without the -A, like so:
python setup.py py2app
Note: You may need to use the command python3 setup.py py2... instead of python setup.py py2... for a python 3 py2app.
Step 4:
Navigate to the dictionary your code is in/dist. In that folder will be your app. (The dist folder should have been created in step three when you ran the command)
For windows users: py2app is not what should be used, instead use py2exe.
I found a solution that worked for me, changing the application icon rather than the window icon using the pyobjc module.
import tkinter as tk
import sys
root = tk.Tk()
if sys.platform.startswith('darwin'):
try:
from Cocoa import NSApplication, NSImage
except ImportError:
print('Unable to import pyobjc modules')
else:
ns_application = NSApplication.sharedApplication()
logo_ns_image = NSImage.alloc().initByReferencingFile_('/path/to/icon.icns')
ns_application.setApplicationIconImage_(logo_ns_image)
else:
pass # handle other platforms
root.mainloop()
tkinter.iconbitmap creates a proxy icon on mac which is a shortcut to that file. If you right click a file and select get info, the window that popes up has an icon. It is the icon of the file. You can drag the icon, and that will move the file. That is a proxy icon. If you set the iconbitmap, with an .app file the proxy icon will be that app. Since files dragged from the applications folder create shortcuts, if the .app you set iconbitmap to be, it will make a short cut if you drag the icon of the title bar. This is helpful because you don't want the user to be able to just drag your icon file out of it's directory, so it doesn't work next time your tkinter program loads that .app file. Before you convert your tkinter program to an app add root.iconbitmap("/Applications/<appname>.app").
Then move your app to the applications folder. When you open your app your tkinter window will have the icon of your app.If you drag the icon into a different folder it will create a short cut to your app.
I am working on a Gtk+ 3 application that is likely to be used fullscreen most of the time, but needs to be switched between fullscreen and non-fullscreen, while maintaining access to the controls located in the header bar. The problem is, since the headerbar is part of the window decorations, it gets hidden when the window goes fullscreen.
My current kludge so ensure the controls are always available works like this:
Setup
create a Gtk.Window with vertical Gtk.Box as first child
create a custom Gtk.HeaderBar (w/ added full screen togglebutton)
set window's titlebar as my custom Gtk.HeaderBar
add all the window's content to the Gtk.Box
When window goes fullscreen
remove the Gtk.HeaderBar from the Gtk.Window titlebar
pack the Gtk.HeaderBar into the Gtk.Box (window's first child).
This results in the Gtk.HeaderBar being at the bottom of the window, so
re-position the Gtk.HeaderBar to the top of the Gtk.Box
When the window goes un-fullscreen
remove the Gtk.HeaderBar from the gtk.Box
set it as the Gtk.Window's titlebar
This results in the following Gtk-warning: gtk_window_set_titlebar() called on a realized window (who cares, just a warning)
This works, but it seems like very much of a hack, and more complicated than it should have to be. Am I missing something and there is a more straightforward approach?
I know several Gtk+ 3 based apps have the header bar behavior I am after (gedit for example), but I have not been able to determine how that is implemented. Any insight would be greatly appreciated.
Also, here is a GitHub gist with a full working example of my current hacky solution: https://gist.github.com/KurtJacobson/6b045b6fc38907a2f18c38f6de2929e3
I will accept answers in any (programming) language.
I am creating a full-frame (no decorations) window with code like this (in python 3.2 using tkinter):
self.root = Tk()
self.W, self.H = self.root.winfo_screenwidth(), self.root.winfo_screenheight()
self.root.overrideredirect(1) # full screen, no menu or borders
self.root.geometry("%dx%d+0+0" % (self.W, self.H))
When I try to open a file dialog or message box, they appear UNDER the full frame window. I can verify this by calling a withdraw() on the main window before I open one of the dialogs. For example,
file = tkinter.filedialog.askopenfilename(parent=self.root) # UNDER main window
On windows I don't have a problem with this, only on fedora 14 and ubuntu 12.04 have I noticed it. (I haven't tested on Mac). I'm passing a parent to the dialogs but they don't seem to be paying attention. Can someone help me understand what I'm doing wrong? Thanks.
Calling .overrideredirect(1) on a window has a different meanings on Windows and X11. On Windows, it tells the OS to disable drawing of the window border. On X11, it tells the window manager to completely ignore the window. Realistically, it should have the same effect on Windows that it does on X11, but this is not the case.
The reason why calling .overrideredirect(1) causes the window to stay on top is because X11 does not have any control over it (as the displaying of the window is not handled by the window manager). The program window and the window manager are completely independent, so implementing standard window stacking would not make sense.
With only tkinter, there is nothing you can do to prevent this behaviour, because tkinter is not really the source of the problem. There may be a way to use X11 Python bindings to show the window without a frame, but this would result in platform specific code.
You may want to rethink removing the window border. Is there a possible alternative? A fullscreen window including the window border is a fine option. Removing window borders is not a good idea at the best of times due to accessibility reasons (no way to move, minimize, maximize, etc.). Also, personally, as a Linux user, I have my window borders customized with all kinds of features (e.g. window tabbing, shade button), and use them quite frequently. Removing the window border would prevent such features from being used.
I can get what I think is the Nautilus desktop window by using this code:
screen = wnck.screen_get_default()
while gtk.events_pending():
gtk.main_iteration()
for window in screen.get_windows():
if window.get_name() == 'x-nautilus-desktop':
xid = window.get_xid()
wrapped_window = gtk.gdk.window_foreign_new(xid)
but when I try to do wrapped_window.add() I get the error that the Window Object does not have the add method.
I know this can be done since someone already has a youtube video demoing the effect at http://www.youtube.com/watch?v=NOlIfhXQX9g but I can't figure out how to get the background window and put a widget on it.
Anyone know how to do it?
You're mixing up gtk.Window and gtk.gdk.Window. They are not the same. The former is a toplevel desktop window and functions as a container for GTK widgets; the latter is an abstraction of an area of the screen which can be drawn on top of, and is not a container.
You can't get an application's GTK widgets using libwnck. How to achieve the effect you want I don't know, but I think you need to look more into extending the window manager, since that is what manages the desktop.
Is there any way to get a border like this in Tkinter? Notice how it lacks the buttons on the top right. Also I don't want this program to show in the task bar.
This is in windows 7, btw.
Tk (and thus, Tkinter) has a command for removing all window manager decoration. This command in tkinter is the "wm_overrideredirect" method of toplevel windows. Pass it a parameter of True to remove the window manager decorations. You can then draw whatever borders you want, usually by packing a canvas over the entire window and drawing on the canvas.
However, when I experiment with this on my Mac, the window appears properly but won't take focus. Perhaps this is a bug in Tkinter. I don't see the same problem with identical code in Tcl.
The WS_DLGFRAME window style should give you a window without a titlebar and WS_EX_TOOLWINDOW is normally also used for a window like this so it is not visible in the taskbar (Or with a hidden parent window like control panel dialogs before Vista) You can figure out the exact window styles with a tool like Spy++ (Visual Studio) or WinSpy++