How can I display an image in Python 3 using tkinter/ttk? - image

The nub of the matter is, what am I doing wrong in the following code snippet?
from tkinter import *
from tkinter.ttk import *
root = Tk()
myButton = Button(root)
myImage = PhotoImage(myButton, file='myPicture.gif')
myButton.image = myImage
myButton.configure(image=myImage)
root.mainloop()
The error message I get from idle3 is as follows:
>>>
Traceback (most recent call last):
File "/home/bob/Documents/Python/tkImageTest.py", line 9, in <module>
myButton.configure(image=myImage)
File "/usr/lib/python3.2/tkinter/__init__.py", line 1196, in configure
return self._configure('configure', cnf, kw)
File "/usr/lib/python3.2/tkinter/__init__.py", line 1187, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
TypeError: __str__ returned non-string (type Button)
>>>
This error message has me stumped, I simply don't understand what it is trying to say. Any ideas?
I would also appreciate suggestions for changes...

The error seems to point to the myButton argument passed to PhotoImage. As you noted in your comment, PhotoImage was treating the widget object as a string (there are several options of type string; see a list of PhotoImage options here).
Your code will work if you implement that line without referencing the myButton object:
myImage = PhotoImage(file='myPicture.gif')
I'm not certain you need to alter the PhotoImage constructor. Look at the PhotoImage docs to determine the valid options (i.e. resource names) for that class. Quoting the help file:
Help on class PhotoImage in module tkinter:
class PhotoImage(Image)
| Widget which can display colored images in GIF, PPM/PGM format.
|
| Method resolution order:
| PhotoImage
| Image
| builtins.object
|
| Methods defined here:
|
| __getitem__(self, key)
| # XXX config
|
| __init__(self, name=None, cnf={}, master=None, **kw)
| Create an image with NAME.
|
| Valid resource names: data, format, file, gamma, height, palette,
| width.
FYI: The easiest way to get to the docs from Python at the command line or from IDLE:
from tkinter import PhotoImage
help(PhotoImage)
And lastly, another useful link about this class is at http://tkinter.unpythonic.net/wiki/PhotoImage.

I tested the example with python 2.7.9, 3.2.5, 3.3.5, 3.4.3 in 32bit and 64bit.
(Win 8.1 64bit)
The code works.
( in python 3.4.3 64bit I had first an error message.
I've completely uninstalled 3.4.3 and then reinstalled.
Now, the example works also with 3.4.3 64 bit )
# basic code from >>
# http://tkinter.unpythonic.net/wiki/PhotoImage
# extra code -------------------------------------------------------------------------
from __future__ import print_function
try:
import tkinter as tk
except:
import Tkinter as tk
import sys
import platform
print ()
print ('python ', sys.version)
print ('tkinter ', tk.TkVersion)
print ()
print (platform.platform(),' ',platform.machine())
print ()
# basic code -------------------------------------------------------------------------
root = tk.Tk()
def create_button_with_scoped_image():
# "w6.gif" >>
# http://www.inf-schule.de/content/software/gui/entwicklung_tkinter/bilder/w6.gif
img = tk.PhotoImage(file="w6.gif") # reference PhotoImage in local variable
button = tk.Button(root, image=img)
# button.img = img # store a reference to the image as an attribute of the widget
button.image = img # store a reference to the image as an attribute of the widget
button.grid()
create_button_with_scoped_image()
tk.mainloop()

Related

Viewing/Editing YAML content in a window using PySimpleGUI

I am learning python and PySimpleGUI seems like a good start for exercises. With this self-exercise I'm working on, I would like to view and edit a YAML file. So far, I am able to create a prompt to browse and select a yaml. I am able to print the data in the console. But my next step is to view the yaml view PySimpleGUI window. I will work on how to edit the yaml content once I can figure out how to display it.
Here is my code:
import PySimpleGUI as sg
import yaml
from yaml.loader import SafeLoader
import os
working_directory = os.getcwd()
layout = [
[sg.Text("Shoose your yaml file:")],
[sg.InputText(key="-FILE_PATH-"),
sg.FileBrowse(initial_folder=working_directory, file_types=[("YAML Files","*.yaml")])],
[sg.Button("Submit"), sg.Exit()],
[sg.Multiline(size=(30,5), key= data)]
]
window = sg.Window("File Loader", layout).Finalize()
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, 'Exit'):
break
elif event == "Submit":
file_path = values["-FILE_PATH-"];
with open(file_path) as f:
data = yaml.load(f, Loader=SafeLoader)
# print(data)
print(values[data])
window.close()
Running this code i get this error:
Traceback (most recent call last):
File "yaml_gui.py", line 13, in <module>
[sg.Multiline(size=(30,5), key= data)]
NameError: name 'data' is not defined
I'm stuck because I am not sure why it is returning this error. The code works if I decide to just print the results in my terminal by using print(data). But when I use print(values[data]), it doesn't work.

Python Time based rotating file handler for logging

While using time based rotating file handler.Getting error
os.rename('logthred.log', dfn)
WindowsError: [Error 32] The process cannot access the file because it
is being used by another process
config :
[loggers]
keys=root
[logger_root]
level=INFO
handlers=timedRotatingFileHandler
[formatters]
keys=timedRotatingFormatter
[formatter_timedRotatingFormatter]
format = %(asctime)s %(levelname)s %(name)s.%(functionname)s:%(lineno)d %
(output)s
datefmt=%y-%m-%d %H:%M:%S
[handlers]
keys=timedRotatingFileHandler
[handler_timedRotatingFileHandler]
class=handlers.TimedRotatingFileHandler
level=INFO
formatter=timedRotatingFormatter
args=('D:\\log.out', 'M', 2, 0, None, False, False)
Want to achieve time based rotating file handler and multiple process can write same log file.In python,I didn't find any thing which can help to resolve this issue.
I have read discussion on this issue (python issues).
Any suggestion which can resolve this issue.
Found the solution : Problem in Python 2.7 whenever we create child Process then file handles of parent process also inherited by child process so this is causing error. We can block this inheritance using this code.
import sys
from ctypes import windll
import msvcrt
import __builtin__
if sys.platform == 'win32':
__builtin__open = __builtin__.open
def __open_inheritance_hack(*args, **kwargs):
result = __builtin__open(*args, **kwargs)
handle = msvcrt.get_osfhandle(result.fileno())
if filename in args: # which filename handle you don't want to give to child process.
windll.kernel32.SetHandleInformation(handle, 1, 0)
return result
__builtin__.open = __open_inheritance_hack

Python error: one of the arguments is required

I'm trying to run a code from github that uses Python to classify images but I'm getting an error.
here is the code:
import argparse as ap
import cv2
import imutils
import numpy as np
import os
from sklearn.svm import LinearSVC
from sklearn.externals import joblib
from scipy.cluster.vq import *
# Get the path of the testing set
parser = ap.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("-t", "--testingSet", help="Path to testing Set")
group.add_argument("-i", "--image", help="Path to image")
parser.add_argument('-v',"--visualize", action='store_true')
args = vars(parser.parse_args())
# Get the path of the testing image(s) and store them in a list
image_paths = []
if args["testingSet"]:
test_path = args["testingSet"]
try:
testing_names = os.listdir(test_path)
except OSError:
print "No such directory {}\nCheck if the file exists".format(test_path)
exit()
for testing_name in testing_names:
dir = os.path.join(test_path, testing_name)
class_path = imutils.imlist(dir)
image_paths+=class_path
else:
image_paths = [args["image"]]
and this is the error message I'm getting
usage: getClass.py [-h]
(- C:/Users/Lenovo/Downloads/iris/bag-of-words-master/dataset/test TESTINGSET | - C:/Users/Lenovo/Downloads/iris/bag-of-words-master/dataset/test/test_1.jpg IMAGE)
[- C:/Users/Lenovo/Downloads/iris/bag-of-words-master/dataset]
getClass.py: error: one of the arguments - C:/Users/Lenovo/Downloads/iris/bag-of-words-master/dataset/test/--testingSet - C:/Users/Lenovo/Downloads/iris/bag-of-words-master/dataset/test/test_1.jpg/--image is required
can you please help me with this? where and how should I write the file path?
This is an error your own program is issuing. The message is not about the file path but about the number of arguments. This line
group = parser.add_mutually_exclusive_group(required=True)
says that only one of your command-line arguments (-t, -i) is permitted. But it appears from the error message that you are supplying both --testingSet and --image on your command line.
Since you only have 3 arguments, I have to wonder if you really need argument groups at all.
To get your command line to work, drop the mutually-exclusive group and add the arguments to the parser directly.
parser.add_argument("-t", "--testingSet", help="Path to testing Set")
parser.add_argument("-i", "--image", help="Path to image")
parser.add_argument('-v',"--visualize", action='store_true')

Best Way of redirecting output to a VTE terminal

Which is the best way of redirect the output of a command to a VTE terminal?
i came with this idea:
On the VTE execute:
tty > /usr/tmp/terminal_number
then read the file from the python program:
with open('/usr/tmp/terminal_number', 'r') as f:
self.VTE_redirect_path=f.readline()
then execute the bash commands, for exemple:
os.system('''echo "foo" > {0}'''.format(self.VTE_redirect_path))
The problem of this method is that the file terminal_number containing /dev/pts/# needs to be refreshed. Also i don't really like the idea of having to create files to communicate. Is there any direct solution?
#Quentin The solution that you gave me prints the console output really bad (it doesn't indents) so i had to use my solution. Here is a clear example:
from gi.repository import Gtk, GObject, Vte, GLib
import os, time, threading
def command_on_VTE(self,command):
length=len(command)
self.terminal.feed_child(command, length)
class TheWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="inherited cell renderer")
self.set_default_size(600, 300)
self.terminal=Vte.Terminal()
self.terminal.fork_command_full(
Vte.PtyFlags.DEFAULT, #default is fine
os.environ['HOME'], #where to start the command?
["/bin/bash"], #where is the emulator?
[], #it's ok to leave this list empty
GLib.SpawnFlags.DO_NOT_REAP_CHILD,
None, #at least None is required
None,
)
#set up the interface
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
#a scroll window is required for the terminal
scroller = Gtk.ScrolledWindow()
scroller.set_hexpand(True)
scroller.set_vexpand(True)
scroller.add(self.terminal)
box.pack_start(scroller, False, True, 2)
self.add(box)
#To get the command to automatically run
#a newline(\n) character is used at the end of the
#command string.
command_on_VTE(self,'''tty > /tmp/terminal_number\n''') # Get the terminal ID
# read the terminal ID
while not os.path.exists("/tmp/terminal_number"):
time.sleep(0.1)
with open('/tmp/terminal_number', 'r') as f:
self.VTE_redirect_path=f.readline()
os.remove('/tmp/terminal_number')
# this cleans the vte
os.system('''printf "\\033c" > {0}'''.format(self.VTE_redirect_path))
# this calls the exemple
threading.Thread(target=self.make_a_test).start()
def make_a_test(self):
os.system('''ls -laR /home/ > {rdc}
echo "-------- The listing ended -------
Note that the input of the commands are not printed
" > {rdc}'''.format(rdc=self.VTE_redirect_path))
win = TheWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
I haven't found a way of getting the Terminal ID with out passing for the creation of a temporary file. This could be skipped if there is some way to pass a variable from the VTE to the python script. Any help on this would be great!
In VTE you use terminal.feed("string")
See vte_terminal_feed.
With python Popen is the suggested method to execute commands.
If you are wanting to use commands then you should do this.
#Uncomment the next line to get the print() function of python 3
#from __future__ import print_function
import os
import subprocess
from subprocess import Popen
command = "echo \"something\""
env = os.environ.copy()
try:
po = Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
universal_newlines=True, env=env)
po.wait()
output, error_output = po.communicate()
if po.returncode:
print(error_output)
else:
print(output)
except OSError as e:
print('Execution failed:', e, file=sys.stderr)
If you want to use gtk with gtk vte then do this instead.
#place the following in a method of a vte instance
env = os.environ.copy()
try:
po = Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
universal_newlines=True, env=env)
po.wait()
output, error_output = po.communicate()
if po.returncode:
print(error_output)
else:
self.feed(output) #here you're printing to your terminal.
except OSError as e:
print('Execution failed:', e, file=sys.stderr)
For the finest control in a regular terminal you can try the cmd module. This will require that you produce your own prompt so it is a more specific option to get what you want.

GAE + Python2.7 + webapp2 + AJAX

Are there any tutorials or code examples related to AJAX implementation for GAE + Python2.7 + webapp2.
I have tried to follow instructions below:
http://code.google.com/appengine/articles/rpc.html
but I receive the following error:
Traceback (most recent call last):
File "E:\dev\workspace\test\webapp2.py", line 1536, in __call__
rv = self.handle_exception(request, response, e)
File "E:\dev\workspace\test\webapp2.py", line 1530, in __call__
rv = self.router.dispatch(request, response)
File "E:\dev\workspace\test\webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "E:\dev\workspace\test\webapp2.py", line 1101, in __call__
handler = self.handler(request, response)
TypeError: __init__() takes exactly 1 argument (3 given)
There is another similar discussion here:
Google App Engine Python Protorpc Error: __call__() takes exactly 1 argument (3 given)
heres is my code from Specialscope's example:
main.py
from BaseHandler import BaseHandler
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
import logging
from google.appengine.api import files
from google.appengine.api import images
import json
import webapp2
class FileuploadHandler(BaseHandler):
def get(self):
blobstore.create_upload_url('/static')
context={}
self.render_response("uploader.html",**context)
class FileDownloadHandler(blobstore_handlers.BlobstoreUploadHandler,BaseHandler):
def post(self):
upload_files=self.request.POST
#image=upload_files['file']
logging.error(upload_files)
keys=upload_files.keys()
imageurls=[]
for key in keys:
if key.find("uploadimage")!=-1:
image=upload_files[key]
file_name=files.blobstore.create(mime_type='image/jpg')
with files.open(file_name,'a') as f:
f.write(image.value)
files.finalize(file_name)
blob_key=files.blobstore.get_blob_key(file_name)
imageurls.append(images.get_serving_url(blob_key))
context={}
context['imagelinks']=imageurls
self.response.write(json.dumps(context))
app = webapp2.WSGIApplication([
('/upload', FileuploadHandler),
('/download', FileDownloadHandler),
], debug = True)
BaseHandler.py
import webapp2
import os
from webapp2_extras import jinja2
from google.appengine.ext import db
class BaseHandler(webapp2.RequestHandler):
#webapp2.cached_property
def jinja2(self):
# Returns a Jinja2 renderer cached in the app registry.
return jinja2.get_jinja2(app=self.app)
def render_response(self, _template, **context):
# Renders a template and writes the result to the response.
rv = self.jinja2.render_template(_template, **context)
self.response.write(rv)
The stack trace suggests that you have a url mapping in your WSGIApplication that has a group in it, but there's no handler with the corresponding arguments.
If you have
(r'/foo/(\s+)/(\s+)', FooHandler),
then you need
class FooHandler(webapp2.RequestHandler):
def get(self, arg1, arg2):
...
The doc you're using pre-dates Python 2.7 support by several years. Were I in your position, I'd be tempted to get the app working first on Python 2.5, then port to 2.7.
The problem is here:
import webapp2
app = webapp2.WSGIApplication([
('/upload', FileuploadHandler),
('/download', FileDownloadHandler),
], debug = True)
You can't use webapp2.WSGIApplication to construct your application, it doesn't understand protorpc. Instead, do this:
from protorpc.wsgi import service
app = service.service_mappings([
('/upload', FileuploadHandler),
('/download', FileDownloadHandler),
])

Resources