How to hide a QWidget under its parent? - qt

I have a modal QDialog, that on the click of a button slides a modeless child QDialog out from underneath it. The problem I have is that the child stays on top of its parent during the animation.
I think I could get away with applying a mask over the portion of the child that overlaps the parent, but it feels like I'm missing a more obvious way of just placing the child under the parent.
I'm using Qt 4.5. Here's some sample code:
void MainWindow::on_myMenu_triggered()
{
parentDlg = new QDialog(this);
parentDlg->setFixedSize(250, 250);
parentDlg->setModal(true);
parentDlg->show();
childDlg = new QDialog(parentDlg);
childDlg->setFixedSize(150, 150);
childDlg->show();
QTimeLine* timeLine = new QTimeLine(1000, this);
connect(timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(childDlgStepChanged(qreal)));
timeLine->start();
}
void MainWindow::childDlgStepChanged(qreal)
{
int parentX = parentDlg->frameGeometry().x();
int parentY = parentDlg->geometry().y();
// Move the child dialog to the left of its parent.
childDlg->move(parentX - 150 * step, parentY);
}
Thanks in advance.

Child widgets are always rendered over the parent so you would have to break that relationship in order to achieve the affect you are looking for directly. Then you could use raise() or lower() if both dialogs had the same parent.

Related

setParent() not showing child widget

I have a class called TitleBar inherited from QWidget and I created a new widget and did setparent() but after doing setparent child widget is not showing, it is showing only after commenting setparent but not alligned with parent, its displaying in some random placess, On maximized view only it shows on right place
TitleBar::TitleBar(QWidget *parent) : QWidget(parent)
{
m_jobSubmitWidget = csJobSubmitPoolWidget::getSubmitPoolInst();
// m_jobSubmitWidget->setParent(QWidget::window());
}
void csTitleBar::BtnClicked()
{
QPoint pos = m_queueBtn->pos() + m_serverToolBar->pos() + QPoint(-m_jobSubmitWidget->width() + m_queueBtn->width(),62); // these are member variables in TitleBar class
// pos shows always same value on moving parent widget
if(itemCount > 2){
m_jobSubmitWidget->move(pos);
m_jobSubmitWidget->show();
m_jobSubmitWidget->setFocus();
}
}
I really suggest that you take a good read at Qt documentation.
QWidgets that have a parent are displayed inside their parent (except for QDialog). If a widget does not have a parent, it will be shown as a separate window.
Parenting a widget to the result of QWidget::window() is kind of hazardous as you don't really know which widget will be returned, so you do not know where the child widget will end up.
Also you do not need to call show() on widgets that have a parent. By default their visibility follows the parent visibility.
In my case I also had to add the widget which I was changing the parent (here textEdit) to the target containing layout:
ui->textEdit->setParent(ui->groupBox1);
m_lastVboxLayout->removeWidget(ui->textEdit);
m_lastVboxLayout = ui->verticalLayout_groupBox1;
m_lastVboxLayout->addWidget(ui->textEdit);
no need to call show() afterwards.

Qt: Resizing QMenuBar corner widget

I put a push button into the top-right corner of my main window menu bar:
QPushButton *pb = new QPushButton("Text");
pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
QMainWindow *mainWindow;
mainWindow->menuBar()->setCornerWidget(pb, Qt::TopRightCorner);
The initial layout is fine. Sometime later, an asynchronous event changes the QPushButton's text to a longer string, but it gets clipped on the right.
I can see that the QPushButton's size changes when the string is updated. The QPushButton is displayed correctly if the window is resized. The problem appears to be getting the QMenuBar to recognize that the widget's size has changed.
This answer How to auto change QPushButton width and QMenuBar corner widget width when change text of button? suggests resetting the corner widget. I would rather avoid that, because my application's structure makes me jump through several ugly and awkward hoops to reset the corner widget after initializing.
The solution is simple. After updating the text of the button call menuBar()->adjustSize(); I have tested it in Qt5.5 and hope it will work for you.
You can use QWidgetAction as a horizontal menu widget:
class TestMenu : public QWidgetAction
{
public:
TestMenu(QObject *parent) :
QWidgetAction (parent)
{
}
virtual QWidget *createWidget(QWidget *parent)
{
QComboBox *combo = new QComboBox(parent);
combo->setFixedWidth(300);
return combo;
}
virtual void deleteWidget(QWidget *widget)
{
delete widget;
}
};
...
QMenu *menu = new QMenu();
menu->addAction(new TestMenu(this));
menuBar()->setCornerWidget(menu);

QGraphicsItem doesn't detect its own boundingRect change

// QT 4.8
I've implemented a resizable QGraphicsItem, which works pretty fine.
However, now, I need to include child items in this resizable item.
Child items size/position will obviously depend on parent one.
My problem is to notify childs when parent one is resized.
But so far, the parent itself doesn't detect its own size change (whereas on the scene, everything behave as expected!)
In the parent item (= the resizable one) item I've tried to override
QVariant itemChange(QGraphicsItemChange, QVariant)
in order to dump change events. I can see all events, but itemChange method never get called when item is (being) resized.
Any help greatly appreciated.
NB:
In my resizable QGraphicsItem constructor, I've enabled the flag QGraphicsItem::ItemSendGeometryChange
ResizableGraphicsItem::ResizableGraphicsItem(QGraphicsItem *p_parent,
qreal p_initialWidth,
qreal p_initialHeight)
: QGraphicsItem(p_parent), _width(p_initialWidth),
_height(p_initialHeight), _resized(true)
{
setFlag(ItemSendsGeometryChanges);
...
}
The resize method looks like the following:
void ResizableGraphicsItem::setSize(qreal p_width, qreal p_height)
{
prepareGeometryChange();
if ((_width != p_width) ||
(_height != p_height))
{
_width = p_width;
_height = p_height;
_resized = true;
}
}
with:
QRectF ResizableGraphicsItem::boundingRect() const
{
return QRectF(0, 0, _width, _height);
}

How do I set a relative position for a Qt widget?

I've been searching around and reading docs about moving widgets around, but I'm still looking for a good example.
I have a widget that I display with a hotkey, and I'd like it to popup somewhere else in the MainWindow rather than the center. If I use move(), then the widget remains in that position regardless if it's parent window changes position. I'd like the widget to be placed in a location inside of the parent widget so that when moving the parent widget, it stays in the relative position. How can I go about doing this?
I read about MapToParent, but I'm not sure how to use this. I tried:
QPoint fD_p = fDialog->pos();
QPoint parent_fD_p = QWidget::mapToParent(fD_p);
fDialog->move(parent_fD_p);
You should reimplement the move event handler in your parent widget void QWidget::moveEvent ( QMoveEvent * event ) and probably the resize event handler.
In these event handlers you can recalculate the new position for your widget and then move it.
mapToParent and mapFromParent methods translate relative coordinates. From the documentation:
QPoint QWidget::mapFromParent ( const QPoint & pos ) const
Translates the parent widget coordinate pos to widget coordinates.
Same as mapFromGlobal() if the widget has no parent.

Need to display the widgets inside my QListWidget with an offset, basically shifted a bit to the right

I have a panel.ui file done using QTDesigner. It's a QFrame class, rectangular shape with few labels on it. And I have a QListWidget class where I insert 3 instances of the panel.ui.
I create a QListWidgetItem and then use List->SetItemWidget(..) to populate my list.
The Result is a list filled with three panels. I was also able to move the panels inside the list using dragDropMode internalMove.
I also tested the ability to shift the panels a bit to the right when I click on them and that worked:
in procedure List::mousePressEvent(QMouseEvent *event)
Panel *child = static_cast<Panel*>(childAt(event->pos()))
...
int y= child->pos().y();
int x = child->pos().x();
child->move (x +10, y); `
Problem: When I run the app and display the list, I want all the panels to be displayed with that 10 offset to the right. So in the List constructor and inside the loop after this->setItemWidget(myPanelItem, myPanel); I try using myPanel->move() like above but it doesn't seem to work.
I run the app, the panels are displayed without my offset ( not sure why?) but when I click on one, it shifts.
move() won't work reliably since the widgets are in a layout. (Well, not a layout as in a QLayout, but the effect is comparable: When any metric in your application changes, e.g. you resize or scroll the list, the widgets are repositioned by the list widget.)
What you can do is wrap your actual widget in a container widget with a layout margin:
QWidget* wrapIntoContainerForOffset(QWidget* widget, int offset /*in pixels*/) {
QWidget* container = new QWidget;
QHBoxLayout* layout = new QLayout(container);
layout->setContentsMargins(/*left=*/ offset, /*others=*/ 0, 0, 0);
layout->addWidget(widget);
return container;
}
Then you add these containers to the listwidget instead.
Have You tried StyleSheets. The QListWidget supports Box model( http://doc.qt.digia.com/qt/stylesheet-customizing.html#box-model ). So You may want to try playing around with margins in the stylesheets.
Style sheet reference: http://doc.qt.digia.com/qt/stylesheet-reference.html

Resources