setParent() not showing child widget - qt

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.

Related

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);

Custom Qt designer widget : a scroll Area containing a custom vertical layout

I want to do something fairly simple : add a custom widget to Qt designer that would basically be a scrollArea containing a custom vertical layout(I added some code to the vertical layout in order to handle its objects for my projects).
The idea would be to represent a vertical menu that would be on the side of my screen
What I have done so far
I created the custom widget plugin and my custom layout.
My custom widget codes looks like this:
#include "menuwidget.h"
MenuWidget::MenuWidget(QWidget *parent) :
QScrollArea(parent)
{
this->setWidgetResizable(true);
QWidget* layoutHoldingWidget= new QWidget(this);
layout= new MenuLayout();
layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
layout->addStretch(1);
layoutHoldingWidget->setLayout(layout);
this->setWidget(layoutHoldingWidget);
}
If I add manually to the layout (in the constructor code) some buttons
for(int i =0;i<20;i++)
layout->addWidget(new QPushButton(this));
It does work and I can see my scrollArea containing some buttons, which is almost what I want.
What I want
I would like to be able to add these buttons directly via Qt designer: the user would first drag the empty MenuWidget on the main window, then would drag QPushButtons on my custom widget exactly like he would do on a regular vertical layout.
Is that possible?How could I do such a thing?
Thank you ! :)
Edit 1
What I was missing was the "scrollAreaWidgetContents" widget that is always created when you drag and drop a QScrollArea. I did a similar thing by adding a widget (let's call it containerWidget) to my custom scrollArea in its domXml function, which enables me to drag and drop widgets on my scroll Area like I wanted to do.
BUT there's still something I can't figure out : I want the containerWidget to have a customLayout (myCustomLayout) . If I add it in the domXml function, I get the following line in the terminal :
Designer:The layout type 'MyCustomLayout' is not supported,
defaulting to grid.
So it means that I can't tell designer to use my custom layout to place my widgets, which is kind of sad :D
Is there any way to "cheat" here?
There are two things to consider:
1) Overwrite in the class you derive from QDesignerCustomWidgetInterface the function to return true
bool isContainer() const { return true; }
This tells QtDesigner that the widget can contain children. (In Qt nearly any Widget can contain any widget as child, but QtDesigner tries to restrict it in a sensible way - e.g. you cant add children to a QLabel in QtDesigner)
2) Implement childEvent of your Widget. Probably in your case it would add Widgets added in QtDesigner to a layout.
Here is a core I've implemented to try this out. I've created a skeleton using "Qt Widget Plugin" Wizard in QtCreator and modified a little bit.
Don't forget to build as release, for the compiler/Qt-version of your QtDesigner , to copy the .dll and .lib files in \plugins\designer directory and to restart QtDesigner!
verticalplugin.cpp
//all other functions remained as created by QtCreator wizard
bool VerticalMenuPlugin::isContainer() const
{
return true;
}
VerticalMenu.h
#ifndef VERTICALMENU_H
#define VERTICALMENU_H
#include <QtGui/QWidget>
#include <QtGui/QVBoxLayout>
class VerticalMenu : public QWidget
{
Q_OBJECT
protected:
virtual void childEvent ( QChildEvent * event );
public:
VerticalMenu(QWidget *parent = 0);
};
#endif
VerticalMenu.cpp
#include "verticalmenu.h"
#include <QChildEvent>
VerticalMenu::VerticalMenu(QWidget *parent) :
QWidget(parent)
{
setLayout (new QVBoxLayout);
}
void VerticalMenu::childEvent ( QChildEvent * event )
{
if ( event->added() )
{
QWidget * newChild = qobject_cast<QWidget *>(event->child());
if ( newChild )
{
layout()->addWidget( newChild );
}
}
}
I hope' it would help as a starting point.
Qt 4 does not support custom layout plugins for designer, so I couldn't achieve what I wanted to do. I will instead use a Vertical Layout and try to implement the additional features that were supposed to be in the custom layout code in the widget code.

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.

How to hide a QWidget under its parent?

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.

how to add an widget into the Form In QtDesigner

in qdesigner_workbench.cpp, how can I add a widget (say QLabel) into a FormWindow by code?
Since methods like createWidget()...etc are all abstract, how do I properly use the internal mechanics to add QLabel into the active FormWindow?
EDIT:
In qdesigner_workbench.cpp, this is currently what I have:
QDesignerFormWindowManagerInterface* fwm = core()->formWindowManager();
QDesignerFormWindowInterface* fw = fwm->activeFormWindow();
QWidget* mw = fw->mainContainer();
QLabel* label = new QLabel(mw); //can be added correctly but not in the right hierarchy
label->setText("I am a good girl.");
The mw (obtained from fw->mainContainer()) is actually a MainWindow, however the real data I need is in:
mw -> children[2] (which is a QDesignerWidget) -> children
There are 9 widgets in the designer, and you can see there's 9 arrays in children mentioned above; see this link (an image) for illustration.
http://img24.imagevenue.com/img.php?image=98871_a_122_476lo.jpg
So... how can I correctly add the QLabel widget?
Tried both
QLabel* label = new QLabel(fw); // will be a sibling of MainContainer, which is the QMainWindow (mw) in this case
QLabel* label = new QLabel(mw); // will be a sibling of QDesignerWidget
and apprarently either of the works.
If you want just to display a widget on a form, you can set your QMainWindow or QDialog to be the widget parent:
QLabel *l = new QLabel(this);
l->setText("My long string");
Where this is a pointer pointing to your current QDialog or QMainWindow.
Otherwise as ufukgun pointed out, you can use setCentralWidget if you need your widget to occupy the center of the QMainWindow.
You should add any QWidget to the QLayout of the form.This will put it into the display strategy of the form when resizing it.
form->ui->layout->add(yourQWidget);
Depending of the QLayout you are using, parameters of the add function will not be the same.
create a widget and add it to your main window as it is your central widget
mainWindow->setCentralWidget(centralWidget);
if you want to add a label, you can add it to this central widget

Resources