I have implemented Finger Scrolling to one of my QListWidget.
I have taken refernce from
http://www.developer.nokia.com/Community/Wiki/Qt_Kinetic_scrolling_-_from_idea_to_implementation
Now the problem is on_current_row_changed event of QListWidget gets fired when i scroll up and down my List.
How i can avoid this on click only it should behave like click not on Scroll.
Starting from Qt5 this is as simple as:
#include <QScroller>
...
QScroller::grabGesture(myListWidget, QScroller::LeftMouseButtonGesture);
For touch screens use TouchGesture instead of LeftMouseButtonGesture.
If the widget doesn't inherit QAbstractScrollArea (e.g. QWebView):
QScrollArea *scrollArea = new QScrollArea;
scrollArea->setWidget(myWidget);
QScroller::grabGesture(scrollArea, QScroller::LeftMouseButtonGesture);
Be sure to resize the widget to its content size.
You need to test whether the finger has moved between mousePress and mouseRelease. You can extract the position of the press, so if you store it in an intermediate variable, then test it against the position of the mouseRelease (say using QPoint::manhattanLength()), you can tell whether the finger has moved. If it has, the user is scrolling, if not, they're clicking.
EDIT: Looking at the code you've linked to, they're already doing the above. Could we see some more of your reimplemenation?
Related
So I currently have got a custom widget, and I want to add them to the main window after clicking a button. I would like to add them all to one fixed position first and then I will be able to drag them wherever I like. I am able to create and display these custom widgets with help of QHBoxLayout or QVBoxLayout, but in this case they will not be in the same position after I create them. Any help will be appreciated!
As the names suggest, the QLayout classes manage the position and geometry of the items added to them. You cannot move (eg. drag) an item out of a layout w/out first removing it from the layout (QLayout::removeItem() and derivatives). For example when you drag a toolbar or dock widget out of a QMainWindow it goes through all sorts of machinations to remove it from the MW layout, change the widget's window flags, remember the old position in the layout, and so on. And the reverse to dock it again.
To do what you describe (drag widgets arbitrarily around a window) you would need to not use a QLayout and position the widgets manually by specifying a QWidget::setGeometry() for example. After initial position, and assuming the user has some way to grab the widget (title bar or drag handle you made, etc), you'll probably still need to manage their positions, for example if the main window is resized (if you care about keeping them contained). Essentially you'd have a bunch of separate widgets acting as individual windows and probably need some way to keep track of them.
I don't know what kind of widgets you're talking about, but one option may be a QMdiArea which lets the user drag windowed widgets around, tabify them, save/restore state, and so on.
For more flexibility you could also look into the Qt Graphics Framework. The graphics scene has a lot of features for user-movable items/widgets, keeping track of them, and so on. It is probably the most flexible method overall, and you can also use regular QWidgets inside a graphics scene.
A couple other Q/A about arbitrarily positioning widgets (I'm sure there are more to be found):
QPushButton alignment on top another widget
How to keep Push Buttons constant in relative to change of Label Size in PyQt4
Just as a QPushButton provides a default clicked() signal, I expected QScrollArea to have a sliderChanged() or similar signal. Interestingly, the QScrollBar does have such a signal.
All I would like to do is to know what part of the huge widget inside the scroll area is visible, whenever the user scrolls it.
There are many solutions, none of which seem elegant to me:
subclass QScrollArea
subclass the widget inside the scroll area, and re-implement its paint event.
create a custom veiwport, using QScrollBar
periodically poll the position of the widget inside the scroll area. This seems to be the worst solution.
Is there a way without subclassing?
There is QAbstractSlider::valueChanged() signal that is emitted when the slider value has changed, with the new slider value as argument. This will notify you as soon as you scroll your view.
WRT the second problem, neither of mentioned points necessary. You need to:
1) Get the position of inner widget (if any) related to the scroll area:
QPoint p = scrollArea->widget()->pos();
It use to be a negative coordinates if you scrolled your view down/right or null without scrolling.
2) Get the size of the visible area
QSize s = scrollArea->viewport()->size();
With these two values you can construct a QRect that will represent the visible area of your inner widget.
I am having QListWidget, i want to have a Transparent Scrollbar with Image.
Initially that scrollbar should be hidden on scroll only it should show.
How i Can achieve this in Qt ?
Any examples or ideas are welcomed.
How i can apply image to Listview Scrollbar.
Here are the three things you can look at to be able to control the scroll bar for most kinds of widgets in Qt:
VerticalScrollBarPolicy
HorizontalScrollBarPolicy
enum Qt::ScrollBarPolicy.
To be able to track how the user interacts with your QListWidget or any Widget for that matter you need to subclass it and implement the virtual methods from the QWheelEvent and possibly the QKeyEvent.
Scrolling is typically done with the mouse wheel and with the keyboard arrow keys and sometimes page-up and page-down and spacebar. I haven't done a lot with QListWidget, but you should double check which keyboard events/mouse events trigger scrolling.
These events will cause scrolling event even after you set either or both of the ScrollBarPolicies for the widget to be Qt::ScrollBarAlwaysOff.
First you should put in the constructor of your widget
this->setVerticalScrollBar(Qt::ScrollBarAlwaysOff);
this->setHorizontalScrollBar(Qt::ScrollBarAlwaysOff);
So you just need to setMouseTracking(true) for the widget (so that it tracks more than just the clicks) and reimplement at the very least wheelEvent(), and when a wheel event occurs, set the vertical/horizontal scroll bar policies to true and call update on your widget.
If you want to turn the scrollbars back off after a few milliseconds after they have started scrolling, you will need to create a QTimer in your constructor for your subclassed widget and connect it to a slot that sets the scroll bar polices on the timeout. Then you start/restart that timer every time the user does a wheelEvent().
As far as applying an image to the ListView Scrollbar, you should look into subclassing QAbstractScrollBar, if you want to actually put an image on it or change the way it looks. Setting up some tool buttons may also be the way to go if you are trying to put buttons with different icons in place of the scrollbar.
I have main window and in this window I have QListWidget. I want this list to be central widget in the main window and I know that I can do that by writing code like setCentralWidget(QWidget*) and it works (list is spread on the whole mainwindow) but this isn't reflected in designer when the list is still in this same position and has the same size. Is there any way to make it so the change is visible in designer as well as in the code?
Thank you.
In Designer, right click on an area of the form next to the QListWidget, then choose Layout->Layout Horizontally (or vertically, almost anything is acceptable).
I figured it out. In order to do so I had to choose grid layout for main window and sizePolicy for list as Prefered.
In my application I have QGraphicsScene with pixmap added and all is viewed in QGraphicsView with scrollbars off.
The program window is smaller then pixmap and when I press arrow keys or move mouse wheel the pixmap is being moved.
How do I disable that so even if the pixmap is bigger than window it won't be moved by keyboard or mouse unless I use my events for that?
(I tried to set interactive property to false but that didn't work)
I believe the easiest solution would be to set FocusPolicy of QGraphicsView to NoFocus and then process all key events in main window.
ui->graphicsView->setFocusPolicy( Qt::NoFocus );
I think the easy way is to use QGraphicsView::setSceneRect() to set the area that the view is allowed to visualize.
If you set the view's sceneRect() to the actual size of the view widget (or just slightly smaller), then it won't be able to scroll or pan outside of this rectangle.
I don't know if there's an easier way, but the moderately easy way would be to make a class that inherits your QGraphicsView class, and overrides the mouse and key press events.
The harder way would involve installing an event filter on the widget.
In my opinion, the hardest brute-force solution would be to detect the change through some sort of signal, and set it back to how it was.