如何在另一张图像上放置一个透明图像(Tkinter)

huangapple go评论68阅读模式
英文:

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: 如何在另一张图像上放置一个透明图像(Tkinter)

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

如何在另一张图像上放置一个透明图像(Tkinter)

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)

...

结果:

如何在另一张图像上放置一个透明图像(Tkinter)

英文:

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 = {
        &#39;r&#39;: bRook, &#39;n&#39;: bKnight, &#39;b&#39;: bBishop, &#39;q&#39;: bQueen, &#39;k&#39;: bKing, &#39;p&#39;: bPawn,
        &#39;R&#39;: wRook, &#39;N&#39;: wKnight, &#39;B&#39;: wBishop, &#39;Q&#39;: wQueen, &#39;K&#39;: wKing, &#39;P&#39;: 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=&quot;nw&quot;)


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=&quot;nw&quot;)

    board.push_san(&#39;e2e4&#39;)

    boardtoimage(root,str(board))

    root.bind(&#39;&lt;Button-1&gt;&#39;, squareclicked)

...

Result:

如何在另一张图像上放置一个透明图像(Tkinter)

huangapple
  • 本文由 发表于 2023年2月7日 03:30:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75365756.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定