How to click a specific button? - python

I am new to python.
I am trying to make the game start, when the button "pull" is clicked.
But what I have, the game starts wherever I click in the win.
from graphics import*
from random import*
from time import*
def main():
# Creating the window
win = GraphWin("Clay Target Control Panel",400,400)
# "Pull" rectangle and color
pullrec = Rectangle(Point(150,290),Point(250,330))
pullrec.setFill("light salmon")
pullrec.draw(win)
pullmess = Text(Point(200,310),"PULL")
pullmess.setSize(11)
pullmess.setStyle("bold")
pullmess.draw(win)
# Start the game when "Pull" rectangle is clicked.
while True:
mouse = win.getMouse()
if pullrec:
win.getMouse()

I suspect that win.getMouse blocks, waiting for a mouse click. pullrec is bound to a rectangle. bool(<rectangle>) is True, so if rectangle always fires. You need to instead call some method that looks at where the mouse was clicked. I know how to do this with tkinter, but not graphics.

Related

Tkinter: How to get ALL widgets under the mouse cursor?

I'm trying to create a simple drag-and-drop interface in Tkinter using the canvas. However, I've hit a snag:
The event binds 'enter' and 'leave' seem to only work for the TOP-most widget under the cursor. E.g., I wrote this bit of code to try and recognize when the cursor is over the 'board' space or not:
self.canvas.create_rectangle(50, 50, 1250, 750, fill = 'grey', tag = 'Board')
self.canvas.tag_bind('Board', "<Enter>", self.on_board)
self.canvas.tag_bind('Board', "<Leave>", self.off_board)
self.mouse_on_board = False
def on_board(self, event):
self.mouse_on_board = True
def off_board(self, event):
self.mouse_on_board = False
But when the cursor enters a draggable item on the board (e.g. a canvas.create_image() image drawn on top of the 'board' rectangle) this is treated as the cursor leaving the board widget. Whereas for my purpose, I want the code to recognize it is still over the board (just over another widget which is itself drawn over the board).
Is there a simple way in Tkinter to know whether the cursor is on top of a widget REGARDLESS of whether there are any other widgets stacked above or beneath it?
Thanks in advance for any answers!

Autoclicker does not activate the window

I wanted to create an autoclicker that would "remember" current position of my mouse pointer, move to specific location on the desktop, perform a double click and then come back to where it was and will do this randomly every 1 to 4 seconds. This way I wanted to achieve an autoclick in a specific place and more or less be able to use my mouse to browse other stuff.
What I want to click is in a different window, it is a program that I leave open visible on one half of my desktop and on the other half I want to do other things. The problem is that auto clicker does not make the program an active window and the click does not work.
import pyautogui
import threading
import random
def makro():
z = random.randint(1,4) #timer set to random value between 1 and 4 seconds
(x, y) = pyautogui.position() #remember current position of mouse pointer
threading.Timer(z, makro).start()
pyautogui.doubleClick(1516, 141) #perform a double click in this location (this clicks do not make the window active and clicks do not work)
pyautogui.moveTo(x, y) #come back to original mouse pointer location
makro()
Thank you for help
I think adding
pyautogui.click(1516, 141) before pyautogui.doubleClick(1516, 141) could activate the window.

Pygame screen looping back

I am making a game in python, which has a main menu, followed by a difficulty select screen. When I select the play game button, the screen changes to the difficulty select screen as intended, but when I click a difficulty, it returns to the main menu screen, which is fully functional, leading me to believe that the function is continuing to run. If I then return to the difficulty select screen and select a difficulty a second time the game progresses as expected. No other button leads to this error which leads me to believe the error is in the select difficulty function itself.
def gameIntro(): # game intro loop
playButton=classes.Button(100,200,275,350,selectDifficulty) #classes is external file which contains a button class. params (x,y,w,h,action=None)
leaderButton=classes.Button(700,200,275,350,leaderboard)
quitButton=classes.Button(1000,200,250,350,quit)
instructButton=classes.Button(425,200,275,350,instructions)
spriteGroup = pygame.sprite.Group(playButton, leaderButton, quitButton, instructButton)
while not(playButton.loop and leaderButton.loop and quitButton.loop and instructButton.loop): #all of button objects have loop set to false, until they are clicked
eventLoop(spriteGroup) #runs an event handler for all of objects in spriteGroup
mainMenuScreen = pygame.image.load('Menu.jpg') # loads the menu Screens
mainMenuScreen = pygame.transform.scale(mainMenuScreen, (displayWidth, displayHeight)) #adjusts image to be same size as display
gameDisplay.blit(mainMenuScreen, (0, 0)) #displays the image
pygame.display.update() #updates the display
clock.tick(fps) #increments the clock by the fps amount to keep the screen changing
def selectDifficulty(): #selects the difficulty so that the appropriate AI is loaded
import Main
easyButton=classes.Button(70,150,300,400,Main.easyAIMaker)
mediumButton=classes.Button(450,150,300,400)
hardButton=classes.Button(800,150,300,400)
spriteGroup = pygame.sprite.Group(easyButton,mediumButton,hardButton)
while not (easyButton.loop and mediumButton.loop and hardButton.loop): #loops the screen while a choice hasnt been made
eventLoop(spriteGroup)
difficultyScreen = pygame.image.load('difficulty screen.jpg')
difficultyScreen = pygame.transform.scale(difficultyScreen, (displayWidth, displayHeight))
gameDisplay.blit(difficultyScreen, (0, 0))
pygame.display.update()
clock.tick(fps)
Problem was I didn't realise how python treated imported code. At the very end of intro.py the gameintro() function is called to start the game. When I imported intro.py this code was rerun causing the loop. By shielding game intro inside:
Def main():
gameIntro()
If __name__=="__main__":
Main()
The gameintro function only runs once

Getting position of user click in pygame

I have a pygame window embedded in a a frame in tkinter. In another frame I have a button which calls the following function when clicked:
def setStart():
global start
# set start position
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP:
start = event.pos
print("start",start)
break
I am intending for the program to print the position of the place where the user clicked on the pygame surface after the button is clicked. However on the first click of the button and the following click of the pygame surface there is no output. It is on the second click of the button before the corresponding second click on the pygame surface that python prints out an output like :
('start', (166, 115))
How can I get it to give me a result right after the click on the pygame surface? I had the same problem when I had two seperate tkinter and pygame windows so the embedding of pygame into tkinter is unlikely to be the cause of the problem.
EDIT: after further testing it appears that if the button is pressed and then the pygame surface is clicked on multiple times, upon a second click of the button the coordinates of all of these clicks are printed out as a batch.
In the most basic form here's how you do it in pygame:
import pygame
pygame.init()
screen = pygame.display.set_mode((100, 100))
clock = pygame.time.Clock()
while True:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP: # or MOUSEBUTTONDOWN depending on what you want.
print(event.pos)
elif event.type == pygame.QUIT:
quit()
pygame.display.update()
More information on how to handle pygame events can be found in the docs.
And here's how you do it in tkinter:
try:
import tkinter as tk # Python 3
except ImportError:
import Tkinter as tk # Python 2
root = tk.Tk()
def print_pos(event):
print(event.x, event.y)
root.bind("<Button-1>", print_pos)
root.mainloop()
More information on tkinter events can be found in effbots documentation.
I would suggest not putting break in an event loop in pygame. Doing so makes all other events go un-handled, meaning that it's possible for the program to not respond to certain events.
Your "EDIT: [...]" is unfortunately wrong, given the code you've given us. I had no problem with the code; it printed the position of where I released the mouse button and always printed just one position. So there have to be a logical error somewhere else in your code.
First I have to say that I don't know anything about pygame. However, if you are already using Tkinter, I could help you maybe: I would define a new function (let's call it mouse_click). In the button-click-function I would bind the new function to the game's surface. In the new function I print out the current mouse position:
def button_click(self):
game_surface.bind("<Button-1>", self.mouse_click)
def mouse_click(self, event):
print "X:", event.x
print "Y:", event.y
I hope this is helpful. Please notice that you should modify this code to make it work in your program (using the correct widget names and so on).
By the way, "Button-1" is the event identifier of the left mouse button.

Python if statement not working as expected. Code 'apparently' called twice

I have this piece of code:
import bge
import GameLogic
import os
os.system("cls")
scene = GameLogic.getCurrentScene()
objects = scene.objects
objectCube = objects["Cube"]
visible = objectCube.visible
if visible == True:
objectCube.setVisible(False, True)
else:
objectCube.setVisible(True, True)
This code is supposed to toggle the visibility of an object but instead the object disappears and immediately reappears in a split second. It looks as if it just flickers. What am I doing wrong?
Also, don't worry about the other variables, they work fine. I have tested them using some Console outputs.
The problem: The mouse sensor sends two signals per click, one for mouse down and one for mouse up. Mouse down sends a positive signal while mouse up sends negative.
You can test this by holding the mouse button down, the cube will disappear and when you release the mouse it will return.
The solution: Use the sensor's positive property to determine if this is a mouse up or down event.
import bge
import GameLogic
import os
os.system("cls")
scene = GameLogic.getCurrentScene()
objects = scene.objects
objectCube = objects["Cube"]
visible = objectCube.visible
# get the mouse sensor
cont = bge.logic.getCurrentController()
sens = cont.sensors['Mouse']
if sens.positive: # positive means a down button event
if visible == True:
objectCube.setVisible(False, True)
else:
objectCube.setVisible(True, True)
The second parameter of setVisible set the game children objects visibility. You set it to True. In this case You hidden the main object and show the children objects.
Following to http://bgepython.tutorialsforblender3d.com/GameObject/setVisible recursive parameter does not mean recursive show/hide all children elements but set the visibility to children elements to True/False
Following to http://www.tutorialsforblender3d.com/BGE_Python/Sensors/Mouse/MouseSensor_LButton_getButtonStatus.html mouse event send two events mouse press and mouse release. Maybe You do not differentiate between press and release and call code twice?

Categories