How do I create a QComboBox delegate that hovers over a QTableView? - qt

I created a delegate class inherited from QStyledItemDelegate and re-implemented the paint function. QComboBox hovers over QTableView, but QComboBox cannot be expanded.
I'm trying to re-implement the paint function
QString value = index.model()->data(index,Qt::DisplayRole).toString();
QStyleOptionComboBox socbox;
socbox.initFrom(cbox);
socbox.state = option.state;
socbox.rect = option.rect;
socbox.currentText = value;
socbox.editable = false;
socbox.frame = true;
socbox.popupRect = QRect(option.rect.x(),option.rect.y(),option.rect.width(),option.rect.width());
QApplication::style()->drawComplexControl(QStyle::CC_ComboBox,&socbox,painter,cbox);
Above is the core code I implemented in the paint function.
The running effect is as follows:
enter image description here
How do I get QComboBox to hover over QTableView and QComboBox to expand and collapse properly?

The logic is very hard to implement at the beginning. You can have a look at the link here: https://forum.qt.io/post/422423
You can combine your code with these.

Related

How To Create Tri-state Actions on Menus Using Qt

I have a situation where I need a tri-state checkable action on a QMenu, and the QAction class appears to only support on or off, unless I'm overlooking something obvious. The situation I have is a context menu where multiple objects are selected, but may have different states for a given boolean condition (i.e. for a given property, some objects have a true value and some false). I can leave the action unchecked when there's a mix of values, but I feel that's misleading to the user.
I'm using Qt 5.5.1 and very experienced with Qt, but not seeing a way to achieve what I want in this instance.
There is no direct way to do it from a QAction, but it is possible to subclass the QWidgetAction and create an action that contains a QCheckBox widget.
class CheckBoxAction : public QWidgetAction {
public:
CheckBoxAction (const QString &text) : QWidgetAction(Q_NULLPTR) {
QHBoxLayout *_layout = new QHBoxLayout(Q_NULLPTR);
QWidget *_widget = new QWidget(Q_NULLPTR);
QLabel *_label = new QLabel(text);
mCheckbox = new QCheckBox(Q_NULLPTR);
_label->setAlignment(Qt::AlignLeft);
_layout->addWidget(mCheckbox);
_layout->addWidget(_label);
_layout->addStretch();
_widget->setLayout(_layout);
setDefaultWidget(_widget);
}
QCheckBox *checkbox() {
return mCheckbox;
}
private:
QCheckBox *mCheckbox;
};
Simply use the class to then add to your menu; for instance:
CheckBoxAction *checkAction = new CheckBoxAction(QStringLiteral("My Action"));
checkAction->checkbox()->setCheckState(Qt::PartiallyChecked);
menu->addAction(checkAction);
You can use the checkbox() method in order to connect to signals when it changes; or change the checkbox state. Hope this helps.

How to override all widgit tooltips to have them displayed in a single QTextBrowser widget?

I am new to Qt and therefore do not know all the in's and out's and would therefore like to know how, when you hover your mouse over a checkbox or other field that contains a tooltip, to get that tooltip text and have it applied/displayed in a QTextBrowser widget??
Thanks for any help on this issue.
Each QWidget has a "toolTip" property. To get it you can simply call:
QString toolTip = desiredWidget->toolTip();
Also, as you see, to get a toolTip as a string you don't have to wait until your mouse will hover over the desired widget. After that you can use this toolTip as you want (e.g. display it in QTextBrowser as you wrote in your question).
If you try to dynamically display tooltip of the widget under cursor, try to track mouse movement.
class MyWidget: public SuperclassWidget
{...};
void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
const QWidget *widget = childAt(event->pos());
if (widget != NULL)
_textBrowser->setHtml(widget->toolTip());
SuperclassWidget::mouseMoveEvent(event);
}
There may be more clever things to prevent too frequent setting of the same tooltip, e.g. remembering the last widget.

Dragging a QWidget in QT 5

I have to make something like the iOS interface, 3x3 field of icons that can be dragged to change their position, and then remember it in an XML file.
I decided to use Grid class (QWidget is parent) as a container and my own class, inherited from QWidget, as elements.
Now I'm trying to learn how to perform a drag & drop for QWidget, but it seems like you are only able to drop onto a QWidget, but it's impossible to drag it.
Is it impossible? How do I move this thing?
Dragging a widget isn't that easy. Plenty of coding you have to do yourself.
From the Qt Docs:
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton
&& iconLabel->geometry().contains(event->pos())) {
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
mimeData->setText(commentEdit->toPlainText());
drag->setMimeData(mimeData);
drag->setPixmap(iconPixmap);
Qt::DropAction dropAction = drag->exec();
...
}
}
This means, when your widget receives a message that it is to be dragged, e.g. like with a mousepress, it has to create a QDrag object.
In the QDrag object you can set a pixmap, which represents your dragged widget. If you hide your widget at this point, it looks like as if your mouse pointer 'took' the widget.
Additionally you need a QMimeData object. In this you can put all kinds of data, which describes your widget. In your use case something which allows you to identify your widget. Because, and here comes the difficult part: You have to do the moving yourself.
The widget, which is the grid's parent, receives the drop event and reads from the mime data, which widget wishes to me moved. From the QDropEvent it gets the point where the widget is to be moved. That's what you have to code: The actual repositioning in your grid layout. And don't forget to update the xml.
do a trick then you can able to drag QWidget also,
QPixmap *widgetPixmap = new QPixmap;
yourWidget->render(widgetPixmap); // rendering the current widget to t_iconTPixmap
Now use this widgetPixmap as the pixmap for yourDragObject->setPixmap();
example,
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton
&& iconLabel->geometry().contains(event->pos())) {
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
mimeData->setText(commentEdit->toPlainText());
QPixmap *widgetPixmap = new QPixmap;
yourWidget->render(widgetPixmap);
drag->setMimeData(mimeData);
drag->setPixmap(widgetPixmap);
Qt::DropAction dropAction = drag->exec();
...
}
}
The Qt wiki contains a QtQuick example on how to emulate the iOS icon interface with less then 80 lines of code.
You can find it here.

How to customize QCombobox with multiple comlumns

I am using QCombobox, i want to every item in QCombobox displays three icons. But currently, every item in QCombobox only displays one icon!
Every icon should be changed dynamically.
You should create new custom QAbstractItemDelegate and set it to QComboBox using void QComboBox::setItemDelegate ( QAbstractItemDelegate * delegate ) api.
In delegate, you need to implement
virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const = 0
as you required.
You will also need to use following API to provide different icon to combo box in userData, that you can use in deletegate's paint method to retrieve icon and draw it.
void QComboBox::addItem ( const QString & text, const QVariant & userData = QVariant() )
Summary:
When I implement as above, there icons only show as drop down list clicked. In normal situation, the text only show. So, for three icons and text show in normal situation we must reimplement paintEvent of QCombobox in case subclass QCombobox or using eventFilter to catch paintEvent of QCombobox without subclass QComboBox!
Thank for your all response!
Reimplement paintEvent, or use big icon image with all 3 icons on it.

How to insert QPushButton into TableView?

I am implementing QAbstractTableModel and I would like to insert a QPushButton in the last column of each row. When users click on this button, a new window is shown with more information about this row.
Do you have any idea how to insert the button? I know about delegating system but all examples are only about "how to edit color with the combo box"...
You can use
QPushButton* viewButton = new QPushButton("View");
tableView->setIndexWidget(model->index(counter,2), viewButton);
The model-view architecture isn't made to insert widgets into different cells, but you can draw the push button within the cell.
The differences are:
It will only be a drawing of a pushbutton
Without extra work (perhaps quite a bit of extra work) the button won't be highlighted on mouseover
In consequence of #1 above, you can't use signals and slots
That said, here's how to do it:
Subclass QAbstractItemDelegate (or QStyledItemDelegate) and implement the paint() method. To draw the pushbutton control (or any other control for that matter) you'll need to use a style or the QStylePainter::drawControl() method:
class PushButtonDelegate : public QAbstractItemDelegate
{
// TODO: handle public, private, etc.
QAbstractItemView *view;
public PushButtonDelegate(QAbstractItemView* view)
{
this->view = view;
}
void PushButtonDelegate::paint(
QPainter* painter,
const QStyleOptionViewItem & option,
const QModelIndex & index
) const
{
// assuming this delegate is only registered for the correct column/row
QStylePainter stylePainter(view);
// OR: stylePainter(painter->device)
stylePainter->drawControl(QStyle::CE_PushButton, option);
// OR: view->style()->drawControl(QStyle::CE_PushButton, option, painter, view);
// OR: QApplication::style()->drawControl(/* params as above */);
}
}
Since the delegate keeps you within the model-view realm, use the views signals about selection and edits to popup your information window.
You can use setCellWidget(row,column,QWidget*) to set a widget in a specific cell.

Resources