I try to create a custom widget like this:
device.h
class Device : public QWidget
{
Q_OBJECT
public:
explicit Device(QWidget *parent = 0);
};
device.cpp
Device::Device(QWidget *parent) :
QWidget(parent)
{
setGeometry(QRect(0, 0, 100, 100));
setStyleSheet(QString::fromUtf8("background: black;"));
raise();
setVisible(true);
qDebug() << "is visible: " << isVisible();
}
The constructor tries to create the square widget with black background. But I see nothing on my MainWindow and have output like:
is visible: false
It seems I create the device object correctly (ui->centralWidget is parent):
// MainWindow constructor
// device and button pointers defined in mainwindow.h
device = new Device(ui->centralWidget);
button = new QPushButton("Push me!", ui->centralWidget);
I think I could see black square with button or only black square overlaped the button. But I see only the button without any square.
It is not clear for me even because I call setVisible(true) and get isVisible() as false in the next line. But the button (the same child of QWidget) is visible. Where is difference?
The parent widget is likely invisible. Order of events matter, if the parent becomes visible after the constructor of Device, then the isVisible will work as intended when called from a different function after it is displayed. Otherwise, if the parent widget is hidden, all of it's children widgets are also hidden (even if you explicitly state otherwise for the children widgets). When do you call show() on the parent widget? Without a Minimal, Complete, and Verifiable Example
we can only speculate.
Related
I have a MainWindow class and a custom title bar widget.
When I set the title bar widget's parent to the MainWindow and attempt to maximize, it doesn't fully maximize the window.
titleBar(QWidget* parent) {
this->setParent(parent);
if (!this->parentWidget()->isMaximized()) {
this->parentWidget()->showMaximized();
}
}
However, if I have a member variable in the titleBar class to store the address of the MainWindow, i.e. QWidget* m_parent, it works.
titleBar(QWidget* parent) {
m_parent = parent;
if (!m_parent->isMaximized()) {
m_parent->showMaximized();
}
}
Printing m_parent and this->parentWidget() yields the same address too. Why does the behavior differ? I'm using Qt 5.15
I hope this has not been asked before, but I have not found any thread that answers my specific question.
I have created my own QDialog class(TagPopup), which accurately displays the layout I have specified in its Constructor. The QDialog is created in the center of the parent - as expected - but when I move the parent the Dialog stays at its original position. I want it to always stay at the center of the parent widget regardless of where it moves.
The parent is a custom class derived from QMainWindow (PlayerWindow).
WindowFlags of the parent class have not been altered, but the child has to be modal, has to have Qt::WA_TranslucentBackground as an attribute and the Qt::FramelessWindowHint has to be set.
Is this only solvable by overriding the parents move event and then have the child move with it or is there a more elegant solution?
void PlayerWindow::open_tag_dialog(int id) {
TagPopup *dialog = new QDialog(this, GameTag::int_to_tag_type(id), (int) 1000000 * elapsed_seconds(), {this->clip->game->home_team, this->clip->game->away_team});
dialog->show();}
This is the method on the parent Widget which creates and shows the Dialog.
explicit TagPopup(QWidget *parent = 0, TagType tag_type = TagType::CUSTOM, int time = 0, vector<Team*> teams = {}, int min_height = 360) : QDialog(parent, Qt::FramelessWindowHint), BasePlayer(min_height, this){
setModal(true);
setAttribute(Qt::WA_TranslucentBackground);
Qt::WindowFlags flags = windowFlags();
setWindowFlags(flags | Qt::WindowStaysOnTopHint);
These are the first lines of the child constructor, which deal with setting the flags and attributes.
I have definitely tried removing all flags, but that also does not help.
Is QDialog for creating something like a popup? It seemed like the obvious pick. Adding the Qt::Popup flag didn't change the behaviour. It instead broke the whole layout when I passed it to the constructor and didn't add any other flags. Therefore didn't meddle with that idea for too long.
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.
I want to open a Widget from my MainWindow. I thought this was easy to do, and all the tutorials I read do it like this:
void MainWindow::on_pushButton_Types_clicked()
{
m_typesWin = new TypesWindow(m_db, this);
m_typesWin->show();
this->hide();
}
However, this only works for me if I don't pass "this" into the constructor. When I add "this" to the constructor, I don't see the widget, the program just stops. If I don't hide "this", then I can see that parts of my widget are actually in my main window. I have no idea why.
EDIT: The classes are automatically created by QtCreator, so they should be alright.
If you want a QWidget to be displayed as a window, a parent widget should not be specified to that widget. Here, because you specify main window as the parent of TypesWindow, TypesWindow becomes embedded in main window. So when you hide main window, TypesWindow embedded in main window also gets hidden.
Since you want TypesWindow to be a separate window, don't pass parent widget to the QWidget constructor in TypesWindow constructor. If you want to access main window from TypesWindow, you can store main window pointer in a pointer field in TypesWindow.
To open a Mainwindows from the new Qwidget:
1)in the NEWWIDGET.CPP:
QWidget *w;
NEWWIDGET::NEWWIDGET(QWidget *parent,QWidget *win) :
QWidget(parent),
ui(new Ui::NEWWIDGET)
{
ui->setupUi(this);
w=win;
}
..
void NEWWIDGET::on_pushButton_clicked()
{
this->hide();
w->show();
}
2)In the NEWWIDGET.H
public:
explicit NEWWIDGET(QWidget *parent=nullptr,QWidget *win=nullptr);
~NEWWIDGET();
I have a problem with QDialog which is not displayed centered on the parent window.
The following snippet explains it:
void MyWidget::showDialog() {
QObject* p = parent();
while (p!=0) {
qDebug() << p;
p = p->parent();
}
qDebug() << QApplication::activeWindow();
MyClassDerivedFromQDialog dlg( this );
if ( dlg.exec() != dlg.Accepted ) {
return;
}
... do something
}
The output on qDebug is the following
QSplitter(0x2d89930, name = "splitter")
MyWidget(0x2d89670, name = "widget")
MainWindow(0x27ef20, name = "application")
MainWindow(0x27ef20, name = "application")
Executing my example opens the dialog somewhere on the screen. Passing QApplication::activeWindow() as a parent to the dialogs constructor results in a dialog centered on the main window. So why is that and how to track down the problem?
I found that this behavior is related to the timing of the dialog creation.
If you create a QDialog (or a derived class) before the dialog parent is shown (e.g., in the parent constructor), the dialog is displayed at a non-predictable location (or at least, not where you'd expect it to show).
However, if the dialog is created after the parent is displayed, then you get the expected behavior.
For example, if you have a button invoking your dialog. Both the button and the dialog are children of the same widget, so the dialog parent is the same as the button parent. In this case, it is advised to delay the dialog creation until the button is clicked, not before that.
This way, you ensure the dialog is created only after the parent is shown.
I am not sure if understand your problem.
QDialogs are always centered on the widget you pass as parent. This is by design. So if you pass "activeWindow()" as parent it is centered on the active window. If you pass "this" as a parent the dialog is centered above MyWidget.
In which way does your dialog not respect these rules?
The Dialog class is instantiated via
MyClassDerivedFromQDialog::MyClassDerivedFromQDialog(QWidget *parent)
: QDialog(parent),
ui(new Ui::MyClassDerivedFromQDialog)
{
ui->setupUi(this);
//remove the ? button in titlebar
Qt::WindowFlags flags = windowFlags();
Qt::WindowFlags helpFlag = Qt::WindowContextHelpButtonHint;
flags = flags & (~helpFlag);
setWindowFlags(flags);
}
And i always use it as in the showDialog function in the initial post. sometimes it works... And no, i do not have two MyWigets which are parents of each other.