2016-11-21 112 views
0

如何在鼠標點擊Zelle圖形中的某個點時讓鼠標執行某些操作?我試圖做的是當我點擊「startbutton」圖像時,使秒錶開始。但是,我顯然做錯了什麼,因爲我的程序崩潰或沒有做任何事情。如何讓鼠標點擊在特定點上做點什麼?

from graphics import * 
import time 
#from tkinter import * 

win = GraphWin('Stopwatch', 600, 600) 
win.yUp() 

#Assigning images 
stopWatchImage = Image(Point (300, 300), "stopwatch.png") 
startImage = Image(Point (210, 170), "startbutton.png") 
stopImage = Image(Point (390, 170), "stopbutton.png") 
lapImage = Image(Point (300, 110), "lapbutton.png") 


stopWatchImage.draw(win) 
startImage.draw(win) 
stopImage.draw(win) 
lapImage.draw(win) 


sec = 0 
minute = 0 
hour = 0 

def isBetween(x, end1, end2): 
'''Return True if x is between the ends or equal to either. 
The ends do not need to be in increasing order.''' 

    return end1 <= x <= end2 or end2 <= x <= end1 

def isInside(point, startImage): 
'''Return True if the point is inside the Rectangle rect.''' 

    pt1 = startImage.getP1() 
    pt2 = startImage.getP2() 
    return isBetween(point.getX(), pt1.getX(), pt2.getX()) and \ 
      isBetween(point.getY(), pt1.getY(), pt2.getY()) 


def getChoice(win):  #NEW 
'''Given a list choicePairs of tuples with each tuple in the form 
(rectangle, choice), return the choice that goes with the rectangle 
in win where the mouse gets clicked, or return default if the click 
is in none of the rectangles.''' 

    point = win.getMouse() 
    if isInside(point, startImage): 
     time.sleep(1) 
     sec += 1 
     timeText.setText(sec) 
     timeText.setText('') 


     while sec >= 0 and sec < 61: 

     #Displaying Time 
      timeText = Text(Point (300,260), str(hour) + ":" + str(minute) + ":" + str(sec)) 
      timeText.setSize(30) 
      timeText.draw(win) 
      time.sleep(1) 
      sec += 1 
      timeText.setText(sec) 
      timeText.setText('') 
      #Incrementing minutes,hours 
      if sec == 60: 
       sec = 0   
       minute += 1 

      if minute == 60: 
       sec = 0 
       minute = 0 
       hour += 1 


return default 


def layout() 
    getChoice(win) 

layout() 

我似乎無法得到它的工作。

編輯:添加了我的代碼的其餘部分進行澄清。

+0

編輯問題,突出顯示代碼,並使用按鈕'{}'正確地格式化代碼。現在你有錯誤的凹痕。 – furas

+0

我已編輯相應的代碼。 – Sammy

回答

0

您可以使用setMouseHandler來指定當您在窗口中單擊時調用的函數。

例如,如果您單擊窗口的左側部分,然後繪製矩形,如果您單擊窗口的右側部分,則繪製圓形。

您可以打開文件graphics.py並查看所有代碼。這是查看您可以使用哪些功能的最快方法。

from graphics import * 

# --- functions --- 

def on_click(point): 
    # inform function to use global variable 
    global win 

    if point.x > win.width//2: 
     c = Circle(point, 10) 
     c.draw(win) 
    else: 
     a = Point(point.x - 10, point.y - 10) 
     b = Point(point.x + 10, point.y + 10) 
     r = Rectangle(a, b) 
     r.draw(win) 

def main(): 
    # inform function to use global variable 
    global win 

    win = GraphWin("My Circle", 500, 500) 

    win.setMouseHandler(on_click) 

    win.getKey() 
    win.close() 

# --- start --- 

# create global variable 
win = None 

main() 

BTW:graphics使用Tkinter其中有小部件ButtonLabelText等,可以使用canvas.create_window()到小部件添加到畫布上。

Tkinter也有功能after(miliseconds, function_name)它可以讓你定期執行功能 - 即。更新時間。

from graphics import * 
import datetime 

# --- classes --- 

class _Widget(): 
    def __init__(self, x, y, w, h, **options): 
     self.x = x 
     self.y = y 
     self.w = w 
     self.h = h 
     self.options = options 

    def draw(self, canvas, **options): 
     return None 

    def set(self, **options): 
     self.widget.config(options) 

    def get(self, **options): 
     self.widget.cget(options) 

class Button(_Widget): 

    def draw(self, canvas, **options): 
     x, y = canvas.toScreen(self.x, self.y) # ??? 

     self.widget = tk.Button(canvas, self.options) 

     return canvas.create_window((x, y), options, width=self.w, height=self.h, window=self.widget, anchor='nw') 

class Label(_Widget): 

    def draw(self, canvas, **options): 
     x, y = canvas.toScreen(self.x, self.y) # ??? 

     self.widget = tk.Label(canvas, self.options) 

     return canvas.create_window((x, y), options, width=self.w, height=self.h, window=self.widget, anchor='nw') 

# --- functions --- 

def on_start(): 
    #global b1, b2 
    global running 

    b1.set(state='disabled') 
    b2.set(state='normal') 

    running = True 

    # run first time 
    update_time() 

    print("START") 

def on_stop(): 
    #global b1, b2 
    global running 

    b1.set(state='normal') 
    b2.set(state='disabled') 
    l.set(text="Controls:") 

    running = False 

    print("STOP") 

def update_time(): 
    #global l 
    #global running 

    if running: 

     l.set(text=datetime.datetime.now().strftime("%H:%M:%S")) 

     # run again after 1000ms (1s) 
     win.after(1000, update_time) 

# --- main --- 

def main(): 
    global win, l, b1, b2 

    win = GraphWin("My Buttons", 500, 500) 

    l = Label(0, 0, 100, 50, text="Controls:") 
    l.draw(win) 

    b1 = Button(100, 0, 100, 50, text="START", command=on_start) 
    b1.draw(win) 

    b2 = Button(200, 0, 100, 50, text="STOP", command=on_stop, state='disabled') 
    b2.draw(win) 

    win.getKey() 
    win.close() 

# --- global variable to access in functions --- 

win = None 
l = None 
b1 = None 
b2 = None 

running = False 

# --- start --- 

main() 

Tkinter的:CanvasButtonother


編輯:工作示例

from graphics import * 


def isBetween(x, end1, end2): 
    return end1 <= x <= end2 or end2 <= x <= end1 

def isInside(point, startImage): 
    x = startImage.getAnchor().getX() 
    y = startImage.getAnchor().getY() 
    w = startImage.getWidth()/2 
    h = startImage.getHeight()/2 

    pt1_x = x - w 
    pt1_y = y - h 

    pt2_x = x + w 
    pt2_y = y + h 

    return isBetween(point.getX(), pt1_x, pt2_x) and \ 
      isBetween(point.getY(), pt1_y, pt2_y) 


def getChoice(event): 
    global hour, minute, sec 
    global running 

    point = Point(round(event.x), round(event.y)) 

    if isInside(point, startImage): 
     sec = 0 
     minute = 0 
     hour = 0 
     running = True 
     update_time() 

    if isInside(point, stopImage): 
     running = False 


def update_time(): 
    global hour, minute, sec 
    #global timeText 
    #global win 

    sec += 1 

    if sec == 60: 
     sec = 0   
     minute += 1 
     if minute == 60: 
      minute = 0 
      hour += 1 

    timeText.setText('{}:{}:{}'.format(hour, minute, sec)) 

    if running: 
     win.after(1000, update_time) 
    else: 
     timeText.setText('') 


def layout(): 
    global win 
    global stopWatchImage 
    global startImage 
    global stopImage 
    global lapImage 
    global timeText 

    win = GraphWin('Stopwatch', 600, 600) 
    #win.yUp() 

    #Assigning images 
    stopWatchImage = Image(Point(300, 300), "stopwatch.png") 
    startImage = Image(Point(210, 170), "startbutton.png") 
    stopImage = Image(Point(390, 170), "stopbutton.png") 
    lapImage = Image(Point(300, 110), "lapbutton.png") 

    #Drawing images 
    stopWatchImage.draw(win) 
    startImage.draw(win) 
    stopImage.draw(win) 
    lapImage.draw(win) 

    timeText = Text(Point(300,260), '') 
    timeText.setSize(30) 
    timeText.draw(win) 

    win.setMouseHandler(getChoice) 

    win.getKey() 

# --- global variable --- 

win = None 

stopWatchImage = None 
startImage = None 
stopImage = None 
lapImage = None 

timeText = None 

running = False 

# --- start --- 

layout() 
+0

你好@furas,我編輯了我的問題來顯示我的代碼的其餘部分。我不太明白你給我看的東西。我是一個初學者,所以我不是很瞭解setMouseHandler等。Thank you – Sammy

+0

'setMouseHandler(function_name)'分配每次單擊鼠標時它將執行的函數。順便說一句:'function_name'意思是沒有'()'和參數的名字。 – furas

+0

明白了,所以我可以通過setMouseHandler來啓動計時器,但是我怎樣才能使它成爲當你有特定區域時,比如按鈕?我有一個秒錶的開始,停止和圈按鈕,每個人都需要分別做不同的事情。你想讓我發佈剩餘的代碼嗎?謝謝回覆。 – Sammy