Mouse wheel moves cursor - python-2.7

I am fairly new to coding with python but I have to learn it as part of my PhD. I want to program a task in which on a straight line (top to bottom) there are 4 possible positions (here circles) that are target zones. Later a stimulus will be presented that corresponds to one of these targets. Afterwards the subject will have to move a mouse cursor on the line to select the correct stimulus. I want to do the input via the wheel of the computer mouse. So if I scroll up the cursor on the button moves along the line and can be placed on one of the zones and then a reward is given.
To my question: How do I implement the input of the mouse wheel, bind it to the cursor and restrict the the cursor to stay on the line (disable all other mouse movements) ?
Thank you in advance.

In PsychoPy Coder --> Demos --> input --> mouse, you will see a demo script on how to react to different kinds of mouse input. Also, see the documentation. In code, you would do something like this, where points is a list of coordinates on your line.
# Your points
points = [[0, 0], [1, 0.5], [2, 1], [3, 1.5]]
# Set up mouse
from psychopy import visual, event
win = visual.Window() # A mouse must be in a window
mouse = event.Mouse() # initialize mouse object
# Begin listening
event.clearEvents('mouse') # Do this in the beginning of every trial, to discard "old" mouse events.
index = 1 # start value
while not any(mouse.getPressed()): # for this example, keep running until any mouse button is pressed
#print mouse.getWheelRel()
scroll_change = int(mouse.getWheelRel()[1]) # returns (x,y) but y is what we understand as scroll.
if scroll_change != 0:
index += scroll_change # increment / decrement index
index = min(len(points)-1, max(index, 0)) # Round down/up to 0 or number of points
print points[index] # print it to show that it works. You would probably do something else here, once you have the coordinates.

Related

How to redraw a curve to Photoshop with Autoit?

I want to draw a specific curve line to Photoshop or to mspaint. This drawing action should be saved for the possibility to redraw that curve in the exact same way. How can I do it with Autoit? Is there a recording and play mechanism? As far as I read, the AU3 recorder is not available anymore.
Photoshop is just an example. I want to be able to do that kind of drawing record for different purposes and programs. Maybe also for online image editors or something.
I am not that familiar with Autoit yet. I do not expect a full code example, maybe you can give me an idea - that would be very helpful.
Currently I tried a bit with mouse functions like MouseDown, MouseMove etc. and it is quite funny, but i do not really have a concept to record and redraw these mouse actions.
If I have to clarify more please let me know - i will do my best to be precise.
I recommend using two scripts, one for recording and the second to replay recorded actions.
Code for the recording:
; declaration
Global $sFileCoordinates = #ScriptDir & '\RecordedMouseMoveCoordinates.txt'
Global $iRecordingDurationInSeconds = 10
Global $iXSave, $iYSave
; functions
Func _recordMouseMoveCoordinatesToFile()
Local $aPos = MouseGetPos()
If $aPos[0] <> $iXSave Or $aPos[1] <> $iYSave Then
FileWrite($hFile, $aPos[0] & ',' & $aPos[1] & #CRLF)
Local $aPos = MouseGetPos()
$iXSave = $aPos[0]
$iYSave = $aPos[1]
EndIf
Sleep(80)
EndFunc
; processing
Sleep(4000) ; wait 4 seconds to place your mouse to the start position
Global $hFile = FileOpen($sFileCoordinates, 1 + 256)
Global $hTimer = TimerInit()
While Round((TimerDiff($hTimer) / 1000), 1) <= $iRecordingDurationInSeconds
ToolTip(Round((TimerDiff($hTimer) / 1000), 1))
_recordMouseMoveCoordinatesToFile()
WEnd
FileClose($hFile)
Recording will start after a 4 second delay. This should allow to move your mouse to the start point of your drawing action.
Global $iRecordingDurationInSeconds = 10 means your drawing action should be finished in 10 seconds (a tooltip displays remaining seconds). And here the seconds script.
Code to redraw curve:
; declaration
Global $sFileCoordinates = #ScriptDir & '\RecordedMouseMoveCoordinates.txt'
; functions
Func _getFileContent($sFile)
Local $hFile = FileOpen($sFile, 256)
Local $sFileContent = FileRead($hFile)
FileClose($hFile)
Return $sFileContent
EndFunc
Func _drawRecordedMouseMoveCoordinatesFromFile($sContent)
Local $aFileContent = StringSplit($sContent, #CRLF, 1)
Local $iX = StringSplit($aFileContent[1], ',')[1]
Local $iY = StringSplit($aFileContent[1], ',')[2]
MouseMove($iX, $iY, 4)
MouseDown('left')
For $i = 1 To $aFileContent[0] Step 1
If $aFileContent[$i] <> '' Then
Local $iX = StringSplit($aFileContent[$i], ',')[1]
Local $iY = StringSplit($aFileContent[$i], ',')[2]
MouseMove($iX, $iY, 4)
EndIf
Next
MouseUp('left')
EndFunc
; processing
Sleep(2000) ; wait 2 seconds till start
Global $sFileContent = _getFileContent($sFileCoordinates)
_drawRecordedMouseMoveCoordinatesFromFile($sFileContent)
There is a start delay of 2 seconds. All saved coordinates will be executed in the same way recorded. It starts with MouseDown('left'), then the mouse movements to MouseUp('left').
Notice:
This approach isn't really robust because of the coordinates which aren't relative to your window. Please see Opt('MouseCoordMode', 0|1|2) in the help file for more information. If you want to draw more than just one line or curve this approach isn't the best. But as your question describes only that requirement it should be fine.

A code needs to be continued...(Python with Tkinter)

This code is a simplified typing game, but I can't continue. The features required are:
Please don't use classes but just use FP;
When 5 random characters appear after you click the button, the 5 characters drop with a speed of 5 pixel/second, and meanwhile, you hit your keyboard to strike them. For every successful hit, your score wins by 10, and the character being hit will disappear. If not successful, they continue to drop untill the bottom edge of the canvas.
Below is part of my code, I've tried several times, but couldn't make it. How can I continue? Many thanks!
from Tkinter import *
from time import *
import string
import random
root = Tk ( )
root.title("Typing")
cvs = Canvas ( root , width=400 , height=350 , background="White" )
def Start():
s=random.sample("string.ascii_letters",5)
cvs.delete("rand")
return cvs.create_text(200,50,text=s,tags='rand',font=('Courier New',36,'normal'))
Button(root,text="Start",command=Start,width=30).pack()
cvs.pack ( )
root.mainloop ( )
You can animate an object by writing a function that draws one frame of animation, and then schedules itself to be called again in the future.
For example, to move a single object down the screen at five pixels a second you can use a function like this:
def animate(cvs, object_id):
# move down five pixels
cvs.move(object_id, 0, 5)
# call this function again in one second
# if the object is still on the screen
(x0,y0) = cvs.coords(object_id)
if y0 < cvs.winfo_height():
cvs.after(1000, animate, cvs, object_id)
You will have to modify that to handle more than one character, or call it once for each character. That decision is left up to you, this just illustrates the general technique.
Next, you can set up a binding to the <KeyPress> event, look at the character that was pressed, and if it matches something on the screen you can delete it. One simple way to keep track of what's on the screen is to map the characters to their canvas ids.
For example:
chars = {}
for char in random.sample(string.ascii_letters, 5):
obj_id = cvs.create_text(...)
chars[char] = obj_id
Now you'll have a dictionary that looks like:
{"a": 1, "X", 2, "y", 3, "f", 4, "B", 5}
You can now move or delete each canvas item by id.

Unable to set the Entry box to correct position in python

I am trying to learn creating GUI using Tkinter .I created a window which includes text,Messagebox,Entry widget,labels and Radio buttons.
I used grid method for frames and tried to make entry boxes in row0 and row1 .And a message Box with Some text.But these are not properly aligned even though i gave correct rows and columns but output is not in order.
Entry box is created very far though i mentioned column1 .And message box is created as per the column specified.Can anyone help me how to solve this.If i am missing anything please let me now .
from Tkinter import*
import tkMessageBox
class Example:
def __init__(self,root):
root.title("Sample")
#Entry functions ---------------------------------------
Label(root, text="First Name").grid(row=0)
Label(root, text="Last Name").grid(row=1)
self.e1 = Entry(root)
self.e1.bind("<Return>",self.ShowChoice_radio)
self.e2 = Entry(root)
self.e2.bind("<Return>",self.ShowChoice_radio)
self.e1.grid(row=0,column=1)
self.e2.grid(row =1,column = 1)
#------------------------------------------------------------------------
self.frame=Frame(root)
self.frame.grid(row=3,sticky=W)
self.label=Label(self.frame, text="mine", width=12,bg="green",fg="white",justify=LEFT)
self.label.grid(row=3,column=4,sticky=W,pady=4)
root.minsize(width=666, height=220)
self.v=IntVar()
role=[("ENGLISH",1),("SPANISH",2),("GERMAN",3)]
Label(self.frame,text="Choose your role of target:",justify=LEFT,padx=2,pady=2).grid(row=4,sticky=W)
i=0
for txt,val in role:
i=i+1
self.rad_bt=Radiobutton(self.frame,text=txt,padx=20,variable=self.v,
command=self.ShowChoice_radio,value=val)
self.rad_bt.grid(row=4,column=i+1)
self.bottomframe = Frame(root)
self.bottomframe.grid(row=12,sticky=W)
self.hello(12)
T=Text(self.bottomframe,height=2,width=30)
T.pack(padx=100,side=TOP)
T.insert(END,"just a normal text to display!\n")
self.mbutton=Button(self.bottomframe,text='Quit',command=self.callback,state='normal')
self.mbutton.pack(padx=3,pady=3,side='left')
self.help=Button(self.bottomframe,text='Help',command=self.help_msg,width=5,justify=CENTER)
self.help.pack(padx=93,pady=3,side='left')
def ShowChoice_radio(self):
print self.v.get()
def help_msg(self):
tkMessageBox.showinfo("Help to print ",message="Not yet implemented")
root.minsize(width=666, height=666)
self.show_entry_fields()
self.help.config(state=DISABLED)
def callback(self):
if tkMessageBox.askyesno('verify','Really Quit?'):
root.destroy()
def hello(self,name):
w=Label(root,text="Hello Tkinter!",width=15).grid(row=10)
whatever_you_do = "Whatever . it is my test that \n i can anble to display manner in this case find out whether it is correct one or wrong \n)"
msg=Message(root, anchor='s',width=200,text = whatever_you_do)
msg.config(bg='lightgreen', font=('times', 14, 'italic'))
msg.grid(row=10,column=1,sticky=W)
def show_entry_fields(self):
print "First Name: %s\nLast Name: %s" % (self.e1.get(), self.e2.get())
if __name__=="__main__":
root=Tk()
app=Example(root)
root.mainloop()
Even the quit and Help buttons are not proper...!!!
I initially voted to close this because there is not a clear question, but mostly only a series of statements and opinions, at least one of which is incorrect. After looking more, I think I can answer your implied question "Why is tkinter behaving in a way that seems wrong to me?". The answer, I believe, is that you do not understand that grid coordinates are independent (start over) for each container gridded. Also, coordinates not used are ignored. In particular:
Root has a grid of 5 rows and 2 columns. Renumbering the rows 0, 1, 2, 3, 4 instead of the confusing labeling you used, there is no entry in column 1 for rows 2 and 4. The width of column 0 is determined by the width of self.frame in row 2, column 0. The entry boxes are far to the right because column 0 is very wide.
Self.frame has a grid of 2 rows and 4 columns. The first 3 columns of row 0 are empty. Self.bottomframe is packed instead of gridded. The buttons are to the left of where you want because you packed them to the left. In other words, tkinter did just what you said, which is apparently not what you want.
You might list the result better if you got rid of self.frame, put 'mine' in (2,0) or (2,0), 'Choose...' in (3, 0), and a frame with 3 radio buttoms in (3,1). Then root column 0 would not be so overly wide.

Changing canvas scroll region on Python turtle canvas

Can I change the scrollregion on a Python turtle canvas? I want the drawing to move with it, not just the coordinates to shift. The appearance I'm going for is side-scroller like, where the screen's display region moves to center the turtle onscreen.
I've tried using turtle.setworldcoordinates(llx, lly, urx, ury), but, from the documentation, "This performs a screen.reset()". I've also looked at this SO question , but this involves scroll bars, will not center the turtle easily, and has a limited canvas space. What I'm looking for is something that:
Moves the display region to center the turtle
Also moves the drawing
Has an infinite scroll region
does not display scroll bars
can be called quickly with a function
My best guess would be to be able to have an infinite scrolled canvas somehow, then hide the scroll bars and set them according to turtle position.
Is this possible in Python 2.7? I don't mind if it uses tkinter as well.
EDIT: 6-3-15
I found the canvas.xview and canvas.yview functions, but they don't seem to work once I define screen = turtle.TurtleScreen(canvas), and TurtleScreen has no xview or yview functions. I can't seem to make this work.
Then I found turtle.ScrolledCanvas(). This seems ideal except it has no methods for setting scroll manually from the program. Can I set the scroll manually on a turtle.ScrolledCanvas()???
The position of a canvas can be changed without a reset using canvas.place() method. It will move the turtle and the drawings too, so the turtle needs to be relocated after every move.
The next code moves the canvas with Left and Right arrows and draws a circle with Space, while keeping the turtle in the center. No ScrolledCanvas needed, just a very large standard canvas:
import turtle
import Tkinter as tk
def keypress(event):
global xx, canvas, t, speed
ev = event.keysym
if ev == 'Left':
xx += speed
else:
xx -= speed
canvas.place(x=xx)
t.setposition((-canvas.winfo_width() / 4) - (xx + 250), 0)
return None
def drawCircle(_):
global t
t.pendown()
t.fillcolor(0, 0, 1.0)
t.fill(True)
t.circle(100)
t.fill(False)
t.fillcolor(0, 1, 0)
t.penup()
# Set the main window
window = tk.Tk()
window.geometry('500x500')
window.resizable(False, False)
# Create the canvas. Width is larger than window
canvas = turtle.Canvas(window, width=2000, height=500)
xx = -500
canvas.place(x=xx, y=0)
# Bring the turtle
t = turtle.RawTurtle(canvas)
t.shape('turtle') # nicer look
t.speed(0)
t.penup()
t.setposition((-canvas.winfo_width() / 4) - (xx + 250), 0)
# key binding
window.bind('<KeyPress-Left>', keypress)
window.bind('<KeyPress-Right>', keypress)
window.bind('<KeyPress-space>', drawCircle)
drawCircle(None)
speed = 3 # scrolling speed
window.mainloop()
Having a real infinite scrolling would require to redraw every item in the canvas every time with the required offset, instead of actually moving or scrolling the canvas. Functions like create_image() can give the illusion of movement with static backgrounds, but it resets the drawings.

How to use grid_forget to eliminate a specific ordering of buttons after they have been instantiated

I am building the GUI for a boardgame for my software engineering class. I am using the TKinter toolkit on Python 2.7 (windows). I am stuck right now because I cant seem to find a way to ignore/forget a certain ordering of buttons. Essentially, I am trying to create a grid of buttons that would represent my game board. And right now, I have a game board that has a total of 49 buttons on a 7x7 grid.
So far this is what I have been able to do:
Instantiate all my button objects where columns = x and rows = y. This easily build a grid of x*y
I then place each button into a list (lets call this list1)
I want to use my list of button objects to ignore/forget/delete (for lack of a better description) certain buttons. I am thinking I can create a 2nd list (list2) of the indexes of the button objects that I want to use grid_forget on and then compare my two lists and only keep the ones that are not in list2. Unfortunately, this doesnt work out the way I want it to. Here is the code:
gameboard = ttk.Labelframe(root, padding = (8,8,8,8), text = "Gameboard",
relief = "sunken")
#forgetButtons will not be displayed on the game board b/c they do not have a
#label (they are not a: room, hallway, starting space)
forgetButtons = [0,1,3,5,6,7,13,14,16,18,21,30,32,41,42,43,45,46,47,48]
#this list tracks all the buttons on the gameboard
myButtons=[]
count = 0
for x in range(7): #build a 7x7 grid of buttons (49 buttons total)
for y in range(7):
btn = Button(gameboard, width=7, height=4)
myButtons.append(btn)
btn.grid(column=x, row=y, padx = 3, pady = 3)
#do some comparison here between the two lists
#to weed out the buttons found in forgetButtons
#**or maybe it should not be done here?**
btn.config(text="Room%d\none\ntwo\nfour\nfive" % x)
You don't need grid_forget these widgets if you just don't create them.
import itertools
import Tkinter as tk
root = tk.Tk()
forgetButtons = [0,1,3,5,6,7,13,14,16,18,21,30,32,41,42,43,45,46,47,48]
myButtons = []
for x, y in itertools.product(range(7), repeat=2):
if not x*7 + y in forgetButtons:
btn = tk.Button(root, width=7, height=4, text="Room%d\none\ntwo\nfour\nfive" % x)
btn.grid(column=x, row=y, padx=3, pady=3)
myButtons.append(btn)
root.mainloop()
I don't know the order to calculate the position for forgetButtons (usually the first index represents the row and the second one the column), but you can easily switch it.