QTabWidget with dynamic change widgets - c++

I'm using QTabWidget (pHTab composed in AbstractManagerTab) to show some data
(IpTrafficPage and SpecTrafficPage widgets),
and I need to dynamically add QPushButtons to added tabs.
When I start application, added buttons are visible only at the last tab.
What could be wrong?
class AbstractTrafficPage : public QWidget
{
Q_OBJECT
public:
explicit AbstractTrafficPage(QWidget *parent = 0);
void addCommandButton(QWidget *btn);
private:
QVBoxLayout *commBtnsLayout;
};
AbstractTrafficPage::AbstractTrafficPage(QWidget *parent) :
QWidget(parent),
commBtnsLayout(new QVBoxLayout)
{
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(commBtnsLayout);
mainLayout->addStretch();
setLayout(mainLayout);
}
void AbstractTrafficPage::addCommandButton(QWidget *btn)
{
commBtnsLayout->addWidget(btn);
}
class IpTrafficPage : public AbstractTrafficPage
{
Q_OBJECT
public:
explicit IpTrafficPage(QWidget *parent = 0) : AbstractTrafficPage(parent) {};
};
class SpecTrafficPage : public AbstractTrafficPage
{
Q_OBJECT
public:
explicit SpecTrafficPage(QWidget *parent = 0) : AbstractTrafficPage(parent) {};
};
class AbstractManagerTab : public QWidget {
public:
AbstractManagerTab(QWidget *parent);
~AbstractManagerTab();
void addCommandButton(QWidget *btn);
private:
QTabWidget *pHTab;
}
AbstractManagerTab::AbstractManagerTab(QWidget *parent) :
QWidget(parent),
pHTab(new QTabWidget)
{
IpTrafficPage *ipPage = new IpTrafficPage(this);
pHTab->addTab(ipPage, tr("IP);
SpecTrafficPage *specPage = new SpecTrafficPage(this);
pHTab->addTab(specPage, tr("Spec"));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(pHTab);
setLayout(mainLayout);
}
AbstractManagerTab::~AbstractManagerTab()
{
delete pHTab;
}
AbstractManagerTab::addCommandButton(QWidget *btn)
{
for (int index = 0; index < pHTab->count(); ++index) {
AbstractTrafficPage *page = dynamic_cast<AbstractTrafficPage *>
(pHTab->widget(index));
if (page)
page->addCommandButton(btn);
}
}
class StoredRecsTab : public AbstractManagerTab
{
Q_OBJECT
public:
explicit StoredRecsTab(QWidget *parent = 0);
};
StoredRecsTab::StoredRecsTab(QWidget *parent) :
AbstractManagerTab(parent)
{
QPushButton *createRecBtn = new QPushButton(tr("Create"), this);
QPushButton *removeRecBtn = new QPushButton(tr("Remove"), this);
addCommandButton(createRecBtn);
addCommandButton(removeRecBtn);
}

Any QWidget can have only one parent. If you want to add a button to many widgets, you need to create many button objects (one per tab).
Another option is to move the button to the visible tab on tab change. But I think it's not so good decision.

Related

QPalette propagation to QDialog not working

I have set a dark theme on my QWidget. In that widget I call a QDialog. The dialog appears in default palette which is light.
This is my custom dialog (Which in this case is for choosing colors for palette! Twisted right?) .cpp file:
#include "custompalettedialog.h"
CustomPaletteDialog::CustomPaletteDialog(QPalette palette, QWidget *parent) : QDialog(parent),
m_palette(palette)
{
QVBoxLayout* mainLayout = new QVBoxLayout(this);
mainLayout->setSpacing(0);
mainLayout->setMargin(0);
QFormLayout* mainFormLayout = new QFormLayout;
mainFormLayout->setHorizontalSpacing(0);
mainFormLayout->setVerticalSpacing(0);
mainLayout->addLayout(mainFormLayout);
for (int var = 0; var < QPalette::ColorRole::NColorRoles; ++var) {
QPushButton* bandButton = new QPushButton;
bandButton->setFlat(true);
bandButton->setAutoFillBackground(true);
QPalette pal = bandButton->palette();
pal.setColor(QPalette::Button, m_palette.color(static_cast<QPalette::ColorRole>(var)));
bandButton->setPalette(pal);
connect(bandButton, &QPushButton::clicked, this, [this, bandButton, var]() {
QColor color = QColorDialog::getColor();
if (color.isValid()) {
m_palette.setColor(static_cast<QPalette::ColorRole>(var), color);
QPalette pal = bandButton->palette();
pal.setColor(QPalette::Button, color);
bandButton->setPalette(pal);
}
});
mainFormLayout->addRow(QVariant::fromValue(static_cast<QPalette::ColorRole>(var)).toString(), bandButton);
}
QPushButton* doneButton = new QPushButton("Done");
connect(doneButton, &QPushButton::clicked, this, &QDialog::accept);
mainLayout->addWidget(doneButton);
}
QPalette CustomPaletteDialog::getPalette()
{
return m_palette;
}
QPalette CustomPaletteDialog::getPalette(bool* ok, const QPalette palette, QWidget *parent, const QString title)
{
CustomPaletteDialog* dialog = new CustomPaletteDialog(palette, parent);
dialog->setFont(parent->font());
dialog->setModal(true);
dialog->setWindowTitle(title);
dialog->exec();
QPalette pal = dialog->getPalette();
*ok = dialog->result();
dialog->deleteLater();
return pal;
}
and the .h file:
#ifndef CUSTOMPALETTEDIALOG_H
#define CUSTOMPALETTEDIALOG_H
#include <QDialog>
#include <QFormLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QColorDialog>
#include <QComboBox>
class CustomPaletteDialog : public QDialog
{
Q_OBJECT
public:
explicit CustomPaletteDialog(QPalette palette, QWidget *parent = nullptr);
static QPalette getPalette(bool* ok, const QPalette palette, QWidget *parent = nullptr, const QString title = QString());
QPalette getPalette();
private:
QPalette m_palette;
};
#endif // CUSTOMPALETTEDIALOG_H
I call the static method getPalette from a parent widget.
I have tried adding this:
dialog->setPalette(parent->palette());
before dialog->setFont(parent->font()); in that static method and not working. My question is how to propagate QPalette from parent QWidget to child QDialog?
This is how I used it:
QPushButton* paletteAddButton = new QPushButton("Add...");
mainGroupBoxLayout->addWidget(paletteAddButton);
connect(paletteAddButton, &QPushButton::clicked, this, [this, customThemeItemModel]() {
bool ok = false;
QPalette palette = CustomPaletteDialog::getPalette(&ok, this->palette(), this, "Chosse UI Palette");
if (ok) {
QStandardItem* item = new QStandardItem("newPalette");
item->setToolTip("Double Click to Change Name, Right Click for More");
item->setData(palette);
customThemeItemModel->appendRow(item);
saveThemes(customThemeItemModel);
}
});
I have a list of themes, user can add custom themes to that list.

QLineEdit bug in access to its text

please guide me in finding the problem of this simplified code in reading text from qlineedit. My code exit in editUser->text() line. Every thing else is ok when I remove this line.
#include ...
QString USERID_LOG="SomeThing";
logDialog::logDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::logDialog)
{
ui->setupUi(this);
QLineEdit* editUser= new QLineEdit( this );
QPushButton* okButton = new QPushButton(tr("OK"));
connect(okButton, SIGNAL(clicked()), this,SLOT(okSlot()));
...
}
void logDialog::okSlot()
{ USERID_LOG=editUser->text(); //////// Error is here
logDialog::accept();
return; }
QString logDialog::GetUser()
{
return(USERID_LOG);
}
////////////////////////////logdialog.h/////////////////////////
QT_BEGIN_NAMESPACE
namespace Ui { class logDialog; }
QT_END_NAMESPACE
class logDialog : public QDialog
{
Q_OBJECT
public:
logDialog(QWidget *parent = nullptr);
~logDialog();
QString GetUser();
public slots:
void okSlot();
private:
QLineEdit* editUser;
QPushButton* okButton;
Ui::logDialog *ui;
};
Consider your constructor...
logDialog::logDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::logDialog)
{
ui->setupUi(this);
QLineEdit* editUser= new QLineEdit( this );
QPushButton* okButton = new QPushButton(tr("OK"));
connect(okButton, SIGNAL(clicked()), this,SLOT(okSlot()));
...
}
The lines...
QLineEdit* editUser= new QLineEdit( this );
QPushButton* okButton = new QPushButton(tr("OK"));
redeclare/redefine two locally scoped variables editUser and okButton that shadow the member variables of the same names. Instead you should simply initialize the member variables themselves...
editUser= new QLineEdit( this );
okButton = new QPushButton(tr("OK"));
Or, perhaps better, perform the initialization in the ctor's initializer list...
logDialog::logDialog(QWidget *parent)
: QDialog(parent)
, editUser(new QLineEdit(this))
, okButton(new QPushButton(tr("OK")))
, ui(new Ui::logDialog)
{
ui->setupUi(this);
connect(okButton, SIGNAL(clicked()), this,SLOT(okSlot()));
...

Qt dialog not showing its widgets

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.

Why doesn't setCentralWidget work?

Here is my class MainWindow :
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
menu* v = new menu(this);
setCentralWidget(v);
}
And my menu class :
menu::menu(MainWindow* parent){
QLabel l = new QLabel("123");
QVBoxLayout* lay = new QVBoxLayout;
lay->addWidget(l);
this->setLayout(lay);
QWidget* a = new QWidget;
QVBoxLayout* lay2 = new QVBoxLayout;
QLabel* ll = new QLabel("456");
lay2->addWidget(ll);
a->setLayout(lay2);
parent->setCentralWidget(a);
}
When I run the program, the window shows 123 but I would like it to show 456.
Is the method setCentralWidget not working?
setCentralWidget works ok.
You are mixing up your widget menu construction with its position in an external widget (MainWindow). You should keep these thing well separated, or you won't be able, for example, to use menu inside other widgets.
So, you should set the appearance of menu in the constructor, and call setCentralWidget only in MainWindow.
It should look like:
file.h
menu::menu(QWidget* parent = 0);
file.cpp
menu::menu(QWidget* parent) : QWidget(parent)
{
// Create items
QLabel* l = new QLabel("123", this);
QLabel* ll = new QLabel("456", this);
// Put items in layout
QVBoxLayout* lay = new QVBoxLayout();
lay->addWidget(l);
lay->addWidget(ll);
// Set "lay" as the layout of this widget
setLayout(lay);
}
UPDATE
Since the wanted behavior is to have an interface that switch view according to button clicks:
the best option is to use a QStackedWidget.
Here a sample code the will produce this interface using QStackedWidget.
widget1.h
#ifndef WIDGET1
#define WIDGET1
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
class Widget1 : public QWidget
{
Q_OBJECT
public:
Widget1(QWidget* parent = 0) : QWidget(parent) {
QPushButton* btn = new QPushButton("Button Widget 1", this);
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(btn);
setLayout(layout);
connect(btn, SIGNAL(clicked()), SIGNAL(buttonClicked()));
}
signals:
void buttonClicked();
};
#endif // WIDGET1
widget2.h
#ifndef WIDGET2
#define WIDGET2
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
class Widget2 : public QWidget
{
Q_OBJECT
public:
Widget2(QWidget* parent = 0) : QWidget(parent) {
QPushButton* btn1 = new QPushButton("Button 1 Widget 2", this);
QPushButton* btn2 = new QPushButton("Button 2 Widget 2", this);
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(btn1);
layout->addWidget(btn2);
setLayout(layout);
connect(btn2, SIGNAL(clicked()), SIGNAL(button2Clicked()));
}
signals:
void button1Clicked();
void button2Clicked();
};
#endif // WIDGET2
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStackedWidget>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void buttonWidget1Clicked();
void button2Widget2Clicked();
private:
QStackedWidget* m_sw;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QVBoxLayout>
#include <QLabel>
#include "widget1.h"
#include "widget2.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create Widgets
Widget1* w1 = new Widget1(this);
Widget2* w2 = new Widget2(this);
QLabel* w3 = new QLabel("Result", this);
m_sw = new QStackedWidget(this);
m_sw->addWidget(w1);
m_sw->addWidget(w2);
m_sw->addWidget(w3);
setCentralWidget(m_sw);
connect(w1, SIGNAL(buttonClicked()), this, SLOT(buttonWidget1Clicked()));
connect(w2, SIGNAL(button2Clicked()), this, SLOT(button2Widget2Clicked()));
}
void MainWindow::buttonWidget1Clicked()
{
m_sw->setCurrentIndex(1); // Will show Widget2
}
void MainWindow::button2Widget2Clicked()
{
m_sw->setCurrentIndex(2); // Will show Widgee3
}
MainWindow::~MainWindow() {}

Add/remove radio button to/from QListWidget by another button? Qt

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.