英文:
How to place an transparent image on top of another image (Tkinter)
问题
在代码的第68到100行中,您将棋盘上的棋子放置到窗口上。在110行,您将棋盘作为背景放置。然而,当运行代码时,棋子看起来不是透明的。这可能是由于图像文件中的透明通道被正确解释,但在放置图像时没有指定透明度。
为了使棋子看起来透明,您需要确保将图像的透明度信息保留,并在将其放置到窗口上时正确处理透明度。在tk.PhotoImage
中,您可以使用format
参数来指定图像的文件格式,以确保透明度正确解释。例如,如果您的图像是PNG格式,并且包含透明度信息,您可以这样使用:
wQueen = tk.PhotoImage(file=r'C:\Users\benja\Documents\Python\Chess project\wQueen.png', format='png')
这将确保图像中的透明通道被正确解释,使棋子看起来透明。
如果您的图像格式不是PNG,您需要使用正确的格式参数来处理透明度。确保在tk.PhotoImage
中为每个图像文件都设置正确的格式参数。
英文:
My embarrassing and likely flame-able code (which will eventually turn into a chess game)
import chess
#from stockfish import Stockfish
import tkinter as tk
import time
board = chess.Board()
def boardtoarr(board): #converts chess board string to 2d array
boardlist = []
linelist = []
for b in range(0,128,2):
linelist.append(str(board)[b])
if len(linelist) == 8:
boardlist.append(linelist)
linelist = []
return boardlist
#given the square of a piece on the board, returns the legal squares the piece can move to
def piecelegalmoves(square,cboard):
ans = ''
for a in cboard.legal_moves:
a = str(a)
if a[0:2] == square:
ans += a[2::]+' '
return ans
def alllegalmoves(cboard):
x = str(cboard.legal_moves)[38:-2]
x = x.split(', ')
return x
squarevariable = ''
def squareclicked(event):
global squarevariable
print(topleftpixelstosquare(event.x,event.y))
print(lsquaretocsquare(topleftpixelstosquare(event.x,event.y)))
squarevariable = lsquaretocsquare(topleftpixelstosquare(event.x,event.y))
def topleftpixels(x,y): #returns top left pixel of given square
return [x*100,y*100]
def topleftpixelstosquare(x,y):
x = ('000' + str(x))
x = x[len(x)-3::]
y = ('000' + str(y))
y = y[len(y)-3::]
return [int(y[0]),int(x[0])]
def csquaretolsquare(square): #converts chess square notation to list square notation
ans = []
letterorder = 'abcdefgh'
ans.append(8-int(square[1]))
ans.append(letterorder.index(square[0]))
return ans
def lsquaretocsquare(square): #converts list square notation to chess square notation
ans = ''
letterorder = 'abcdefgh'
ans += (letterorder[square[1]])
ans += str(8-square[0])
return ans
def boardtoimage(root,boardstr): #places all pieces onto the window graphically
global wQueen,wKing,wKnight,wBishop,wPawn,wRook,bQueen,bKing,bKnight,bBishop,bPawn,bRook
for y in range(8):
for x in range(8):
piece = boardtoarr(boardstr)[y][x]
xcoord = topleftpixels(x,y)[0]
ycoord = topleftpixels(x,y)[1]
if piece == 'Q':
tk.Label(root, image = wQueen).place(x = xcoord,y = ycoord)
if piece == 'K':
tk.Label(root, image = wKing).place(x = xcoord,y = ycoord)
if piece == 'R':
tk.Label(root, image = wRook).place(x = xcoord,y = ycoord)
if piece == 'P':
tk.Label(root, image = wPawn).place(x = xcoord,y = ycoord)
if piece == 'B':
tk.Label(root, image = wBishop).place(x = xcoord,y = ycoord)
if piece == 'N':
tk.Label(root, image = wKnight).place(x = xcoord,y = ycoord)
if piece == 'q':
tk.Label(root, image = bQueen).place(x = xcoord,y = ycoord)
if piece == 'k':
tk.Label(root, image = bKing).place(x = xcoord,y = ycoord)
if piece == 'r':
tk.Label(root, image = bRook).place(x = xcoord,y = ycoord)
if piece == 'p':
tk.Label(root, image = bPawn).place(x = xcoord,y = ycoord)
if piece == 'b':
tk.Label(root, image = bBishop).place(x = xcoord,y = ycoord)
if piece == 'n':
tk.Label(root, image = bKnight).place(x = xcoord,y = ycoord)
def CMI_clicked(): #check if the chess menu image was clicked
global root
global BoardImage
for widget in root.winfo_children(): #code to clear page
widget.destroy()
boardbackground = tk.Label(root, image = BoardImage) #place the board image at the background
boardbackground.pack()
board.push_san('e2e4')
boardtoimage(root,str(board))
#while True:
#print('x')
#boardstr = str(board)
root.bind('<Button-1>', squareclicked)
def Menu():
global root
global ChessMenuImage
#Menu
ChessMenuOption = tk.Button(root ,image = ChessMenuImage, command = CMI_clicked) #create button using chess menu image and call function 'CMI_clicked' when pressed
ChessMenuOption.place(x = 380, y = 380) #place the chess menu image at given coordinates
root = tk.Tk()
ChessMenuImage = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\Chess_Selection_Image.png') #Load chess menu image file
BoardImage = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\ChessBoardImage.png') #Load board image file
#Piece image loading
#White
wQueen = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wQueen.png')
wKing = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wKing.png')
wPawn = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wPawn.png')
wBishop = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wBishop.png')
wKnight = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wKnight.png')
wRook = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wRook.png')
#Black
bQueen = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bQueen.png')
bKing = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bKing.png')
bPawn = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bPawn.png')
bBishop = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bBishop.png')
bKnight = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bKnight.png')
bRook = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bRook.png')
root.geometry('800x800')
Menu()
root.mainloop()
lines 68-100 is where I'm placing the pieces, line 110 is where I'm placing the board as the background. However when I run the code it looks like this:
I know by running this code:
import tkinter as tk
win = tk.Tk()
photoimage = tk.PhotoImage(file=r'C:\Users\benja\Documents\Python\Chess project\wQueen.png')
width, height = photoimage.width(), photoimage.height()
canvas = tk.Canvas(win, bg="blue", width=width, height=height)
canvas.pack()
canvas.create_image(0, 0, image=photoimage, anchor='nw')
win.mainloop()
that python recognizes the pieces as transparent as it returns this
What am I doing wrong?
答案1
得分: 1
由于您在显示棋盘和棋子的图像上使用了Label
小部件,而Label
不支持透明背景。
正如您的第二个示例所示,您可以使用Canvas
来显示透明图像。下面是修改后的boardtoimage()
和CMI_clicked()
函数,以使用Canvas
而不是Label
:
...
def boardtoimage(root, boardstr): #将所有棋子以图形方式放在窗口上
piece_mapping = {
'r': bRook, 'n': bKnight, 'b': bBishop, 'q': bQueen, 'k': bKing, 'p': bPawn,
'R': wRook, 'N': wKnight, 'B': wBishop, 'Q': wQueen, 'K': wKing, 'P': wPawn,
}
for y in range(8):
for x in range(8):
piece = boardtoarr(boardstr)[y][x]
# 获取相应的棋子图像
image = piece_mapping.get(piece, None)
if image:
xcoord = topleftpixels(x,y)[0]
ycoord = topleftpixels(x,y)[1]
# 显示棋子图像
canvas.create_image(xcoord, ycoord, image=image, anchor="nw")
def CMI_clicked(): #检查是否单击了棋盘图像
global canvas
for widget in root.winfo_children(): #清除页面的代码
widget.destroy()
# 创建用于显示透明图像的画布
canvas = tk.Canvas(root, width=BoardImage.width(), height=BoardImage.height(), highlightthickness=0)
canvas.pack()
# 显示棋盘图像
canvas.create_image(0, 0, image=BoardImage, anchor="nw")
board.push_san('e2e4')
boardtoimage(root, str(board))
root.bind('<Button-1>', squareclicked)
...
结果:
英文:
Since you have used Label
widgets to show the images of the board and chess piece and Label
does not support transparent background.
As your second example shows, you can use Canvas
to show those transparent images. Below are the modified boardtoimage()
and CMI_clicked()
functions to use Canvas
instead of Label
:
...
def boardtoimage(root, boardstr): #places all pieces onto the window graphically
piece_mapping = {
'r': bRook, 'n': bKnight, 'b': bBishop, 'q': bQueen, 'k': bKing, 'p': bPawn,
'R': wRook, 'N': wKnight, 'B': wBishop, 'Q': wQueen, 'K': wKing, 'P': wPawn,
}
for y in range(8):
for x in range(8):
piece = boardtoarr(boardstr)[y][x]
# get the corresponding piece image
image = piece_mapping.get(piece, None)
if image:
xcoord = topleftpixels(x,y)[0]
ycoord = topleftpixels(x,y)[1]
# show the piece image
canvas.create_image(xcoord, ycoord, image=image, anchor="nw")
def CMI_clicked(): #check if the chess menu image was clicked
global canvas
for widget in root.winfo_children(): #code to clear page
widget.destroy()
# create the canvas to show those transparent images
canvas = tk.Canvas(root, width=BoardImage.width(), height=BoardImage.height(), highlightthickness=0)
canvas.pack()
# show the chess board image
canvas.create_image(0, 0, image=BoardImage, anchor="nw")
board.push_san('e2e4')
boardtoimage(root,str(board))
root.bind('<Button-1>', squareclicked)
...
Result:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论