Derrived Widget not centered on parent when shown as dialog - c++

I have a class MyListWidget derrived from QWidget. I passed parent and flags to the base class QWidget constructor (tried both Qt::Dialog and Qt::Popup in tests) but the custom widget is shown in the center of the screen instead centered to its parent.
MyListWidget* myListWidget = new MyListWidget(this, Qt::Dialog);
This is the constructor:
MyListWidget::MyListWidget(QWidget* parent, Qt::WindowFlags flags)
: QWidget(parent, flags),
ui(std::auto_ptr<Ui::MyListWidget>(new Ui::MyListWidget))
{
ui->setupUi(this);
}
If I put this widget into a separate dialog, anything works as expected. But why?
Wrapping works:
QDialog* popup = new QDialog(this, Qt::Popup);
QVBoxLayout* hLayout = new QVBoxLayout(popup);
// ... doing list creation like above
hLayout->addWidget(mmyListWidget);
popup->setLayout(hLayout);
const int width = mapListWidget->width();
const int height = mapListWidget->height();
popup->resize(width, height);
Any ideas what could happend here?

QWidget is not shown on center by default, so you need to center it manually (you can do that in the constructor):
MyListWidget::MyListWidget(QWidget* parent, Qt::WindowFlags flags)
: QWidget(parent, flags),
ui(std::auto_ptr<Ui::MyListWidget>(new Ui::MyListWidget))
{
ui->setupUi(this);
move(
parent->window()->frameGeometry().topLeft() +
parent->window()->rect().center() - rect().center()
);
}
P.S. Beware of std::auto_ptr, you probably want to use std::unique_ptr these days.

I'm not quite sure what you're trying to achieve but I have the feeling you should derive MyListWidget from QDialog.
Regards,
Ben

Related

Change background color of a Qlayout containing QButtons

I have this Qt code:
QHBoxLayout *taggerBox = new QHBoxLayout;
falseBtn = new QToolButton;
falseBtn->setText(tr("False"));
voidBtn = new QToolButton;
voidBtn->setText(tr("Void"));
taggerBox->addWidget(falseBtn);
taggerBox->addWidget(voidBtn);
I would like to change the background of the QHBoxLayout (NOT the background of each button). I didn't find any way to change the background color of a QLayout.
How can I do this ?
Thanks!
QLayout is not a visual element, it's a container that adjust location of contained widgets. You can change background of QFrame or other widgets you included QLayout into.
Since QHBoxLayout is not a QWidget it hasn't its own appearance. So you can't change its color.
You'll have to add an intervening widget that you set the layout on, and change that widget's background. E.g.
auto *taggerBox = new QWidget;
auto *layout = new QHBoxLayout(taggerbox);
falseBtn = new QToolButton(tr("False"));
voidBtn = new QToolButton(tr("Void"));
layout->addWidget(falseBtn);
layout->addWidget(voidBtn);
auto palette = taggerBox->palette();
palette.setColor(QPalette::Window, Qt::blue);
taggerBox->setPalette(palette);
If you're doing this in the constructor of some class, then likely the objects have the same lifetime as the class as there's no point to dynamically allocate them. In such circumstances, the widgets and layouts should be class members instead:
class MyClass : ... {
QWidget taggerBox;
QHBoxLayout taggerLayout{&taggerBox};
QToolButton falseBtn{tr("False")};
QToolButton voidBtn{tr("Void")};
public:
MyClass(...);
};
MyClass::MyClass(...) : ... {
taggerLayout.addWidget(&falseBtn);
taggerLayout.addWidget(&voidBtn);
auto palette = taggerBox.palette();
palette.setColor(QPalette::Window, Qt::blue);
taggerBox.setPalette(palette);
...
}

adding a Q3DScatter to an existing QDialog form

I would like to insert a Q3DScatter instance onto one of my forms. I am able to construct the graph and display it with:
Q3DScatter *graph = new Q3DScatter();
QWidget *container = QWidget::createWindowContainer(graph);
...do some graph stuff...
container.show()
This successfully creates the graph and shows it in its own window/container. I would now like to place it inside another form that has been designed in qt-creator. I have placed an empty widget on the form(QDialog) as a placeholder, but am unable to move the Q3DScatter into the widget.
I see Q3DScatter::Q3DScatter(const QSurfaceFormat *format = Q_NULLPTR, QWindow *parent = Q_NULLPTR) in the documentation but I dont have a QWindow parent to attach it to, as the form I would like to add it to is a QDialog...
I am very new to widgets in general, so please correct me if this is the wrong approach.
Add the container as a child of the dialog. Put in a layout if you need to resize when the dialog is resized. Example:
MyDialog::MyDialog(Q3DScatter *scatter, QWidget *parent) : QDialog(parent)
{
QHBoxLayout * const l = new QHBoxLayout(this);
l->setMargin(0);
l->addWidget(QWidget::createWindowContainer(scatter, this);
}

QDockWidgets merging incorrectly

I have a QDockWidget class and a QMainWindow:
// docker.hpp
class Docker : public QDockWidget
{
Q_OBJECT
public:
Docker(QString title, QWidget* parent = 0);
}
// docker.cpp
Docker::Docker(QString title, QWidget* parent): QDockWidget(title, parent)
{
QWidget* widget = new QWidget(this);
widget.setMinimumSize(200, 200);
setWidget(widget);
widget->setStyleSheet("border:5px solid gray;");
setAllowedAreas(Qt::AllDockWidgetAreas);
}
// mainwindow.hpp
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent);
private slots:
void createDockers();
};
// mainwindow.cpp
MainWindow::MainWindow(QWidget* parent): QMainWindow(parent)
{
setDockOptions(dockOptions() |
QMainWindow::AllowTabbedDocks |
QMainWindow::GroupedDragging);
// The following line of code does not change the situation.
// setTabPosition(Qt::RightDockWidgetArea, QTabWidget::East);
// There are some other codes which connect a button to the void createDockers() method
}
void createDockers()
{
Docker* dock = new Docker("Docker", this);
dock->setFloating(true);
dock->show();
}
I am able to create two Dockers with clicks of the button mentioned above.
However, when I drag one QDockWidget onto the other, the border disappears and no tabs show up:
I am expecting the following to happen: (Achieved by spawning several QDockWidgets)
I am also noticing that one of the QDockWidgets did not vanish. Instead, it merged back to the MainWindow. This only happens if they are the "first two" QDockWidgets.
What caused this problem and how to solve it? I am trying to mimic this project.
I guess it's linked to the QMainWindow::GroupedDragging option. I'm pretty sure it should work well without it (I mean for the not showing tab issue). Do you have restrictions on dock position somewhere else? The documentation implies it could create issues: http://doc.qt.io/qt-5/qmainwindow.html#DockOption-enum
For the style issue, you may need to redefine it on tab event, because once tabbed, the widget may inherit the tab style instead of the dock widget style you defined (not certified at all ^^)
Last guess/thing you can try, is to start with the dock tabbed and not floating to see if you have any new bahaviour, it was what I was doing in a previous project and it was working pretty well.
Sorry but no other ideas for the moment.

How can set a Qwidget inside a QGraphicsWidget?

Is it possible that a QGraphicsWidget be a parent for QWidget? I have a QGraphicsItem and I want to add a QWidget inside this item, How can I set a QWidget in a QGraphicsItem or QGraphicsWidget that is a child of QGraphicsItem?
QGraphicsWidget is basically a QGraphicsItem for QWidgets ... it provides a layout you can use so it should be no problem at all
use:
QGraphicsScene::addWidget( QWidget * widget, Qt::WindowFlags wFlags = 0 )
QWidget and QGraphicsWidget are very different. However, the QGraphics system provides a QGraphicsProxyWidget for embedding QWidget and QWidget-based items in a QGraphicsScene.
You can directly create the QGraphicsProxyWidget and call the function setWidget, before adding the QGraphicsProxyWidget to your QGraphicsScene: -
QGraphicsScene* pScene = new QGraphicsScene;
QWidget* pWidget = new QWidget;
QGraphicsProxyWidget* pProxy = new QGraphicsProxyWidget(parent); // parent can be NULL
pProxy->setWidget(pWidget);
pScene->addItem(pProxy);
The proxy widget can now be moved, scaled etc in the scene and the functionality of its QWidget will have signals passed through to it to work as expected.
Alternatively, the QGraphicsScene contains a shortcut function addWidget, which internally creates the QGraphicsProxyWidget for you and returns it from the function: -
QGraphicsProxyWidget* pProxy = pScene->addWidget(pWidget);

How do I place the QScrollBar on the content of the QScrollArea?

I want to make a scrollbar that fades in and out depending on usage. I subclassed QScrollBar and got the look that I want. The problem is that the scrollbar is placed next to the content. How do I instead make it go on top of the content?
I created a new QScrollbar which I connected to the original via signals and then used widget->setParent and then widget->setGeometry() to paint it on top
I quicker solution is to reparent the QScrollBars that the QScrollArea creates and add it to a new QLayout to position it how you want.
QScrollArea *scrollArea = new QScrollArea();
QScrollBar *scrollBar = scrollArea->horizontalScrollBar();
scrollBar->setParent(scrollArea);
scrollBar->setFixedHeight(20);//required for later
QVBoxLayout *scrollAreaLayout = new QVBoxLayout(scrollArea);
scrollAreaLayout->setContentsMargins(0, 0, 0, 10);//use whatever margins you want
scrollAreaLayout->addStretch(1);
scrollAreaLayout->addWidget(scrollBar);
This gets the basic functionality working, however the QScrollArea still adds space where the scrollbar would have been. To remove this, subclass QProxyStyle and override pixelMetric().
#include <QProxyStyle>
class StyleFixes : public QProxyStyle
{
public:
int pixelMetric(PixelMetric metric, const QStyleOption *option = Q_NULLPTR, const QWidget *widget = Q_NULLPTR) const override
{
if(metric == PM_ScrollBarExtent)
{
return 0;
}
return QProxyStyle::pixelMetric(metric, option, widget);
}
};
Then just apply it in main.cpp
QApplication::setStyle(new StyleFixes);
This will remove the arrows on the scrollbar however so you'll need to style it yourself.