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.
Related
I am trying to find the easiest (with shortest code) way of displaying a popup dialog window in Windows in my non-GUI Python 3.7 program. Basically, it tries to find and grab control of a window with a particular name. If it finds the window, it does its thing and all is good. If it doesn't find the window I'd like a wee popup message saying "Window not found". I know I can do this using PyQt5 or similar, but it is an awful lot of code just display a dialog!
You could do
import ctypes
mymessage = 'A message'
title = 'Popup window'
ctypes.windll.user32.MessageBoxA(0, mymessage, title, 0)
ctypes is part of the standard library, so this works on Windows without the need to install any packages.
A most simple way I could think of (not necessarily elegant) would be creating a .vbs file and calling MsgBox from there
MsgBox "Window not found!", 65, "Information"
Then call that file from Python using
>>> import os
>>> os.system("call popupmessage.vbs")
However, this is not cross-platform, but I assume you are using Windows.
Also keep in mind the directory in the os.system call is relative to your working directory unless you specify the full (or absolute) directory.
You should refer to https://www.tutorialspoint.com/vbscript/vbscript_dialog_boxes.htm on how to use MsgBox
I’d like to create a restricted folder/ file explorer in Python (I have version 2.7.9, but I don’t mind changing that) for Windows.
Essentially, I want to initially specify the folder to which the code opens. For example, the code should initially open to: C:\Users\myName\Desktop\myDemoFolder (the user must not know this folder simply by looking at the GUI).
The user must be able to browse downwards (deeper into folders) and backwards (but only up to the initial folder to which the code opens). The user must be able to click to open a file (for example: pdf), and the file must automatically open in its default application.
An example of what I’d like is presented in figure 1. (The look of the interface is not important)
Currently, I am able to get figure 2 using the code presented here:
from Tkinter import Tk
from tkFileDialog import askopenfilename
Tk().withdraw()
filename = askopenfilename()
print(filename)
Research has indicated that it is not possible to change the default buttons in Tkinter windows. Is this true? If it can’t be done with Tkinter (and that’s fine), how else can we do it?
I’d happily choose simple, non-Tkinter code (perhaps using wxPython’s wx.GenericDirCtrl()) rather than elaborate Tkinter code, but no restrictive libraries please.
A modular design approach is not needed. I’d rather have simple (functional) code that is shorter than object-oriented code.
I was trying to do the same thing when I realized that maybe you could create all the buttons you need and then set the color of the buttons you don't need to your background color using:
button-name.config(bg = "background-color")
Just change the "button-name" to your button's name and set "background-color" to the background color!
I've been looking for a way to open a text file with a text editor I made with python, and assumed it had something to do with system arguments, so made a simple application which would write the arguments sent by the system to a text window, and used "open with" on the text file and application, but the only argument was the path of the application. Many questions similar to mine have been answered on here but none of the answers have worked for me. How would I do this?
Thanks for any responses.
(I'm using OS X 10.9.5, with python 2.7)
Tried code:
from Tkinter import *
import sys, time
root = Tk()
root.geometry('300x200')
text = Text(root)
text.pack(side=TOP, fill="both", expand=True)
text.insert(END, sys.argv)
for x in xrange(len(sys.argv)):
text.insert(END,sys.argv[x])
root.mainloop()
Displayed text:
['/Path/pyfe.app/Contents/Resources/file_opener.py']/Path/pyfe.app/Contents/Resources/file_opener.py
If I understand your question correctly, you are talking about opening a file with the Finder's Open with context menu when clicking on a file. If so, it's probably a duplicate of MacOSX - File extension associate with application - Programatically. The standard way is to create an OS X app bundle (for Python programs, you can use py2app to do that) and then set proper key type in its Info.plist. That's assuming your text editor is a true GUI app (uses Tkinter or Cocoa or whatever) and not just a program that runs in a shell terminal window (in Terminal.app for example). In that case, you might be able to create a simple wrapper app (even using AppleScript or Automator and modifying its Info.plist as above) to launch your Python program in a terminal window and pass in the file name from the open event. To properly handle multiple files opened at different times would require more work.
UPDATE: as you have clarified, you are using Python Tkinter and a real GUI app. The native OS X Tk implementation provides an Apple Event handler to allow you to process Apple Events like Open Document. The support is described in tcl terms in the Tcl/Tk documentation so you need to translate it to Python but it's very straightforward. Python's IDLE app has an example of one, see, for instance, addOpenEventSupport in macosxSupport.py. For simple apps using py2app, you could instead use py2app's argv emulation.
I published a detailed description at https://moosystems.com/articles/8-double-click-on-files-in-finder-to-open-them-in-your-python-and-tk-application.html.
As answered above you need to adapt your Info.plist file to tell OS X that your app can at least view the file types you want to process.
Then you can use py2app's argv emulator to access any files dragged on your app while it's not running.
Then install a Tk event handler to accept files while the app is already running.
Find the details in the linked article.
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)')
I wrote a little app with a gui to analyze xml files. I have 2 .py files where 1 is the GUI and the second handels the xml.
My Problem is that the Icons i set and also a gif that i show using QMovie are not showing up on any machine but my development machine.
The other machines do not have PyQt or Python installed. They are using my Installation-folder from Python that I've copied onto a network drive. The i just copied the python32.dll in the machines system32 folder and the app works...except for the icons.
That's how i set the icons and reference the gif:
self.setWindowIcon(QtGui.QIcon("grabb.ico"))
--------other code---------
self.movie = QMovie("load.gif", QByteArray(), self)
self.movie.setCacheMode(QMovie.CacheAll)
self.movie.setSpeed(100)
self.movie_screen.setMovie(self.movie)
self.movie.start()
The file is in the same dir as the py so this should work. I've also tried absolute paths but that didn't give me any better results.
Now i have read on stack that this could be resolved by using the ressource-system.
So i used the designer to create a ressource files and then compiled it using pyrcc4 into a .py (using the parameter for python 3). Now I'm reffering to the images like this:
self.setWindowIcon(QtGui.QIcon(":icon/grabber.ico"))
--------other code---------
self.movie = QMovie(":loader/load.gif", QByteArray(), self)
self.movie.setCacheMode(QMovie.CacheAll)
self.movie.setSpeed(100)
self.movie_screen.setMovie(self.movie)
self.movie.start()
This again works fine on my machine but nowhere else.
Any ideas as to why only ma machine shows the icons ?
I'm not using py2exe or alike!
I too came across the same situation.
One approach is to set the paths in qt.config file and place this in the location of your executable.
I tested this with Python 2.6, and its working fine without any issue.
You said that you have shared your python installation which has PyQt4 init.
Lets say you python share path is \\somesystem\Python26
Yo will find a qt.config file in \\somesystem\Python26\PyQt4. Take it and replace the below lines in qt.conf
[Paths]
Prefix = //somesystem/Python26/PyQt4
Binaries = //somesystem/Python26/PyQt4