I write on Python an GUI with dynamic resizing, I mean, if the height of all the elements of the window are more than the height of the window, the scrollbar appears on the right side, but if I resize the window and the height of all elements are less than the window, the scrollbar disappear.
I have made this using the <Configure> event. This is part of the code I have used:
mycanvas = Canvas(self.parent,bd=0,highlightthickness=0,relief='flat')
sbar = tk.Scrollbar(mycanvas,orient='vertical')
sbar.config(command=mycanvas.yview)
mycanvas.config(yscrollcommand=sbar.set)
def canvasscroll(event):
mycanvas.yview('scroll',int(-1*(event.delta/120)), "units")
def resizecanvas(event):
if self.mainyposition > event.height: #mainyposition is the addition of the height of all widgets in screen
sbar.pack(side=RIGHT, fill=Y)
else:
sbar.forget()
print(event.height)
self.widgetname.bind_all("<MouseWheel>", canvasscroll)
self.widgetname.bind_all("<Configure>", resizecanvas)
Everything works well except for two issues:
First of all, when the window starts, the <Configure> event is called a few times, and print the height on screen, but the last time its called before the program stills on stand by is a height that is not the correct height of the window, so this causes that it shows unnecesarily the scrollbar. The problem solves itself once I resize the window and the event runs again, but the first run it fails doing this. Any way to solve this?
And second, during the resizing, the console doesn't show any errors, but when I close the window, it shows me an Exception in Tkinter Callback that references the pack() method of the scrollbar. I don't know how to solve this... The errors are this:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1702, in __call__
return self.func(*args)
File "Y:\Factory\GLP2-e Admin (Todos los archivos)\Nueva Interfaz\classmain.py", line 108, in resizecanvas
sbar.pack(side=RIGHT, fill=Y)
File "C:\Python34\lib\tkinter\__init__.py", line 2140, in pack_configure + self._options(cnf, kw))
_tkinter.TclError: bad window path name ".!canvas.!scrollbar"
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1702, in __call__
return self.func(*args)
File "Y:\Factory\GLP2-e Admin (Todos los archivos)\Nueva Interfaz\classmain.py", line 108, in resizecanvas
sbar.pack(side=RIGHT, fill=Y)
File "C:\Python34\lib\tkinter\__init__.py", line 2140, in pack_configure + self._options(cnf, kw))
_tkinter.TclError: bad window path name ".!canvas.!scrollbar"
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1702, in __call__
return self.func(*args)
File "Y:\Factory\GLP2-e Admin (Todos los archivos)\Nueva Interfaz\classmain.py", line 108, in resizecanvas
sbar.pack(side=RIGHT, fill=Y)
File "C:\Python34\lib\tkinter\__init__.py", line 2140, in pack_configure + self._options(cnf, kw))
_tkinter.TclError: bad window path name ".!canvas.!scrollbar"
[Finished in 22.3s]
Thanks to everyone.
Related
Althogh it works perfectly fine with built in turtle shapes it doesn't work with
new registered shapes.The error is pyimage1 doesn't exist and both my program and file are in the same directories
Here is the code
root=Tk()
import turtle
def image():
global img
img='batman.gif'
player=turtle.Turtle()
wn=turtle.Screen()
wn.register_shape(img)
player.shape(img)
B=Button(root,text='click',command=image).pack()```
The error shown is:```Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\dell\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\Users\dell\OneDrive\Desktop\imagetk.py", line 10, in image
player.shape(img)
File "C:\Users\dell\AppData\Local\Programs\Python\Python37\lib\turtle.py", line 2777, in shape
self.turtle._setshape(name)
File "C:\Users\dell\AppData\Local\Programs\Python\Python37\lib\turtle.py", line 2506, in _setshape
self._item = screen._createimage(screen._shapes["blank"]._data)
File "C:\Users\dell\AppData\Local\Programs\Python\Python37\lib\turtle.py", line 723, in _createimage
return self.cv.create_image(0, 0, image=image)
File "<string>", line 1, in create_image
File "C:\Users\dell\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 2489, in create_image
return self._create('image', args, kw)
File "C:\Users\dell\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 2480, in _create
*(args + self._options(cnf, kw))))
_tkinter.TclError: image "pyimage1" doesn't exist```
The problem is the way you're mixing turtle and tkinter is creating two roots which leads to this error. You're trying to use standalone turtle when you should be using embedded turtle. I.e. you should be using RawTurtle instead of Turtle and RawScreen instead of Screen. But don't just swap the names, look them up in the documentation. Your code should look roughly like:
from tkinter import *
from turtle import TurtleScreen, RawTurtle
IMAGE = 'batman.gif'
def image():
player = RawTurtle(screen)
player.shape(IMAGE)
root = Tk()
Button(root, text='click', command=image).pack()
canvas = Canvas(root)
canvas.pack()
screen = TurtleScreen(canvas)
screen.register_shape(IMAGE)
screen.mainloop()
I'm trying to write a tkinter program, and I came across an error that I've never seen before while working with tkinter. I've searched around everywhere, and tried everything I can think of. This is my code so far:
x=tk.Canvas(top,width=1000,height=750,bg="grey")
x.pack()
y=tk.PhotoImage(file="C:\\Users\\Admin\\Desktop\\images (3)_CnyokaDvJmG1xu.png")
x.create_image(top,0,0,image=y)`
and this is error
Traceback (most recent call last):
File "C:\Users\Admin\Anaconda3\lib\tkinter\__init__.py", line
1705, in __call__
return self.func(*args)
File "C:/Users/Admin/.spyder-py3/temp.py", line 16, in open
x.create_image(top,0,0,image=y).pack()
File "C:\Users\Admin\Anaconda3\lib\tkinter\__init__.py", line
2489, in create_image
return self._create('image', args, kw)
File "C:\Users\Admin\Anaconda3\lib\tkinter\__init__.py", line
2480, in _create
*(args + self._options(cnf, kw))))
_tkinter.TclError: bad screen distance "."
You don't have to supply containing widget when placing an image in a canvas, coordinates are enough:
x.create_image(0,0,image=y)
The error is because canvas does not accept a widget as coordinates.
I want to make an application, that uses Bash commands, but everytime it results in Exception in Tkinter callback.
I already have tried to use subprocess popen but there it even wanted to start the commands.
from tkinter import *
import os
# The following commands gets executed, if the user is pressing the action button
def button_action():
update_button.config(os.system('sudo -S pacman -Syu'), text="Aktualisiert!")
# create a window
fenster = Tk()
# set the title of the window
fenster.title("Befehlsammlung")
# create button and labels
update_label = Label(fenster, text="Drücke auf Aktualisieren, um alle Pakete zu updaten.",)
update_button = Button(fenster, text="Aktualisieren", command=button_action)
exit_button = Button(fenster, text="Schließen", command=fenster.quit)
# Add your components in your favourite
update_label.pack()
update_button.pack()
exit_button.pack()
# wait for input
fenster.mainloop()
I except the button changes to "Aktualisiert" and not the actual Exception error.
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.7/tkinter/__init__.py", line 106, in _cnfmerge
cnf.update(c)
TypeError: 'int' object is not iterable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/home/flozge/PycharmProjects/untitled1/GUI.py", line 7, in button_action
update_button.config(os.system('sudo -S pacman -Syu'), text="Aktualisiert!")
File "/usr/lib/python3.7/tkinter/__init__.py", line 1485, in configure
return self._configure('configure', cnf, kw)
File "/usr/lib/python3.7/tkinter/__init__.py", line 1469, in _configure
cnf = _cnfmerge((cnf, kw))
File "/usr/lib/python3.7/tkinter/__init__.py", line 109, in _cnfmerge
for k, v in c.items():
AttributeError: 'int' object has no attribute 'items'
Process finished with exit code 0
You don't need to pass the os.system('sudo -S pacman -Syu') call as an argument for the update_button.config for it to run. You just need to call it somewhere inside the button_action function, which will be triggered when "Aktalisieren" button is clicked as specified in line update_button = Button(fenster, text="Aktualisieren", command=button_action).
def button_action():
os.system('sudo -S pacman -Syu')
update_button.config(text="Aktualisiert!")
When I typed the following code as per the Think Python text book, I'm getting the error message below.
The window does actually get displayed, but it doesn't contain the desired content.
from swampy.World import World
world=World()
world.mainloop()
canvas = world.ca(width=500, height=500, background='white')
bbox = [[-150,-100], [150, 100]]
canvas.rectangle(bbox, outline='black', width=2, fill='green4')
The error message was like this:
Traceback (most recent call last):
File "15.4.py", line 4, in <module>
canvas = world.ca(width=500, height=500, background='white')
File "/usr/local/lib/python2.7/dist-packages/swampy/Gui.py", line 244, in ca
return self.widget(GuiCanvas, width=width, height=height, **options)
File "/usr/local/lib/python2.7/dist-packages/swampy/Gui.py", line 359, in widget
widget = constructor(self.frame, **widopt)
File "/usr/local/lib/python2.7/dist-packages/swampy/Gui.py", line 612, in __init__
Tkinter.Canvas.__init__(self, w, **options)
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 2234, in __init__
Widget.__init__(self, master, 'canvas', cnf, kw)
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 2094, in __init__
(widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: can't invoke "canvas" command: application has been destroyed
The main application loop needs to be pretty much the last thing you run in your application. So move world.mainloop() to the end of your code like this:
from swampy.World import World
world = World()
canvas = world.ca(width=500, height=500, background='white')
bbox = [[-150, -100], [150, 100]]
canvas.rectangle(bbox, outline='black', width=2, fill='green4')
world.mainloop()
What happens in your code is that when the line with world.mainloop() is hit, it builds the user interface elements and goes in to the main loop, which continuously provides your application with user input.
During it's lifetime, that main loop is where your application will spend 99% of its time.
But once you quit your application, the main loop terminates and tears down all those user interface elements and the world. Then the remaining lines after the main loop will be executed. In those, you're trying to build and attach a canvas to a world that has already been destroyed, hence the error message.
I want to display an icon on a menu bar, so using this information, I coded this:
img = Image.open("help.png")
menubar.add_cascade(label="Help",menu=helpmenu,bitmap=ImageTk.PhotoImage(img))
I got this error:
Traceback (most recent call last):
File "mine.py", line 67, in <module>
m.menus(root)
File "mine.py", line 55, in menus
menubar.add_cascade(label="Help",menu=helpmenu,bitmap=ImageTk.PhotoImage(img))
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 2699, in add_cascade
self.add('cascade', cnf or kw)
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 2696, in add
self._options(cnf, kw))
_tkinter.TclError: bitmap "pyimage2" not defined
How to fix this ?
To display a PhotoImage you should use the image attribute, not bitmap.
You can also simply open an image file directly using ImageTk.PhotoImage(file='...')
So you can use the following code to display your image in the menu:
img = ImageTk.PhotoImage(file="help.png")
menubar.add_cascade(label="Help", menu=helpmenu, image=img)