Best way to display dynamic element on a QListView (with Model/View)? - qt

We can implement our own delegate to display rich text or images, but ListView can print static item only. You can't put "real" items into it, you can just paint them.
So, there isn't a way to show clickable hyperlink, ReTweet buttons, or load asynchronous images. Just think about a timeline-listview for Facebook or Twitter. That's what I'm working on.
Now, my solution is writing my listview in QML. Other widget are still native Qt widget. (I don't like a non-native pure QML user interface.)
QML is really flexible when doing that kind of work. Then export my model, finally put a viewer into my QMainWindow. But coding in two programming languages and trying to communicate with other native widget is really difficult.
So, what's the best way to display dynamic element?

The MVC framework is not very good for this kind of work.
To do it properly, you would need to provide a delegate for whatever dynamic types you need to display, and then provide an external mechanism that forces the model to emit dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) whenever these types need redrawing. It gets worse with interactive content because you would need to force an update on mouse overs in order to trigger the delegate painting.
For stuff like this you are better off using QGraphicsScene/View. Rather than rely on a model, each item can take of itself and you still get only essential repaints (via it's BSP structure), plus you have the option of hardware acceleration.

Related

How can I disable a Qt widget without changing its appearence

I have a Qt widget which has a layout and there are more widgets inside it. When I disable the widget the whole widget becomes little faded and no modifications are possible anymore. I want the features that comes with disabling a widget but I do not want it's appearance to change. Please let me know how this can be done.
Few ideas that comes to my mind:
Rather disabling widget, capture all the events on the widget and do nothing
Update style sheet for disabled state (not sure if possible)
1. Capture events
Use QObject::installEventFilter() and QObject::eventfilter().
Keep in mind the way Qt dispatch GUI events, in particular children get events first. So you need to install the event filter recursively on all widgets and watch for QEvent::ChildAdded.
2. Using stylesheets
This is a not a good solution. Stylesheets tend to break QStyle mechanisms which may lead to side effects.
3. Use a QPixmap
Hide all the child widgets, render them to a QPixmap and draw the pixmap in the paintEvent.

Can I use a custom widget as a view in a model-based QListView?

I would like to render a series of complex data in a scrollable list using Qt5. Since the source of the data is a timeline, I'd like to load it lazily --- that is, I would like to use the features of QAbstractItemModel to load data on demand. The views will be read-only.
Can I use a custom widget to display data in each cell of the list?
So far I've seen some suggestions:
use QAbstractItemView->setIndexWidget(); however, because I'd like to load the data lazily, it seems needlessly expensive to create and set widgets for all indices, before the data is loaded.
use QAbstractItemView->setItemDelegate() with a custom QStyledItemDelegate that overrides paint(). The result looked good, but the widgets were simply rendered, and not interactive (couldn't select text, etc).
You can do it with QGraphicsScene or even with QScrollArea + your custom widgets. It is not necessary to use QAbstractItemModel everywhere.
If you will use custom widgets for each model item you, probably, will have performance and interactivity problem.
Ofc, you can write a custom delegate, but delegates with interactivity is very complex topic - it is necessary to handle mouse events manually, draw a selection, etc.

How to draw something in a tooltip?

I am trying to develop a functionality using Qt which I don't know whether it is possible to implement. Here is the requirement:
When the user hovers over a node (an object derived from QGraphicsItem), a window will be shown near the node, in the window there might be some histograms or buttons that can be clicked to show further information. When the mouse leaves the window, it will automatically close.
I tried to use a tooltip, because it can pop-up near the node and close when the mouse leaves it, but it can only show text. So, it still cannot work that way. I am wondering if there is another way to do this? I did lots of google search, but there is still no answer.
Thanks so much for helping me with this.
If you're ok with using a 3rd party library, Qxt provides a class that provides a tooltip that is QWidget based, which will let you use an arbitrary widget as the tooltip rather than just text.
See: Qxt::ToolTip
you don't have to use tooltip for your app
you can use or call widget or dialog, on hover mouse event
Please refer Qt Example EmbeddedDialog Example, It is advanced, But you can understand how hover Enter/Leaving events are working. I personally prefer don not create instance of Popupdialog for each item, create it if only nesessary. Otherwise create one dialog and pass its reference to all the items through the constructor initialization.
1. These are the API you are intrested on, reimplemet this.
QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) and void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
2. When You create Dialog, You can pass Qt::WindowFlags as Qt::ToolTip.

Use Model/View on a QListWidget

Yes, you are right. We have QListView already, it is prefect when we are trying to display simple list with Model/View.
But, QListView has lots of problem when we need to display complex list with rich text and widgets. Just think about a timeline-listview for Facebook or Twitter.
Sure, we can implement our own delegate for rich text or images, but ListView can print static item only. So, there isn't a way to show clickable hyperlink (you can calculate position of the mouse and hyperlink, but it is a really drity work) or load asynchronous images.
Well, QListWidget seems our solution. We can put widgets into it. But. we will lost our Model/View/Delegate architecture, that is terrible!
Now, my solution is writing my listview in QML. Other widget are still native Qt widget. (I don't like a non-native pure QML user interface.)
QML is really flexiable when doing that kind of work. Then export my model, finally put a viewer into my QMainWindow. But coding in two programming languages and trying to communicate with other native widget is really difficult.
So, is there a way to use Qt's Model/View architecture with QListWidget? Or I have to implement them by myself?
QListWidget does use Qt's MVC, as it derives from QListView and...
QListWidget uses an internal model to manage each QListWidgetItem in
the list.
Just use QListWidget::model () const to access the model.

Qt: Custom QListView and live controls

My custom QListView has delegates to paint the items. I'd like to add a live control to some of the row items (like a QLineEdit), that'll always be present in the row and will automatically scroll correctly with the list.
Since items are not widgets, I cannot assign a control to be a child of an "item", thus scrolling will leave the control in its fixed spot within the QListView widget.
Is there another way?
Is that even possible?
Normally the edit widget is created (and positioned) by the delegate when an QEvent::EnterEditFocus event occurs then destroyed when a subsequent QEvent::LeaveEditFocus occurs and the data is sent back to the model. The delegate should then repaint with the new model data.
Could you expand on what you mean by a "live" control?
Why would you want to have an edit widget constantly open? I think a better way to do this would be to create a delegate which paints the normal view (i.e. for Qt::DisplayRole) in a way which you want. Assuming you create your subclass view correctly, the delegate should still update when the model changes.
If you really want to do what you're asking though, I suspect you might be able to by:
creating your own item delegate (subclassing QAbstractItemDelegate)
reimplement createEditor() to use a QLineEdit
then use the delegate's updateEditorGeometry()
Have a read of the Delegate Classes section of the Introduction to Model/View Programming though first. The Spin Box Delegate Example and Pixelator Example are worth studying too if you haven't already.

Resources