0

I have a tkinter GUI that displays an image, and I want to make a button that rotates it 90 degrees when I click it. I am using PIL, so I tried the rotate() function and all it does when I click it is scoot the image down the window. I have tried several other ways to rotate it and nothing seems to work. I am trying to build this rotate button within a class in my program. Does anyone know a good way to do this? Also, here's where I use rotate() where it's not actually rotating

class showIMG:
   def __init__(self, frame):
      self.frame = frame
      self.button = Button(self.frame, text="Show", command=self.show)
      self.button.pack()
      self.button1 = Button(self.frame, text="Rotate", command=self.rotate)
      self.button1.pack()
 
   def show(self):
      #image is created here from an array, which gives me a png, then I have:
      self.img = Image.open("spec_img.png")
      self.img1 = ImageTk.PhotoImage(self.img)
      self.label = Label(window, image = self.img1)
      self.label.pack()
     
   def rotate(self):
      self.img = Image.open("img.png")
      self.img = self.img.rotate(90)
      self.img1 = ImageTk.PhotoImage(self.img)
      self.label = Label(window, image=self.img1)
      self.label.pack()

I do see that I am reloading the image over and over again, but I'm not sure how I would do it such that a) I don't have to keep reloading it and b) it doesnt try to draw over itself

  • 1
    At the moment, each time the rotate function is called, the image is loaded from the file and then rotated. If you want to just rotate the image, you don't need to reload it every time. Please describe the current behaviour in more detail and perhaps include the code for the button, so that we can help you better. – Alex V. Mar 30 '23 at 17:39
  • @AlexV. that's all i have for the rotate function. the image is generated by a function called show() and it makes, saves and displays a png. how would i be able to rotate the image that is being displayed without reloading it every time? – lordclyborne Mar 30 '23 at 17:53
  • 1
    you could put self.img = Image.open("img.png") inside __init__ instead of rotate. That way it would just get loaded once, when you create an instance of the class showIMG. I have never used labels to put images on a tkinter window, but maybe the issue of incorrect positioning stems from using pack. Maybe use place instead of pack? https://www.activestate.com/resources/quick-reads/how-to-add-images-in-tkinter/ – Alex V. Mar 30 '23 at 17:57
  • This answer is easier. https://stackoverflow.com/questions/75116418/how-to-rotate-a-image-in-python-tkinter-window – toyota Supra Mar 30 '23 at 18:43
  • @toyotaSupra no because that user wants to animate their rotation – lordclyborne Mar 30 '23 at 18:49
  • @JRiggles no because that user wants to animate their rotation – lordclyborne Mar 30 '23 at 18:49
  • @AlexV. that still does not rotate the image. It just scoots down the window each time i click the button – lordclyborne Mar 30 '23 at 18:51
  • @lordclyborne Please update your question, with the new code. Maybe the issue comes from that you just redefine self.label, without properly removing the existing label that is associated to that variable. Try adding a self.label.destroy() before self.label = Label(...) in rotate. Also, it would be good to put self.label into __init__ as well, so that it is not defined solely in the methods. – Alex V. Mar 30 '23 at 19:01

1 Answers1

1

You should not load the image inside rotate() since it is the job of show(). Also you should not create new label widget to show the image inside rotate(), create the label inside show().

Below is the modified code:

class showIMG:
    def __init__(self, frame):
        self.frame = frame
        self.label = None  # initialize an instance variable for the label
        self.button = Button(self.frame, text="Show", command=self.show)
        self.button.pack()
        self.button1 = Button(self.frame, text="Rotate", command=self.rotate)
        self.button1.pack()

    def show(self):
        if self.label is None:
            # create the label with the wanted image
            self.img = Image.open("img.png")
            self.img1 = ImageTk.PhotoImage(self.img)
            # reserve enough space for the rotation of image
            size = max(self.img.width, self.img.height)
            self.label = Label(self.frame, image = self.img1, width=size, height=size)
            self.label.pack()

    def rotate(self):
        # make sure an image is already loaded in a label
        if self.label:
            self.img = self.img.rotate(90, expand=1)
            self.img1 = ImageTk.PhotoImage(self.img)
            self.label.config(image=self.img1)
acw1668
  • 40,144
  • 5
  • 22
  • 34