-1

I'm working on a project that should automatically generate a "playing card" type of image.

I have a blank image with no text to work with. My original idea was to populate this blank image with text using Pillow. I do not think this is a good idea because:

  • There is no easy way to automatically place the text (always keep it horizontally centered but calculate the right height based on the contents)
  • To my knowledge, I can't autosize text. I essentially want a textbox, and if text gets too big the font size shrinks to fit rather than overflowing.

What is an alternative solution to this problem? I'm open to completely ditching any image libraries, I just don't know where to go from here.

Attached to this post is the blank image I previously referred to, as well as two images that demonstrate the desired result with "text fitting."

Thanks in advance.

123

Nash Anderson
  • 70
  • 1
  • 8

1 Answers1

0

I'm not sure what you want to do with the card image, but the below is an example of using a tk.Canvas to display the blank card with a text overlay.

Since the title and the description header are only one line, they are positioned by their absolute centers. The description is positioned by the top-left, so it will always start in the same spot, regardless of the amount of text it contains.

If you have any questions, ask them.

import tkinter     as     tk
from   tkinter     import EventType as tke
from   PIL         import Image, ImageTk, ImageGrab
from   dataclasses import dataclass


@dataclass
class Card(tk.Canvas):
    master     :tk.Widget
    blankname  :str 
    width      :int 
    height     :int
    title      :str  
    subtitle   :str    
    description:str   

    def __post_init__(self):
        tk.Canvas.__init__(self, self.master, width=self.width, height=self.height, highlightthickness=0)
        hw = self.width//2
        self.img_id = self.create_image(hw, self.height//2, image=self.blankname, tags=self.blankname)
        self.ttl_id = self.create_text(hw, 62 , width=300, font=('Ariel', 22, 'bold'), text=self.title)
        self.sub_id = self.create_text(hw, 340, width=300, font=('Ariel', 18), text=self.subtitle, justify=tk.CENTER)
        self.dsc_id = self.create_text(50, 360, width=300, font=('Ariel', 14), text=self.description, justify=tk.CENTER, anchor=tk.NW)

    #https://stackoverflow.com/a/38645917/10292330
    #this grabs a screenshot of the card at the exact position and size for the card
    def save(self, *args):
        root = self.nametowidget(self.winfo_toplevel())
        x=root.winfo_rootx()+self.winfo_x()
        y=root.winfo_rooty()+self.winfo_y()
        x1=x+self.winfo_width()
        y1=y+self.winfo_height()
        ImageGrab.grab().crop((x,y,x1,y1)).save(f'{self.title}.png')


class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.geometry('392x560')
        
        #must be loaded before we start making cards, as-well-as any other blanks
        self.blank           = ImageTk.PhotoImage(Image.open('blank.png'), name='blank')
        #base kwargs for ALL cards that use THIS blank
        blank_kwargs         = {'blankname':'blank', 'width':self.blank.width(), 'height':self.blank.height()}
        
        #symbiotic link data
        sym_link_desc  = (
            "Activate while over an ally to buff them "
            "or activate while over an opponent to defuff them. "
            "The links you create are destroyed when you receive damage from a non-ally."
        )
        sym_link_kwargs = {
            **blank_kwargs, 
            'title':'Symbiotic Link', 
            'subtitle':'Linkstrider', 
            'description':sym_link_desc
        }
        
        #symbiotic sustain data ~ 
        #whoops @ "while while" ~ you get the point
        #I left it cause I'm not remaking the image
        sym_sustain_desc  = (
            "Activate while while linked to an enemy "
            "to leech their health for a short duration. "
            "The leeching ends if you are hit in it's duration."
        )
        sym_sustain_kwargs = {
            **blank_kwargs, 
            'title':'Symbiotic Sustain', 
            'subtitle':'Linkstrider', 
            'description':sym_sustain_desc
        }
        
        #card
        self.card  = Card(self, **sym_link_kwargs)
        self.card.pack() 

        #press space to save
        self.bind('<space>', self.card.save)
        
       
if __name__ == '__main__':
    App().mainloop()

enter image description here enter image description here

Helpful Links:

  1. tk.Canvas
  2. tk.Canvas.create_image
  3. tk.Canvas.create_text
  4. tkinter docs main page
OneMadGypsy
  • 4,640
  • 3
  • 10
  • 26