4

I have created a simple button program using turtle in Python. It is most likely very sloppy but works perfectly in IDLE. However, when trying to load it without IDLE it just draws the two buttons and then quits the program. I've looked over the code without any success on finding the cause.

Here's where I think the issue is (the last few lines):

def main():
    onscreenclick(Button.clicked,1)

main()

However I am not entirely sure. Here is the full program just in case.

from turtle import *
bgcolor('skyblue')
penup()
left(90)
speed(0)
hideturtle()
buttonlist = []

class Button:
  x_click = 0
  y_click = 0
  def __init__(self, x, y, size, color, text, fontsize, fixvalue):
    self.x = x
    self.y = y
    self.size = size
    self.color = color
    self.text = text
    self.fontsize = fontsize
    self.fixvalue = fixvalue
  def showButton(self):
    goto(self.x , self.y)
    pendown()
    fillcolor(self.color)
    begin_fill()
    for i in range(4):
      forward(self.size)
      right(90)
    end_fill()
    penup()
    goto((self.x+self.size/2),self.y+self.fixvalue)
    right(90)
    write(self.text, move=False, align="center", font=("Arial", self.fontsize, "normal"))
    left(90)
  def hideButton(self):
    goto(self.x, self.y)
    fillcolor('skyblue')
    pencolor('skyblue')
    pendown()
    begin_fill()
    for i in range(4):
      forward(self.size)
      right(90)
    end_fill()
    penup()
    pencolor('black')
  def checkClick(self):
    if self.x < Button.x_click:
      if Button.x_click < (self.x+self.size):
        if self.y < Button.y_click:
          if Button.y_click < (self.y+self.size):
            return 1

  def clicked(x, y):
    Button.x_click = x
    Button.y_click = y

    if home_1.checkClick() == 1:
      home_1.hideButton()
    if home_2.checkClick() == 1:
      home_2.hideButton()

home_1 = Button(10,10,100,'red','←',45,20)
home_2 = Button(-50,-50,50,'blue','Hello!',10,15)
Button.showButton(home_1)
Button.showButton(home_2)

def main():
    onscreenclick(Button.clicked,1)

main()

I hope there is a solution.

Cheers.

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52
Jakey Snakey
  • 95
  • 1
  • 1
  • 7
  • 2
    Please add your code using a code block instead of a link to some web service and provide a [MCVE](https://stackoverflow.com/help/mcve) – albert Sep 15 '17 at 12:40
  • 1
    I highly recommend you to stop using the `from turtle import *` and instead just do `import turtle` and use the functions through `turtle.penup()` etc. It might feel stupid now to write the same thing over and over again everywhere, but your future self will thank you. Importing a lot of short names like this will get really confusing really quickly. – Markus Meskanen Sep 15 '17 at 12:52
  • Or `import turtle as tt` for instance, and use `tt.penup()`, etc. – Terry Jan Reedy Jul 22 '21 at 17:51

2 Answers2

3

You're right that the issue lies in the main() function, try adding a turtle.mainloop() call to the end:

def main():
    onscreenclick(Button.clicked,1)
    mainloop()

main()

If that doesn't work for you, you can also try the turtle.done() function, although I recommend you to try mainloop() first:

def main():
    onscreenclick(Button.clicked,1)
    done()

main()
Markus Meskanen
  • 19,939
  • 18
  • 80
  • 119
0

turtle is based on tkinter, which is based on the tcl/tk GUI framework. Turtle's mainloop ultimately calls the tcl event-handler mainloop, which repeatedly calls tcl's update() function, which handles pending events and update the screen. Tcl's mainloop keeps control until it is explicitly exited, such as by closing the turtle window.

IDLE aids turtle and tkinter development and learning by periodically calling tcl's update without blocking, so that one can (temporarily) omit calling mainloop and interact with the screen or screens one is working on by entering commands in the IDLE Shell. But mainloop needs to be added back when running outside of IDLE.

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52