Draw more than one widget in QListView item - c++

I created my own data model based on QAbstractListModel and connected it with QListView by simple ui->listView->setModel(prodModel) - it works fine.
Now I want to create custom view in QListView for each item. For example, I want to reach that every data row from model will be shown in style like Stack Overflow (question with rating). I want to use Qt widgets and arrange it on my own idea - using layouts etc.
Unfortunately, a Qt's guide about model/view doesn't have described how to use QItemDelegate to show my widgets - I'm not interested about editing data in view (but I want to interact like click - ideally if I could click and get signal/sth in each widget in my custom view).
I found some examples, but they describe drawing only one widget (QProgressBar) without any layouts.
Any help will be appreciable, thanks!

Related

Expandable list view with customized scrollbar in Qt

I want to build a widget like this one that we can find in Word :
So, there is a list view using a specific scrollbar with 3 buttons and no scroll.
When you click on the last button at the bottom right, a new list view with a classic scrollbar is shown over the previous list view (hidden when losing focus). So basically, the smae behavior as the one in Word.
We are already capable of displaying a list view with custom content.
My main concern is how to build the widget in the first image: the list view with the custom scrollbar (3 buttons, no scroll)?
What is the proper way to do this ?
I assume that you're implementing a subclass of QAbstractListView.
I don't believe you need a custom scrollbar - just put the scrollbar and the button into a QVBoxLayout; hide the button once it's checked (you could even connect its toggled() to its setHidden() for that).
At first hide the default scroll-bar by calling the QAbstractScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff) method.
Then create your three buttons on the left side and connect the QPushButton::clicked() signals to some slots where you just scroll your list by calling the QAbstractItemView::scrollTo(index), QAbstractItemView::scrollToBottom() or QAbstractItemView::scrollToTop().
While it is correct that you could just build a custom widget consisting of a view with hidden scrollbars and add the buttons to the layout, connecting the signals/slots needed to provide the proper actions, you can also consider to implement your own QScrollBar class. QListView is derived from QAbstractScrollArea, which provides setVerticalScrollBar() so you can just set an object of it to be used by the view. The integration of scroll area and scroll bar should be much more straightforward this way, but you'll have to do the painting of the scroll bar's content yourself, or put a layout and the buttons in there (QScrollBar derives from QWidget, and you'll have to reimplement paintEvent()).

How to create QSplitter ui class via qt designer?

I am new to Qt and I need to implement a monitoring interface with the following considerations:
I have a main window, on which I should put multiple screens, qsplitter appears to be the best solution.
The interface provides user with the option of changing the number of cameras, so QSplitter should be created/re-created during run time.
The problem is that I have too many cameras to pre-define widgets for them, so I need to create QSplitter UI instances dynamically.
The problem is that I can't find QSplitter classes when using Qt Designer and creating QSplitter class programatically is not working as MainWindow has been created through Qt Designer (.ui).
I would like to hear any suggestions regarding this issue, if there are better approaches, please let me know.
In Qt Designer, the QSplitter is not a widget, but a Layout.
Select the widgets you want to include in the two splitter areas, then select Layout from the context menu (right mouse button) - you will find two entries Layout Horizontally in splitter and Layout Vertically in splitter to group the widgets in a vertical or in a horizontal splitter.
QSplitter isn't a strict UI element, it's essentially a parent element that controls child elements. If you want to do it through Designer you'd probably run into headaches, but the basic gist is you select a number of widgets to be controlled by it, and click the Layout Horizontally/Vertically in splitter button which is in the layout buttons group.
What you might be best doing is creating your child elements programmatically, creating your splitter programmatically, adding the child widgets with someSplitter->addWidget(...). In the Qt docs there's some sample code for this:
QSplitter *splitter = new QSplitter(parent);
QListView *listview = new QListView;
QTreeView *treeview = new QTreeView;
QTextEdit *textedit = new QTextEdit;
splitter->addWidget(listview);
splitter->addWidget(treeview);
splitter->addWidget(textedit);
http://doc.qt.io/qt-5/qsplitter.html#details
And if you really want to do it in Designer there's a guide here: http://www.bogotobogo.com/Qt/Qt5_Splitter.php
Although QSplitter is a widget, you can't create one directly in Qt Designer. It is only available for laying out pre-existing widgets - which does not fit your use-case, since you need to create child widgets dynamically.
However, you can work around this limitation by using widget promotion. This is a simple mechanism that allows you to add substitute classes to represent widgets that are not directly available in Qt Designer. The idea is that you add a widget that is most similar to the one you actually want (e.g. a QFrame is most similar to QSplitter) and then promote that to the substitute class which you have defined in your own header file. When uic finally generates the code, it will use your substitute class instead of the class of the widget added in Qt Designer (which just acts as a placeholder).
Note that when you create your substitute class in the Promoted Widgets dialog, the base class should be a QFrame, not a QSplitter. This is because you are extending a QFrame (i.e. your placeholder widget), rather than a QSplitter. Of course, you can define your substitute class to be anything you like.
Image is easier to understand.

Customizing QT QTreeView with custom widgets

In my raster drawing program I need to create a layers interface like in Photoshop or Sketchbook Pro. I read the documentation and figured out that I have to use QTreeView. But I didn't find a lot of information in the documentation about creating QTreeView with custom widgets. So:
1) How to insert custom widgets into tree view?
2) What is the difference between QTreeView and QTreeWidget?
3) What is the difference between QAbstractItemModel and qitemdelegate?
4) Any examples/articles/guides?
5) Maybe I should use something else?
QTreeWidget is a model and a view in one class, it's called a convenience view. It works against the good practice of separatng the views and the models, and probably shouldn't be used in a system where the notion of document layers belongs in the document handling code.
QTreeView is just a view, without any bundled models. When you have a model, you can set it on a view, making the view display the model.
A QAbstractItemModel is the data model. It has nothing to do with views or delegates at all - the model can exist and be useful without a view at all.
A delegate provides display and editing widgets for items of data in a view. It is a property of the view, not of the model. Different views can show the same model using different delegates, all at the same time.
Although the delegate lets you provide the custom widgets you're after, its use may be unnecessary. If the item you display has static contents, you can simply provide a QImage or a QPixmap as the data.
Special for your case (5): DON'T use any of QTreeView, QStandardItemModel and other such classes. If you need interaction with widgets + if you need widgets to be animated then you should use simple QScrollArea with QVBoxLayout inside of it.
Qt MVC is designed to process big amount of cognate data. It is not designed to provide widget-based interaction. So, if you want to "assign" one widget to each item and to interact with them - you will have a lot of problems with implementing delegates (tracking mouse events, providing editor's factory). Ofc, you may create your own delegates with custom drawing and custom processing of mouse events, but it's much easy to use simple widgets.

A custom widget to display and select among multiple graphic views

I have a collection of images, dynamically generated through QGraphicsView widgets, and i'd like my users to choose between them. For that purpose, i would display inside a custom widget available images in some kind of grid and have users click the one they are interested in.
Multiple questions arise :
is there an existing widget that already fits this purpose ?
should i find a way to disable all mouse event handling by QGraphicsView items, or could i add a transparent widget in front of graphic views which would intercept them ?
is there a performance issue displaying many QGraphicsView widgets (up to a few hundreds) ? Should i export them to plain images first ?
First off, no, there's no widget designed specifically for that purpose.
I don't think you are grasping what QGraphicsView is for. It's for displaying a QGraphicsScene, which is meant to hold many QGraphicsItems. Based on your post, I can't see why you would need multiple QGraphicsViews. You can simply have one QGraphicsView and display many images inside of its scene. For example, see QGraphicsPixmapItem.
You definitely should not have hundreds of QGraphicsViews. You probably just want one (although a few could be justified in certain circumstances), in which you display many QGraphicsItems in a QGraphicsScene. You can definitely have hundreds of QGraphicsItems visible at once. In your case, you probably want QGraphicsPixmapItems, which are a subclass of QGraphicsItem. You could even have multiple QGraphicsScenes, and display whichever one is relevant using QGraphicsView::setScene. If you want the user to be able to select an image from a grid, and then work with that image, I would look to the State Pattern.
I can't think of any reason to disable mouse handling in QGraphicsViews, QGraphicsScenes, or QGraphicsItems. Why should these not handle their own mouse events? You can (and should, where necessary) subclass them and reimplement mousePressEvent, mouseMoveEvent, mouseRelease event, etc. to obtain the functionality you want.
Good luck!

QListView item background color

I'm trying to change the background color of the item which currently has the mouse hover.
What I've done so far is: I subclassed QListView and in the ctor:
connect(this,SIGNAL(entered(QModelIndex)),this,SLOT(enteredSlot(QModelIndex)));
The job basically needs to be done in the slot enteredSlot(QModelIndex) but I have no idea how.
You can achieve what you are trying to do a bit easier by setting a style sheet for your QListView. If you haven't worked with style sheets before you may want to back track in the documentation a bit but most common activities related to customizing the appearance of widgets can be done using them. Do not confuse them with QStyles which is a different styling mechanism.