qt vertical and horizontal layouts inside gridlayout? - qt

I am new to Qt App Development. I am attaching two screen shots, one is the desired ui and other is created one using code.
I believe my code will explain things, instead of my typing here and confusing all my friends here. What needs to be changed /updated?
/* HEADER FILE */
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
// Ui::Widget *ui;
};
#endif // WIDGET_H
/*Implementation Code */
#include "widget.h"
#include "ui_widget.h"
#include<QGridLayout>
#include<QVBoxLayout>
#include<QHBoxLayout>
Widget::Widget(QWidget *parent) :
QWidget(parent)//,
//ui(new Ui::Widget)
{
this->setGeometry(50,50,850,650);
QGridLayout *gridLayout= new QGridLayout(this);
setLayout(gridLayout);
QVBoxLayout *vLayout = new QVBoxLayout(this);
QHBoxLayout *hLayout = new QHBoxLayout(this);
//QWidget *tmp1 = new QWidget(this);
//QWidget *tmp2 = new QWidget(this);
// tmp1->setLayout(vLayout);
// tmp2->setLayout(hLayout);
gridLayout->addLayout(vLayout,0,3);
gridLayout->addLayout(hLayout,3,0);
//gridLayout->addWidget(tmp1,0,3,1,1);
//gridLayout->addWidget(tmp2,3,0,1,1);
QWidget *w = new QWidget(this);
QWidget *w1 = new QWidget(this);
QWidget *w2 = new QWidget(this);
QWidget *w3 = new QWidget(this);
QWidget *w11 = new QWidget(this);
QWidget *w22 = new QWidget(this);
QWidget *w33 = new QWidget(this);
QWidget *w4 = new QWidget(this);
QWidget *w5 = new QWidget(this);
w->setStyleSheet("background-color:rgb(0,0,0);");
w1->setStyleSheet("background-color:rgb(255,0,0);");
w2->setStyleSheet("background-color:rgb(255,0,255);");
w3->setStyleSheet("background-color:rgb(0,255,0);");
w11->setStyleSheet("background-color:rgb(255,0,0);");
w22->setStyleSheet("background-color:rgb(255,0,255);");
w33->setStyleSheet("background-color:rgb(0,255,0);");
w4->setStyleSheet("background-color:rgb(0,0,255);");
w5->setStyleSheet("background-color:rgb(255,255,0);");
vLayout->addWidget(w1);
vLayout->addWidget(w2);
vLayout->addWidget(w3);
vLayout->addWidget(w11);
vLayout->addWidget(w22);
vLayout->addWidget(w33);
hLayout->addWidget(w4);
hLayout->addWidget(w5);
gridLayout->addWidget(w,0,0,2,2);
show();
}
Widget::~Widget()
{
//delete ui;
}

The code doesn't look so bad. In my opinion, you just need to tweak the parameters to your addWidget/addLayout calls. Think about what your grid-layout should be like, and then choose the parameters accordingly.
I would try it like this:
// Desired grid layout is of size 2x2:
// .................
// . row0 . row0 .
// . col0 . col1 .
// .................
// . row1 . row1 .
// . col0 . col1 .
// .................
// Big widget at row 0, column 0
gridLayout->addWidget (w, 0, 0);
// "Horizontal group" at row 1, column 0
gridLayout->addLayout (hLayout, 1, 0);
// "Vertical group" at rows 0+1 (i.e. rowspan 2), column 1
gridLayout->addLayout (vLayout, 0, 1, 2, 1);
Does that work better (I havent tried it out myself)?

Related

How to avoid hidden QWidget height included in QStackedLayout?

I have this scenario with which I have been struggling for few hours:
I have a main widget, whose layout is set to main_layout, before which 3 layouts are added to the main_layout:
A QVBoxLayout (header_app_layout)
A second QVBoxLayout (header_loader_layout)
A QStackBoxLayout (content_layout)
The QStackBoxLayout (content_layout) has 2 child widgets added to it, of which only 1 is shown:
m_content1_widget (shown widget)
m_content2_widget
My problem is that, content_layout is taking into consideration the heights of the hidden child widgets in the widget: m_content1_widget, because of which the main_widget height is overflowing.
If I change content_layout from QStackedLayout to QVBoxLayout type, it all starts working fine.
So it seems to me that, QStackedLayout is respecting the height of the hidden widgets, which I don't want it to. Any ideas to overcome this ?
Here is the code:
main.cpp
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
main_widget w;
w.setFixedSize(400, 400);
w.show();
return app.exec();
}
main_widget.h
#include <QWidget>
#include <QLabel>
#include <QStackedLayout>
#include <QVBoxLayout>
#include <QPushButton>
class main_widget : public QWidget
{
Q_OBJECT
public:
main_widget();
};
main_widget.cpp
#include "main_widget.h"
main_widget::main_widget()
: QWidget(nullptr)
{
QVBoxLayout *header_app_layout = new QVBoxLayout();
QLabel *header_app_label = new QLabel();
header_app_label->setText(tr("Header"));
header_app_layout->addWidget(header_app_label);
QVBoxLayout* header_loader_layout = new QVBoxLayout();
QLabel* header_loader_label = new QLabel();
header_loader_label->setText(tr("Header Loader"));
header_loader_layout->addWidget(header_loader_label);
QWidget *m_content1_widget = new QWidget();
QVBoxLayout* content1_layout = new QVBoxLayout(m_content1_widget);
QPushButton* content1_button1 = new QPushButton(tr("content1_button1"));
content1_layout->addWidget(content1_button1);
QPushButton* content1_button2 = new QPushButton(tr("content1_button2"));
content1_layout->addWidget(content1_button2);
QPushButton* content1_button3 = new QPushButton(tr("content1_button3"));
content1_layout->addWidget(content1_button3);
content1_button2->hide(); //Hidden for now. But it's height is being included
content1_button3->hide();
QWidget* m_content2_widget = new QWidget();
QVBoxLayout* content2_layout = new QVBoxLayout(m_content2_widget);
QPushButton* content2_button1 = new QPushButton(tr("content2_button1"));
content2_layout->addWidget(content2_button1);
QPushButton* content2_button2 = new QPushButton(tr("content2_button2"));
content2_layout->addWidget(content2_button2);
QPushButton* content2_button3 = new QPushButton(tr("content2_button3"));
content2_layout->addWidget(content2_button3);
content2_button2->hide();
content2_button3->hide();
QStackedLayout* content_layout = new QStackedLayout(); //Doesn't work
//QVBoxLayout *content_layout = new QVBoxLayout(); //Works, but I need it to be of type `QStackedLayout` to show the 2 child widgets conditionally
content_layout->addWidget(m_content1_widget);
content_layout->addWidget(m_content2_widget);
content_layout->setStackingMode(QStackedLayout::StackingMode::StackOne);
content_layout->setCurrentIndex(0);
QVBoxLayout* main_layout = new QVBoxLayout;
main_layout->addLayout(header_app_layout); //Adding a QVBoxLayout
main_layout->addLayout(header_loader_layout); //Adding another QVBoxLayout
main_layout->addSpacing(32);
main_layout->addLayout(content_layout); //Adding the QStackedLayout
this->setLayout(main_layout);
}
I was able to resolve the issue by calling adjustSize on m_content2_widget, which removed the space occupied by the hidden controls inside m_content2_widget.
m_content2_widget->adjustSize();

how to make a widget of multiple other widget in QT

I am new in Qt and am using qt creator for the GUI designing, now i have to make a dynamic form in which a label,line edit and a button are added for each feature like length,width,etc.However the features are not static there may be 2 feature sometime and other time there might be 6 depending upon the xml file.thus i want to make a widget which for each feature creates an instance.
I have made basic structure of grouped widget using this:
cal_widget.h
#ifndef CAL_WIDGET_H
#define CAL_WIDGET_H
#include <QWidget>
#include<QVBoxLayout>
#include<QPushButton>
#include<QLineEdit>
class cal_widget : public QWidget
{
Q_OBJECT
public:
explicit cal_widget(QWidget *parent = nullptr);
QVBoxLayout* layout;
QPushButton* btn;
QLineEdit* ln1;
QLineEdit* ln2;
signals:
public slots:
};
#endif // CAL_WIDGET_H
cal_widget.cpp
#include "cal_widget.h"
cal_widget::cal_widget(QWidget *parent) : QWidget(parent)
{
layout = new QVBoxLayout();
btn= new QPushButton();
ln1 = new QLineEdit("mm");
ln2 = new QLineEdit("pix");
layout->addWidget(ln1);
layout->addWidget(btn);
layout->addWidget(ln2);
this->setLayout(layout);
}
and calling the above widget in another form mainwidget.cpp
{
QVBoxLayout* vbox = new QVBoxLayout();
cal_widget* cal1 = new cal_widget(this);
cal_widget* cal2 = new cal_widget(this);
cal_widget* cal3 = new cal_widget(this);
cal_widget* cal4 = new cal_widget(this);
cal_widget* cal5 = new cal_widget(this);
vbox->addWidget(cal1);
vbox->addWidget(cal2);
vbox->addWidget(cal3);
vbox->addWidget(cal4);
vbox->addWidget(cal5);
ui->scrollArea->setLayout(vbox);
}
i am getting result as :this
how can i get desired result
DONE
cal_widget.h
#ifndef CAL_WIDGET_H
#define CAL_WIDGET_H
#include <QWidget>
#include<QGroupBox>
#include<QGridLayout>
#include<QPushButton>
#include<QLineEdit>
class cal_widget : public QGroupBox
{
Q_OBJECT
public:
explicit cal_widget(const QString& feature, QWidget *parent = nullptr);
QGridLayout* layout;
QPushButton* btn;
QLineEdit* ln1;
QLineEdit* ln2;
signals:
public slots:
};
#endif // CAL_WIDGET_H
cal_widget.cpp
#include "cal_widget.h"
cal_widget::cal_widget(const QString& feature, QWidget *parent) : QGroupBox(parent)
{
this->setTitle(feature);
layout = new QGridLayout();
btn= new QPushButton("OK");
ln1 = new QLineEdit("mm");
ln2 = new QLineEdit("pix");
layout->addWidget(ln1,0,0);
layout->addWidget(ln2,0,1);
layout->addWidget(btn,1,0,1,2);
this->setLayout(layout);
}

Convert QStackedLayout to QHBoxLayout dynamically

I would like to change my widget layout from QStackedLayout to QHBoxLayout to QVBoxLayout dynamically by clicking on push buttons. I am able to switch from QVBoxLayout to QHBoxLayout and vice versa, but my approach does not work for QStackedLayout. I've exhausted all options I can think of. A sample code is attached. Does anyone know how I can achieve my objective?
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QStackedLayout>
#include <QGridLayout>
#include <QLabel>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
QPushButton *button1_;
QPushButton *button2_;
QPushButton *button3_;
QHBoxLayout *hLayout_;
QVBoxLayout *vLayout_;
QStackedLayout *sLayout_;
QVBoxLayout *gLayout_;
public slots:
void layoutHorizontal();
void layoutVertical();
void layoutStacked();
private:
bool isStackedLayout_;
QLabel *bar_;
};
#endif // WIDGET_H
#include "widget.h"
#include <QtAlgorithms>
#include <QDebug>
Widget::Widget(QWidget *parent) : QWidget(parent){
bar_ = new QLabel(tr("TEST!"));
button1_ = new QPushButton(tr("to Horizontal Layout"),(bar_));
button2_ = new QPushButton(tr("to Vertical Layout"),(bar_));
button3_ = new QPushButton(tr("to Stacked Layout"),(bar_));
button1_->setStyleSheet("background: rgba(255,255,0,255);");
button2_->setStyleSheet("background: rgba(255,0,255,255);");
button3_->setStyleSheet("background: rgba(0,255,255,255);");
connect(button1_,SIGNAL(clicked()),this,SLOT(layoutHorizontal()));
connect(button2_,SIGNAL(clicked()),this,SLOT(layoutVertical()));
connect(button3_,SIGNAL(clicked()),this,SLOT(layoutStacked()));
gLayout_ = new QVBoxLayout;
setLayout(gLayout_);
hLayout_ = new QHBoxLayout(bar_);
hLayout_->setObjectName(tr("currentLayout"));
gLayout_->addWidget(bar_);
hLayout_->addWidget(button1_);
hLayout_->addWidget(button2_);
hLayout_->addWidget(button3_);
isStackedLayout_ = false;
resize(480,200);
}
Widget::~Widget() { }
void Widget::layoutHorizontal(){
QLayout *layout = bar_->findChild<QLayout *>(tr("currentLayout"));
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
delete layout;
QHBoxLayout *hLayout_ = new QHBoxLayout(bar_);
hLayout_->setObjectName(tr("currentLayout"));
hLayout_->addWidget(button1_);
hLayout_->addWidget(button2_);
hLayout_->addWidget(button3_);
isStackedLayout_ = false;
}
void Widget::layoutVertical(){
QLayout *layout = bar_->findChild<QLayout *>(tr("currentLayout"));
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
delete layout;
QVBoxLayout *vLayout_ = new QVBoxLayout(bar_);
vLayout_->setObjectName(tr("currentLayout"));
vLayout_->addWidget(button1_);
vLayout_->addWidget(button2_);
vLayout_->addWidget(button3_);
isStackedLayout_ = false;
}
void Widget::layoutStacked(){
QLayout *layout = bar_->findChild<QLayout *>(tr("currentLayout"));
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
delete layout;
QStackedLayout *sLayout_ = new QStackedLayout(bar_);
sLayout_->setObjectName(tr("currentLayout"));
sLayout_->addWidget(button1_);
sLayout_->addWidget(button2_);
sLayout_->addWidget(button3_);
isStackedLayout_ = true;
}
The visibility property on your buttons gets set to "invisible" after pulling widgets out of the QStackedLayout (likely because the QStackedLayout relies on this property to emulate stacking). As such, I was able to get your code to work by adding the following:
void Widget::layoutHorizontal() {
...
button1_->setVisible(true);
button2_->setVisible(true);
button3_->setVisible(true);
isStackedLayout_ = false;
}
It's also worth noting that removing the widgets from the layout prior to deleting it is not necessary. The layout doesn't take ownership of the widgets in it. As such you can delete the following:
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
Create another widget with only widgets and one layout inside. Then use setLayout for your widget. Sorry for my bad C++ knowledge :)
class ChangeableWidget: public QWidget {
private QVBoxLayout vbox;
private QHBoxLayout hbox;
private QStackedLayout stacked;
private QPushButton button1;
private QPushButton button2;
ChangeableWidget()
{
button1 = new QPushButton("1");
button2 = new QPushButton("2");
vbox = new QVBoxLayout();
vbox.addWidget(button1);
vbox.addWidget(button2);
hbox = new QHBoxLayout();
hbox.addWidget(button1);
hbox.addWidget(button2);
stacked = new QStackedLayout();
stacked.addWidget(button1);
stacked.addWidget(button2);
setLayout(vbox);
}
void ChangeableWidget::layoutVertical()
{
setLayout(vbox);
}
void ChangeableWidget::layoutHorizontal()
{
setLayout(hbox);
}
}

How to add buttons to a main window in Qt?

I'm new to qt programming so please don't mind if you find it a noob question. I've added a button to my main window but when I run the code the button is not displayed. Here's my code:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtWidgets>
MainWindow::MainWindow(QWidget *parent)
{
QPushButton *train_button = new QPushButton(this);
train_button->setText(tr("something"));
train_button->move(600, 600);
train_button->show();
}
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;
};
#endif // MAINWINDOW_H
MainWindow::~MainWindow()
{
delete ui;
}
What should I do?
In main window you should use central widget . You have two choices :
Set the button for central widget ( Not so good choice ) :
QPushButton *train_button = new QPushButton(this);
train_button->setText(tr("something"));
setCentralWidget(train_button);
Add a widget and add the button to that widget and set the widget for centralWidget :
QWidget * wdg = new QWidget(this);
QPushButton *train_button = new QPushButton(wdg);
train_button->setText(tr("something"));
setCentralWidget(wdg);
And surely you can use Layouts for your centralWidget:
QWidget * wdg = new QWidget(this);
QVBoxLayout *vlay = new QVBoxLayout(wdg);
QPushButton *btn1 = new QPushButton("btn1");
vlay->addWidget(btn1);
QPushButton *btn2 = new QPushButton("btn2");
vlay->addWidget(btn2);
QPushButton *btn3 = new QPushButton("btn3");
vlay->addWidget(btn3);
wdg->setLayout(vlay);
setCentralWidget(wdg);

Adding drop down menu to Qt GUI - error 'menubar' no declared

I'm trying to create a menu in Qt following this example http://doc.qt.nokia.com/latest/mainwindows-menus.html
but I keep getting the error 'menuBar' not declared in this scope
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
In context:
#include <QtGui>
#include "borderlayout.h"
#include "window.h"
Window::Window()
{
QTextBrowser *centralWidget = new QTextBrowser;
//***Change this to whatever widget(s) the drawing area is. QPainter or something?
centralWidget->setPlainText(tr("DRAW HERE YAY"));
BorderLayout *layout = new BorderLayout;
layout->addWidget(centralWidget, BorderLayout::Center);
layout->addWidget(createLabel("File ..."), BorderLayout::North);
layout->addWidget(createLabel("Toolbar yo!"), BorderLayout::West);
//layout->addWidget(createLabel("Status bar"), BorderLayout::South);
//Maybe we could put in a status bar. For now let's not worry about it. It's not a requirement.
setLayout(layout);
createMenus();
setWindowTitle(tr("Border Layout"));
}
QLabel *Window::createLabel(const QString &text)
{
QLabel *label = new QLabel(text);
label->setFrameStyle(QFrame::Box | QFrame::Raised);
return label;
}
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
window.h
#ifndef WINDOW_H
#define WINDOW_H
#include <QWidget>
class QLabel;
class QMenu;
class Window : public QWidget
{
Q_OBJECT
public:
Window();
private:
void createMenus();
QLabel *createLabel(const QString &text);
QMenu *saveMenu();
};
#endif
window.cpp
#include <QtGui>
#include "borderlayout.h"
#include "window.h"
Window::Window()
{
QTextBrowser *centralWidget = new QTextBrowser;
//***Change this to whatever widget(s) the drawing area is. QPainter or something?
centralWidget->setPlainText(tr("DRAW HERE YAY"));
BorderLayout *layout = new BorderLayout;
layout->addWidget(centralWidget, BorderLayout::Center);
layout->addWidget(createLabel("File ..."), BorderLayout::North);
layout->addWidget(createLabel("Toolbar yo!"), BorderLayout::West);
//layout->addWidget(createLabel("Status bar"), BorderLayout::South);
//Maybe we could put in a status bar. For now let's not worry about it. It's not a requirement.
setLayout(layout);
createMenus();
setWindowTitle(tr("Border Layout"));
}
QLabel *Window::createLabel(const QString &text)
{
QLabel *label = new QLabel(text);
label->setFrameStyle(QFrame::Box | QFrame::Raised);
return label;
}
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
The menu bar is a feature of the QMainWindow class.
Because your Window class is being inherited directly from QWidget, it does not have the menuBar method, hence your error.
You need to subclass your Window class from QMainWindow rather than QWidget.

Resources