简体   繁体   中英

Background picture in turtle.TurtleScreen() does not show correctly in tkinter

Code 1: Creates a Tk() window, a Frame() , Canvas() to host a turtle.TurtleScreen() with a certain background picture. The dimensions of these widgets are not defined at the outset. Instead, they are defined after widget creation using the tkinter's .configure() method and turtle's .screensize() method. The issue here is that the background picture does not appear correctly even though the turtle screensize appears correct.

Code 2: It does the same job as Code 1 except that it first obtains the size of the image and uses it to define the size of the Canvas widget first before displaying it as the background image of turtle.TurtleScreen() . The background image does appear correctly.

Questions:

  1. Why does the issue occur in code 1 and how to overcome the issue, ie correctly show a background image in turtle.TurtleScreen() in the event of a change in background image size?
  2. Why is the sizes of Frame and Canvas widgets 2 pixel larger for code 1 than for code 2, even though the Canvas is defined with borderwidth=0 ? Is this something to do with the Canvas's default borderwidth=2?

Code 1:

import tkinter as tk
import turtle as tt


root = tk.Tk()

def getsize( widget ):
    widget.update_idletasks()
    w = widget.winfo_width()
    h = widget.winfo_height()
    print( 'w={}, h={}\n'.format(w,h) )
    return w,h

app = tk.Frame( root,  )
canvas = tk.Canvas( app, bg='yellow', borderwidth=0, )
app.grid( row=0, column=0, sticky='nsew' ) 
canvas.grid( row=0, column=0, sticky='nsew' )
print('\nFrame'); aw, ah = getsize( app )
print('canvas'); cw, ch = getsize( canvas )

pic = 'test.gif'
screen = tt.TurtleScreen( canvas )
screen.bgpic( pic )
screen.bgcolor( 'pink' )
screen.update()
print( 'Turtle :' )
print( 'screen size = ', screen.screensize() )
print( 'screen attributes = ', screen.__dict__ )
print( 'screen.bgpic() = ', screen.bgpic() )
photoimage = screen._bgpics[pic]
pw = photoimage.width()
ph = photoimage.height()
print( '\nphotoimage width={} height={}'.format( pw, ph) )

canvas.configure( width=pw+2, height=ph+2 )
screen.screensize( pw+2, ph+2 )
screen.bgpic( pic )

print('\nFrame'); aw, ah = getsize( app )
print('canvas'); cw, ch = getsize( canvas )

Code 2:

import tkinter as tk
import turtle as tt


root = tk.Tk()

pic ='test.gif'
image = tk.PhotoImage( file=pic )
iw = image.width()
ih = image.height()
print( 'image width={} height={}\n'.format( iw, ih) )

def getsize( widget ):
    widget.update_idletasks()
    w = widget.winfo_width()
    h = widget.winfo_height()
    print( 'w={}, h={}\n'.format(w,h) )
    return w,h

app = tk.Frame( root, )
canvas = tk.Canvas( app, width=iw, height=ih, bg='yellow', borderwidth=0 )
app.grid( row=0, column=0, sticky='nsew' ) 
canvas.grid( row=0, column=0, sticky='nsew' )
print('Frame'); aw, ah = getsize( app )
print('canvas'); cw, ch = getsize( canvas )

screen = tt.TurtleScreen( canvas )
screen.bgpic( pic )
screen.bgcolor( 'pink' )
screen.update()
print( 'Turtle :' )
print( 'screen size = ', screen.screensize() )
print( 'screen attributes = ', screen.__dict__ )
print( 'screen.bgpic() = ', screen.bgpic() )
photoimage = screen._bgpics[pic]
pw = photoimage.width()
ph = photoimage.height()
print( '\nphotoimage width={} height={}'.format( pw, ph) )

Answer to Q1:

After further research, I discovered TurtleScreen() has an attribute called .cv to point to the tk.Canvas widget that is passed into it. As with all tk.Canvas widget, there is a need to update(ie configure) its scrollregion to show the new visible area of the tk.Canvas when there is a change. The "scrollregion" option states how large an area the canvas can be scrolled.

So the changes to Code 1, I needed to replace:

canvas.configure( width=pw+2, height=ph+2 )
screen.screensize( pw+2, ph+2 )
screen.bgpic( pic )

with

canvas.configure( width=pw, height=ph, borderwidth=0 )
w = int(screen.cv.cget("width"))
h = int(screen.cv.cget("height"))
screen.cv.configure(scrollregion = (-w//2, -h//2, w//2+1, h//2 ))
print( '\nscreen.cv width={} height={}'.format( w, h) )

Answer to Q2:

The difference in the report Frame and Canvas sizes by 2 pixel was due to the +2 in used in Code 1:

canvas.configure( width=pw+2, height=ph+2 )

Instead, I should have used:

canvas.configure( width=pw, height=ph )

It seems that a Canvas does consume 1 row/column of pixel to form it's boundary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM