I would like to create GUI on my RPi so that I can scroll through Listbox like I do in my iPhone, without the use of a scrollbar. In other words, by just touching the listbox and 'flicking' your finger up/down, I would like to be able to scroll.
Can this scrolling method be done with TKinter or any GUI for RPi?
Yes it is.
Just have a look how the binding of scrollbars work.
How can you achieve the desired effect? Bin Mouse-Move events (touch move is nothing else) and use it to connect it to yview / xview depending on what scroll you want to have.
(e.g. check the direction your mouse moves inside your callback and use that information to trigger the scrolling event.)
If further help is needed, let us know.
Edit:
Here some "dummy-code"...
# this is your callback bound to mouse-move event
def mouse_move_callback(event):
# use event.y with a previous remembered y value to determine
# directions
directions = 1 # just as an example, could also be -1
# scroll the listbox vertically.
# to increase scrolling speed, either multiply counter by some value >1
# or replace 'units' which means scroll 1 character in the current setting
# by 'pages' for larger steps. 'pages' should scroll the visible
# area of the listbox further.
listbox.yview_scroll(1, 'units')
You could also use mouse button press and mouse button release to trigger the actions. Mouse button press would then store an y value (beginn of scroll) and mouse button release would be bound to the above callback.
Related
Question: It seems that ButtonPress events on tkinter give the location of the click w/r to the top left corner of the window. However, when you click on a Button widget, a ButtonPress event occurs, but the x,y location values given are w/r to the top left corner of the Button. How can I get the ButtonPress event to occur at the location w/r to the top left corner of the window, not the button?
Details: I have a tkinter program that lets users draw on a picture (layout below), but only occurs below a certain y value. If you move the cursor below that threshold (aka below the picture and into an area that has instructions), no drawing functionality can occur. Drawing only occurs with clicks, so <Button-1> is bound to a class method that keeps track of where the click occurred and draws on the picture at that location:
self.root.bind('<Button-1>', self.addDot)
However, in the area that has instructions, there is an undo button. Clicking on it in theory should undo the last click's effect. Instead, if I click on it, it registers a <ButtonPress> event that has x and y values with respect to the top left corner of the button, not the window. I do not know how to differentiate when the x,y location of a button press occurs w/r to the window or the button, so the self.addDot function executes near the top left of the image. Everywhere else you click behaves as normal.
One caveat I have seen is that if I change the binding to be on the canvas, not the root, this strangely goes away and behaves as expected. Why is that?
Layout:
i was able to create a text widget with a search, and highlight every finding. The only thing i miss is a button like "Next" which jumps to the next finding.
So far i was not even able to show (jump) to the first finding.
I can move the cursor there, but i cant move the screen.
The text widget has a huge ammount of text, and i use a scrollbars if that can help.
Is there any way to move the screen or scrollbar to the curzor? Or to a tag? Or to a finding?
Thanks, Gábor
You can call the yview methods to scroll the widget by a particular amount. However, for this specific use case the text widget has the see method, which arranges for a given index to be visible.
From the official tcl/tk documentation (upon which Tkinter is built):
[see] Adjusts the view in the window so that the character given by
index is completely visible. If index is already visible then the
command does nothing. If index is a short distance out of view, the
command adjusts the view just enough to make index visible at the edge
of the window. If index is far out of view, then the command centers
index in the window.
Is it possible in Tkinter to avoid the event grab which occures when you press a mouse button over a widget and keep it pressed while you move the mouse?
I want to register the mouse button and then track all widgets the user enters while he moves his mouse with the button pressed. When the user releases the mouse button the application executes the same action for all tracked widgets.
The following code should explain what I want to do.
# Set a tracking flag
widget.bind('<Button>', start_tracking)
# Add the entered widget to the tracked widgets, if the tracking flag is set
widget.bind('<Enter>', add_to_tracked_widgets)
# Execute an action for every tracked widget; unset the flag
widget.bind('<ButtonRelease>', end_tracking)
I took a look at the grab_current and grab_status methods, but they always returned None.
Python version is 3.4.1.
This is probably the most complicated way to do this, but okay.
One thing that makes this more complicated is Tkinter itself, because event.widget still refers to the widget that was clicked on initally. A different event we can use is Motion which is activated when the mouse moves inside a widget.
tk.bind("<Motion>", add_tracked)
I think you can implement the list and state variables yourself, so we come to the add_tracked method (I just renamed it, it's your add_to_tracked_widgets):
def add_tracked(event):
if tracking:
# Get coordinated of the event and use the master window method to determine
# wich widget lays inside these.
widget = tk.winfo_containing(event.x_root, event.y_root)
# Since 'Motion' creates many events repeatedly, you have to convert this
# list into a set to remove duplicates.
widgets.append(widget)
I have a program somewhat similar to Microsoft Paint, and I'm working on implementing canvas resizing. I need to detect if the mouse cursor has moved into resizing range, and if the left mouse button is held down while the mouse is being moved. I have a QGraphicsRectItem set up as my canvas, and I want to detect mouse movement and mouse button state in my QGraphicsRectItem, without it being selected.
I've been using QGraphicsItem.hoverMoveEvent for detecting if the cursor is within resizing range or not, but when the left mouse button is held down, hoverMoveEvent is no longer triggered.
There's mouseMoveEvent, but as the docs say:
If you do receive this event, you can be certain that this item also
received a mouse press event, and that this item is the current mouse
grabber.
In my program, it's impractical for my canvas to be the current mouse grabber when resizing. I may have other objects that need to retain their selection states while the canvas is being resized.
I realize I could do this in the QGraphicsScene containing my QGraphicsRectitem, but to avoid interdependence between them, I'd like to be able to do this all in my QGraphicsRectItem.
So my question is: How, if possible, do I detect mouse movement and mouse button states on a QGraphicsRectitem without the it being selected?
I am aiming to change the a part of the Tkinter screen when a button is clicked. Do I have to destroy the screen then redraw it (to create the illusion that only a part is being changed?) Or can I keep the button there and somehow only change one part (like the graphics.) Thanks!
No, you do not have to destroy the screen and redraw it. You can easily insert widgets into the current window when a button is clicked. There's nothing special about being run from a button click -- the code is the same as your initialization code.