I'm writing a qt program and trying to resize mainwindow when sub widget is hidden, but there's some difference in Linux and Windows, and I don't know the property way to adjust size in both.
Here's my minimum code:
// MainWindow
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *mainWidget = new QWidget(this);
QVBoxLayout *mainlayout = new QVBoxLayout(mainWidget);
QPushButton *hide = new QPushButton(mainWidget);
subwidget *sub = new subwidget(mainWidget);
mainlayout->addWidget(hide);
mainlayout->addWidget(sub);
connect(hide, &QPushButton::clicked, sub, &subwidget::onHide);
setCentralWidget(mainWidget);
adjustSize();
connect(hide, &QPushButton::clicked, this, [&] {
QTimer::singleShot(0, this, [&] { adjustSize(); });
});
}
// Widget
subwidget::subwidget(QWidget *parent)
: QWidget{parent}
{
QVBoxLayout *vlayout = new QVBoxLayout(this);
QPushButton *btn1 = new QPushButton();
btn2 = new QPushButton();
vlayout->addWidget(btn1);
vlayout->addWidget(btn2);
}
void subwidget::onHide()
{
btn2->hide();
}
When I set the timer interval to 1, mainwindow will be the adjusted size when btn2 is hidden in Linux, but it doesn't work in Windows. How can I adjust the mainwindow in windows?
PS: I have tried to add a signal when subwidget is hidden and connect it to adjustSize like connect(sub, &subwidget::hidden, this, [&] { adjustSize(); });, but it also doesn't work.
Related
please, help me to solve this probleme of qt;
QWidget::setLayout: Attempting to set QLayout "" on Login_1 "Login_1", which already has a layout ?
Login_1::Login_1(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::Login_1)
{
ui->setupUi(this);
//The main windows
QGridLayout* MainLayout = new QGridLayout();
//The first ligne (username, line 0)
QLabel* LbNom = new QLabel("User name");
QLineEdit* LeNom = new QLineEdit();
MainLayout->addWidget(LbNom,0,0);
MainLayout->addWidget(LeNom,0,1);
//The second line (password, line 1)
QLabel* LbPassword = new QLabel("Password");
QLineEdit* LePassword = new QLineEdit(this);
MainLayout->addWidget(LbPassword,1,0);
MainLayout->addWidget(LePassword,1,1);
//Login Button(line 2)
QPushButton* PbLogin = new QPushButton(this);
PbLogin->setText("Login");
MainLayout->addWidget(PbLogin,2,0);
//setLayout(MainLayout);
}
Login_1::~Login_1()
{
delete ui;
}
Thank you for your helping...
I create at first time a new widget:
QWidget* Mywidget = new QWidget();
After tha, I make for this widget (Mywidget) parent of my odd layout:
QGridLayout* MainLayout = new QGridLayout(Mywidget);
And it work
I would like to create custom QT dialog (non-modal). Problem with my implementation is that it shows only dialog window with title, and no widgets that I've added to it.
Code below (I've ommited most of it, added just dialog and main window parts).
MainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
/// some other stuff
private:
std::unique_ptr<ui::DialogAddUpdateItem> addItemDialog;
/// some other stuff
}
MainWindow.cpp
/// some stuff
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
/// some stuff
addItemButton = new QPushButton(tr("Add item"));
QObject::connect(addItemButton, &QPushButton::pressed, this, &MainWindow::openAddItemDialog);
navLay->addWidget(addItemButton);
addItemDialog = make_unique<ui::DialogAddUpdateItem>(this);
/// some stuff
}
void MainWindow::openAddItemDialog() {
addItemDialog->show();
//addItemDialog->raise(); does not work with or without those functions
//addItemDialog->activateWindow();
//QApplication::processEvents();
}
DialogAddUpdateItem.h
namespace ui {
class DialogAddUpdateItem : public QDialog
{
Q_OBJECT
public:
DialogAddUpdateItem(QWidget *parent = nullptr);
private:
QPushButton *buttonAcc, *buttonRevert, *buttonCancel;
QGroupBox *centralWidget, *buttonsWidget;
QLabel *labelName, *labelDescription;
QLineEdit *textName;
QPlainTextEdit *textDescription;
}
}
DialogAddUpdateItem.cpp
namespace ui {
DialogAddUpdateItem::DialogAddUpdateItem(QWidget *parent) : QDialog(parent)
{
if (!item) {
setWindowTitle(tr("New object"));
}
centralWidget = new QGroupBox;
QHBoxLayout *itemLay = new QHBoxLayout;
centralWidget->setLayout(itemLay);
labelName = new QLabel(tr("Name"));
itemLay->addWidget(labelName);
textName = new QLineEdit;
if (item) {
textName->setText(QString::fromStdString(item->getName()));
}
itemLay->addWidget(textName);
labelDescription = new QLabel(tr("Description"));
if (item) {
textDescription = new QPlainTextEdit(QString::fromStdString(item->getDescription()));
} else {
textDescription = new QPlainTextEdit;
}
itemLay->addWidget(textDescription);
buttonAcc = new QPushButton(tr("Save"));
buttonAcc->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QObject::connect(buttonAcc, &QPushButton::clicked, this, &DialogAddUpdateItem::acceptItem);
buttonRevert = new QPushButton(tr("Revert"));
buttonRevert->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QObject::connect(buttonRevert, &QPushButton::clicked, this, &DialogAddUpdateItem::revertItem);
buttonCancel = new QPushButton(tr("Cancel"));
buttonCancel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QObject::connect(buttonCancel, &QPushButton::clicked, this, &DialogAddUpdateItem::cancelItem);
buttonsWidget = new QGroupBox;
itemLay->addWidget(buttonsWidget);
QVBoxLayout *buttonsLay = new QVBoxLayout;
buttonsLay->addWidget(buttonAcc);
buttonsLay->addWidget(buttonRevert);
buttonsLay->addWidget(buttonCancel);
}
}
In DialogAddUpdateItem.cpp the centralWidget has no parent, therefore it is not bound to anything and therefore not displayed. You should modify this:
centralWidget = new QGroupBox;
into this:
centralWidget = new QGroupBox(this);
Now the DialogAddUpdateItem will be the parent of the centralWidget and it should display it.
Also it seems like You are leaving some other widgets without a parent - it might cause trouble. For example the QLineEdit textName has this issue.
I am trying to make a panel that shows some data, that gets added when I press a button. I will explain it trough these images:
this would be the initial state of the app, a window with a QGraphicsView
if I click "Help" it should display a window above it that never goes out of focus
I looked into using QDockWidget, but that just creates a panel next to it, that that's not what I Want. If anyone knows how to do this, I would be very grateful, thanks.
You can set children widgets in your QGraphicsView and consider it like a regular QWidget:
QApplication app(argc, argv);
QGraphicsScene* scene = new QGraphicsScene(0, 0, 1000, 1000);
QGraphicsView* view = new QGraphicsView(scene);
view->show();
QPushButton* button = new QPushButton("Show label");
QLabel* label = new QLabel("Foobar");
QVBoxLayout* layout = new QVBoxLayout(view);
layout->setAlignment(Qt::AlignRight | Qt::AlignTop);
layout->addWidget(button);
layout->addWidget(label);
label->hide();
QObject::connect(button, &QPushButton::clicked, label, &QLabel::show);
return app.exec();
The label will be visible in the QGraphicsView when you click on the button.
You can also embed a widget in your scene with QGraphicsProxyWidget class:
QApplication app(argc, argv);
QGraphicsScene* scene = new QGraphicsScene(0, 0, 1000, 1000);
scene->addItem(new QGraphicsRectItem(500, 500, 50, 50));
QGraphicsView* view = new QGraphicsView(scene);
view->show();
QWidget* w = new QWidget();
QGraphicsProxyWidget* proxy = new QGraphicsProxyWidget();
QPushButton* button = new QPushButton("Show label");
QLabel* label = new QLabel("Foobar");
QVBoxLayout* layout = new QVBoxLayout(w);
layout->addWidget(button);
layout->addWidget(label);
layout->setAlignment(Qt::AlignRight | Qt::AlignTop);
label->hide();
QObject::connect(button, &QPushButton::clicked, label, &QLabel::show);
proxy->setWidget(w);
scene->addItem(proxy);
return app.exec();
I have an application that has 3 main widgets. I also have a pop-out QDockWidget. I'm trying to get the QDockWidget to dock into the right half of the bottom widget, but as you can see in the image below, the only places I can dock the window are on the edges of the application. How can I make it so that the QDockWidget window takes up the right half of the bottom widget?
Also, is there a way to have a QDockWidget be already docked upon opening the application instead of having it open separately in its own window?
EDIT: Using #Bertrand's answer below, here's what I wound up doing:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
void on_actionRestore_layout_triggered();
QMainWindow* m_rightSideWindow;
QDockWidget* m_dockWidget1;
QDockWidget* m_dockWidget2;
QDockWidget* m_dockWidget3;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtWidgets>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_rightSideWindow(NULL),
m_dockWidget1(NULL),
m_dockWidget2(NULL),
m_dockWidget3(NULL)
{
ui->setupUi(this);
QSplitter *splitter = new QSplitter(this);
splitter->setOrientation(Qt::Horizontal);
QTreeView* leftSideWidget = new QTreeView(this);
m_rightSideWindow = new QMainWindow(this);
m_rightSideWindow->setWindowFlags(Qt::Widget);
m_rightSideWindow->layout()->setContentsMargins(3, 3, 3, 3);
splitter->addWidget(leftSideWidget);
splitter->addWidget(m_rightSideWindow);
m_dockWidget1 = new QDockWidget("Dock 1", this);
m_rightSideWindow->addDockWidget(Qt::TopDockWidgetArea, m_dockWidget1);
m_dockWidget1->setTitleBarWidget(new QWidget()); // remove title bar
m_dockWidget1->setAllowedAreas(Qt::NoDockWidgetArea); // do not allow to dock
QTextEdit* textEdit1 = new QTextEdit(this); // put any QWidget derived class inside
m_dockWidget1->setWidget(textEdit1);
m_dockWidget2 = new QDockWidget("Dock 2", this);
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, m_dockWidget2);
m_dockWidget2->setTitleBarWidget(new QWidget());
m_dockWidget2->setAllowedAreas(Qt::NoDockWidgetArea);
QTextEdit* textEdit2 = new QTextEdit(this);
m_dockWidget2->setWidget(textEdit2);
m_dockWidget3 = new QDockWidget("Dock 3", this);
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, m_dockWidget3);
QTextEdit* textEdit3 = new QTextEdit(this);
m_dockWidget3->setWidget(textEdit3);
setCentralWidget(splitter);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionRestore_layout_triggered()
{
QList<QDockWidget*> list = findChildren<QDockWidget*>();
foreach(QDockWidget* dock, list)
{
if(dock->isFloating())
dock->setFloating(false);
m_rightSideWindow->removeDockWidget(dock);
if (dock == m_dockWidget1)
m_rightSideWindow->addDockWidget(Qt::TopDockWidgetArea, m_dockWidget1);
else
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, dock);
dock->setVisible(true);
}
m_rightSideWindow->splitDockWidget(m_dockWidget2, m_dockWidget3, Qt::Horizontal);
}
You can dock a QDockWidget on a QMainWindow or another QDockWidget.
To get the desired layout embed a sub QMainWindow on the right side of your main window, and use it as a QWidget with setWindowFlags(Qt::Widget):
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtWidgets>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSplitter *splitter = new QSplitter(this);
splitter->setOrientation(Qt::Horizontal);
QTreeView* leftSideWidget = new QTreeView(this);
m_rightSideWindow = new QMainWindow(this);
m_rightSideWindow->setWindowFlags(Qt::Widget);
m_rightSideWindow->layout()->setContentsMargins(3, 3, 3, 3);
splitter->addWidget(leftSideWidget);
splitter->addWidget(m_rightSideWindow);
m_dockWidget1 = new QDockWidget("Dock 1", this);
m_rightSideWindow->addDockWidget(Qt::TopDockWidgetArea, m_dockWidget1);
m_dockWidget1->setTitleBarWidget(new QWidget()); // remove title bar
m_dockWidget1->setAllowedAreas(Qt::NoDockWidgetArea); // do not allow to dock
QTextEdit* textEdit1 = new QTextEdit(this); // put any QWidget derived class inside
m_dockWidget1->setWidget(textEdit1);
m_dockWidget2 = new QDockWidget("Dock 2", this);
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, m_dockWidget2);
m_dockWidget2->setTitleBarWidget(new QWidget());
m_dockWidget2->setAllowedAreas(Qt::NoDockWidgetArea);
QTextEdit* textEdit2 = new QTextEdit(this);
m_dockWidget2->setWidget(textEdit2);
m_dockWidget3 = new QDockWidget("Dock 3", this);
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, m_dockWidget3);
QTextEdit* textEdit3 = new QTextEdit(this);
m_dockWidget3->setWidget(textEdit3);
setCentralWidget(splitter);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionRestore_layout_triggered()
{
QList<QDockWidget*> list = findChildren<QDockWidget*>();
foreach(QDockWidget* dock, list)
{
if(dock->isFloating())
dock->setFloating(false);
m_rightSideWindow->removeDockWidget(dock);
if (dock == m_dockWidget1)
m_rightSideWindow->addDockWidget(Qt::TopDockWidgetArea, m_dockWidget1);
else
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, dock);
dock->setVisible(true);
}
m_rightSideWindow->splitDockWidget(m_dockWidget2, m_dockWidget3, Qt::Horizontal);
}
I am at trying to make a simple app which contains 2 pushButtons and QWidgetList with radiobuttons. All Ui-elements needs to be created manually. I tried to use signals like that, but Qt Creator doesn't compile this.
// window.h
namespace Ui {
class Window;
}
class Window : public QWidget
{
Q_OBJECT
public:
explicit Window(QWidget *parent = 0);
QPushButton * addButton;
QPushButton * removeButton;
QLineEdit textEdit;
QList<QRadioButton*> radioButtonList;
QGridLayout * layout;
public slots:
void addButton_clicked();
private:
QGroupBox *createRadiobuttonGroup();
QGroupBox *createPushButtonGroup();
QGroupBox *createTextEdit();
QGroupBox *createListWidget();
Ui::Window *ui;
};
//Window.cpp
Window::Window(QWidget *parent) :
QWidget(parent),
ui(new Ui::Window)
{
QGridLayout *grid = new QGridLayout;
grid->addWidget(createRadiobuttonGroup(), 0, 1);
grid->addWidget(createPushButtonGroup(), 1, 1);
grid->addWidget(createTextEdit(), 1, 0);
grid->addWidget(createListWidget(), 0, 0);
setLayout(grid);
setWindowTitle(tr("Group Box"));
resize(640, 480);
}
QGroupBox *Window::createListWidget()
{
QGroupBox *groupBox = new QGroupBox(tr("RadioButton List"));
QListWidget *radioButtonList = new QListWidget();
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(radioButtonList);
vbox->addStretch(1);
groupBox->setLayout(vbox);
QListWidgetItem *item = new QListWidgetItem();
radioButtonList -> addItem(item);
QString *value = new QString("Radiobutton value");
radioButtonList -> setItemWidget(item, new QRadioButton(tr(value->toUtf8())));
return groupBox;
}
QGroupBox *Window::createRadiobuttonGroup()
{
QGroupBox *groupBox = new QGroupBox();
QRadioButton *radio1 = new QRadioButton(tr("&Vetical"));
QRadioButton *radio2 = new QRadioButton(tr("&Horizontal"));
radio1->setChecked(true);
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(radio1);
vbox->addWidget(radio2);
vbox->addStretch(1);
groupBox->setLayout(vbox);
return groupBox;
}
QGroupBox *Window::createPushButtonGroup()
{
QGroupBox *groupBox = new QGroupBox();
QPushButton *addButton = new QPushButton(tr("&Add"));
QPushButton *renameButton = new QPushButton(tr("&Remove"));
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(addButton);
vbox->addWidget(renameButton);
vbox->addStretch(1);
groupBox->setLayout(vbox);
return groupBox;
}
QGroupBox *Window::createTextEdit()
{
QGroupBox *groupBox = new QGroupBox();
QLineEdit *textEdit = new QLineEdit();
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget (textEdit);
vbox->addStretch(1);
groupBox->setLayout(vbox);
connect(addButton, SIGNAL(clicked()), this, SLOT(addButton_clicked()));
return groupBox;
}
void Window::addButton_clicked()
{
QRadioButton radio_btn = new QRadioButton("name");
vbox << radio_btn; // append radio button to the list
vbox->addWidget(radio_btn);
}
void Window::addButton_clicked()
{
QRadioButton radio_btn = new QRadioButton("name");
vbox << radio_btn; // append radio button to the list
vbox->addWidget(radio_btn);
}
Variable vbox does not exist in that scope. And even if it did, QVBoxLayout does not have a << operator, so you can't use that. You also call it a list for some reason.