Create Widget in QMainWindow and load to ScrollArea - c++

I tried to create a Mainwindow with an slot, which creates a Widget and loads it to the ScrollArea in the Mainwindow. This doesn't work, so I tired to create the Widget in the constructor of the mainwindow and I always get errors and don't know why.. so what's the right declaration of the Widget?
#include <QtGui>
class Mainwindow : public QMainWindow
{
Q_OBJECT
public:
Mainwindow(QMainWindow *parent = 0);
public slots:
private:
QScrollArea *List,*Sublist,*Overall,*Settings;
QLabel *label_title;
QPushButton *bn_exit,*bn_list,*bn_overall,*bn_settings;
};
//! ------------------------------------- Mainlist -------------------------------------
class Sublist : public QWidget{
Q_OBJECT
private:
QLabel *title;
public:
Sublist(QWidget *parent = 0);
};
and .cpp
Mainwindow::Mainwindow(QMainWindow *parent) : QMainWindow(parent) {
this->resize(1024,576);
//this->setWindowFlags(Qt::Popup);
QPalette palette;
palette.setColor(QPalette::Background, QColor(16,16,16));
this->setPalette(palette);
Sublist SecondList;
//! [Set ScrollAreas]
List = new QScrollArea(this);
List->setGeometry(0,60,200,456);
List->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
Sublist = new QScrollArea(this);
Sublist->setGeometry(200,60,824,456);
Sublist->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
//Sublist->setWidget(SecondList)
}
//! ---------------------------------------- MainList------------------------------------------------------
Sublist::Sublist(QWidget *parent){
resize(1200,1200);
title = new QLabel("Title",this);
title->setGeometry(1120,1120,40,90);
}

I have played around with your code a bit, noticed a few things:
In class Mainwindow you define your QScrollArea variables:
QScrollArea *List,*Sublist,*Overall,*Settings;
You define a variable named Sublist of type QScrollArea, but you also have a class of the same name:
class Sublist : public QWidget
Probably would be a good idea to change the variable names for your scroll areas:
QScrollArea *list, *subList, *overall, *settings;
Next, in the constructor for class Sublist you pass a pointer to the parent class but never assign it to your base class. You also have a QLabel widget that never is placed anywhere. What seems to be needed is a layout for your custom widget.
The Sublist class could be something like this:
//.h
class Sublist : public QWidget
{
Q_OBJECT
public:
Sublist(QWidget *parent = 0);
private:
QLabel *title;
QVBoxLayout *layout;
};
//.cpp
Sublist::Sublist(QWidget *parent) : QWidget(parent) {
resize(1200,1200);
title = new QLabel("Title");
title->setGeometry(1120,1120,40,90);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(title);
setLayout(layout);
}
The Mainwindow class something like this:
//.h
class Mainwindow : public QMainWindow
{
Q_OBJECT
public:
Mainwindow(QMainWindow *parent = 0);
private:
Sublist *secondList;
QScrollArea *list, *subList, *overall, *settings;
QLabel *label_title;
QPushButton *bn_exit,*bn_list,*bn_overall,*bn_settings;
};
//.cpp
Mainwindow::Mainwindow(QMainWindow *parent) : QMainWindow(parent)
{
this->resize(1024,576);
QPalette palette;
palette.setColor(QPalette::Background, QColor(16,16,16));
palette.setColor(QPalette::Foreground, QColor(255,255,255));//set text to white
this->setPalette(palette);
secondList = new Sublist(this);
//! [Set ScrollAreas]
list = new QScrollArea(this);
list->setGeometry(0,60,200,456);
list->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
subList = new QScrollArea(this);
subList->setGeometry(200,60,824,456);
subList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
subList->setWidget(secondList);
}
Im still not 100% sure this is what you where trying to achieve with this code, but I hope that I have helped you to resolve some of the issues in your current implementation.

Related

C++ Qt inherit from custom widget

I'm working on a project with Qt and C++.
Now my Question is:
Is inheritance possible in UI classes?
For example: This is the Widget I want to inherit from
//windowA.h
namespace Ui {
class WindowA;
}
class WindowA : public QWidget
{
Q_OBJECT
public:
explicit WindowA(QWidget *parent = nullptr);
~AddWindow();
QPushButton *button;
};
//windowA.cpp
WindowA::WindowA(QWidget *parent) :
QWidget(parent)
{
button = new QPushButton();
button->setText("Save");
connect(button, SIGNAL (clicked()), this, SLOT (//slot));
QGridLayout *layout = new QGridLayout();
layout->addWidget(button, 0, 0);
this->setLayout(layout);
}
This is the widget that inherits from WindowA
//windowB.h
namespace Ui {
class WindowB;
}
class WindowB : public WindowA
{
Q_OBJECT
public:
explicit WindowB(QWidget *parent = nullptr);
~WindowB();
};
How would I implement a QPushButton, so that it's possible to set different text in both classes?
I can add a QPushButton but the text set in WindowA would also be set in WindowB. The problem is to set a different text for the button in WindowB than it is set for the button in WindowA
If I understand your question correctly, all you need to do is change what text you set on the button in your constructor:
WindowB::WindowB(QWidget *parent) :
WindowA(parent)
{
button->setText("Something else!");
}

Parent issue (?) while using derived Qt widget class

The following is the smallest example I could make to present the isuue.
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *vLayout = new QVBoxLayout(this);
QGroupBox *gb = new QGroupBox;
// MyGroupBox *gb = new MyGroupBox;
vLayout->addWidget(gb);
QPushButton *btB = new QPushButton;
vLayout->addWidget(btB);
}
The code above produces the image above, it's just a group box and a button in vertical layout.
If I replace QGropBox by MyGroupBox then it doesn't show there anymore. The code below produces the image below.
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *vLayout = new QVBoxLayout(this);
// QGroupBox *gb = new QGroupBox;
MyGroupBox *gb = new MyGroupBox;
vLayout->addWidget(gb);
QPushButton *btB = new QPushButton;
vLayout->addWidget(btB);
}
Where mygroupbox.h (the constructor body is empty in the .cpp file):
#include <QWidget>
class MyGroupBox : public QWidget
{
Q_OBJECT
public:
explicit MyGroupBox(QWidget *parent = 0);
signals:
public slots:
};
Why the group box isn't showing there? How to make it appear?
This is why it doesn't appear:
class MyGroupBox : public QWidget
Your "group box" is basically just a QWidget. Inherit from QGroupBox instead.
As an aside, a minimal example could look like the below. Not a single declaration/statement/expression can be removed. The button aids in visualizing the problem, so it should be left in. The use of a failure trigger variable highlights exactly what condition triggers the failure: the code self-documents and you almost need no narrative to explain it. The question could be as concise as the test case below and one sentence "Why is the group box's border not visible when fail is true?". Most likely, had you followed the minimization fully through, you'd realize yourself what the problem was - it becomes rather obvious. It's not so when MyGroupBox is declared in another file!
The technique of putting it all into a single main.cpp file is critical in spotting the problem: all of the code is physically next to each other, making it much easier to spot mistakes! When you minimize, usually the first things that have to go are separate files: cram it all into one file, and then relentlessly remove absolutely everything that's not directly needed in reproducing the issue.
#include <QtWidgets>
struct MyGroupBox : public QWidget {};
int main(int argc, char ** argv) {
bool fail = true;
QApplication app{argc, argv};
QWidget widget;
QVBoxLayout layout{&widget};
QGroupBox groupBox;
MyGroupBox myGroupBox;
QPushButton button;
layout.addWidget(fail ? static_cast<QWidget*>(&myGroupBox) : &groupBox);
layout.addWidget(&button);
widget.show();
return app.exec();
}
This concise style is not only for trivial test cases. In your real code, the Widget's header and implementation could look as follows:
// Widget.h
#include <QtWidgets>
#include "MyGroupBox.h"
class Widget : public QWidget {
Q_OBJECT
QVBoxLayout layout{this};
MyGroupBox groupBox;
QPushButton button{tr("Click Me!")};
public:
explicit Widget(QWidget * parent = nullptr);
};
// Widget.cpp
#include "Widget.h"
Widget::Widget(QWidget * parent) :
QWidget{parent} {
layout.addWidget(&groupBox);
layout.addWidget(&button);
}
If you insist on shielding the interface from implementation details, don't use pointers to widgets etc., use a PIMPL.
// Widget.h
#include <QWidget>
class WidgetPrivate;
class Widget : public QWidget {
Q_OBJECT
Q_DECLARE_PRIVATE(Widget)
QScopedPointer<WidgetPrivate> const d_ptr;
public:
explicit Widget(QWidget * parent = nullptr);
};
// Widget.cpp
#include "Widget.h" // should always come first!
#include "MyGroupBox.h"
class WidgetPrivate {
Q_DECLARE_PUBLIC(Widget)
Widget * const q_ptr;
public:
QVBoxLayout layout{q_func()};
QGroupBox groupBox;
MyGroupBox myGroupBox;
QPushButton button{"Click Me!"};
WidgetPrivate(Widget * q) : q_ptr(q) {
layout.addWidget(&groupBox);
layout.addWidget(&button);
}
};
Widget::Widget(QWidget * parent) :
QWidget{parent}, d_ptr{new WidgetPrivate{this}}
{}

Creating a class that implements tabs and can be used as a "central widget" in QMainWindow

I want the central widget of my mainWindow class to be a QTabWidget. My plan is to create widgets that I want to put in the tabs as separate classes and add them to QTabWidget class and add the QtabWidget class itself as a central Widget to the mainWindow class.
To do this, how must I declare my tabWidget class ?
Should it be :
class centralTab : public QMainWindow
{
}
or
class centralTab : public QDialog
{
}
Also, in the ctor, What should be used as the parent ?
Just create QMainWindow subclass:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
//...
};
In constructor use addTab() method::
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
QTabWidget *tabWidget = new QTabWidget(this);
//some settings
tabWidget->addTab(new QLabel("example1"), "General1");
tabWidget->addTab(new QLabel("example2"), "General2");
setCentralWidget(tabWidget);
}
Why QMainWindow? Because only QMainWindow has setCentralWidget() method;
You can add different widgets and set also icon to every tab, QLabel is just example.

Qt - Compiler complains when invoking setLayout() on my MainWindow

I wanna learn how to create a gui by hand without the designer. I tried to add a layout to my MainWindow but when running it says
QWidget::setLayout: Attempting to set QLayout "" on MainWindow "", which already has a layout
This is my code :
//Header
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QHBoxLayout *layout;
};
//Constructor in my *.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
layout = new QHBoxLayout;
this->setLayout(layout);
}
//The usual main function
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
What is wrong? I did what my book said. I even looked up some code on the internet which was really hard to find somehow and it was still the same. I just cannot add a layout to my window.
There's a similar question which helped me find out what's wrong. Thanks to Mat for his link to that question.
What every QMainWindow needs is a QWidget as central widget. I also created a new Project with the designer, compiled it and looked the ui_*.h files up.
So every QMainWindow should look similar to this :
//Header
class MainWindow : public QMainWindow
{
Q_OBJECT
QWidget *centralWidget;
QGridLayout* gridLayout;
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
};
//*.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
centralWidget = new QWidget(this);
this->setCentralWidget( centralWidget );
gridLayout = new QGridLayout( centralWidget );
}
Now you don't add / set the layout to the MainWindow. You add / set it to the centralWidget.

QComboBox doesn't connect

I'm programming in QT 4.8.4 with C++. I want to have a drop-down menu, where I can select an option, and then it will run an exe with the selected item on the menu as the option for the exe.
Here's my code:
#ifndef GUI_H
#define GUI_H
#include <QDialog>
#include <QtGui>
class QLabel;
class QLineEdit;
class QPushButton;
class gui : public QDialog
{
Q_OBJECT
public:
gui(QWidget *parent = 0);
public slots:
void gui::on_go_clicked();
private:
QLabel *label1;
QLabel *label2;
QLineEdit *lineEdit;
QPushButton *goButton;
QComboBox cb;
};
#endif
And the .cpp file:
#include <QtGui>
#include <QApplication>
#include <QComboBox>
#include "gui.h"
#include <vector>
gui::gui(QWidget *parent) : QDialog(parent)
{
label1 = new QLabel(tr("Insert Name (Optional):"));
label2 = new QLabel(tr("Class Name (Required):"));
lineEdit = new QLineEdit;
goButton = new QPushButton(tr("&Go"));
goButton->setDefault(true);
connect(goButton, SIGNAL(clicked()), this, SLOT(on_go_clicked()));
QComboBox *cb = new QComboBox();
cb->addItem("Hello", "1");
cb->addItem("Test", "2");
QHBoxLayout *hLayout1 = new QHBoxLayout;
hLayout1->addWidget(label1);
hLayout1->addWidget(lineEdit);
QHBoxLayout *hLayout2 = new QHBoxLayout;
hLayout2->addWidget(label2);
hLayout2->addWidget(cb);
QHBoxLayout *hLayout3 = new QHBoxLayout;
hLayout3->addWidget(goButton);
hLayout3->addStretch();
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addLayout(hLayout1);
vLayout->addLayout(hLayout2);
vLayout->addWidget(cb);
vLayout->addLayout(hLayout3);
setLayout(vLayout);
setWindowTitle(tr("TEST"));
setFixedHeight(sizeHint().height());
}
void gui::on_go_clicked()
{
QMessageBox::information(this, "ASDF", cb.currentText());
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
gui *stuff = new gui;
stuff->show();
return app.exec();
}
Right now I'm just trying to figure out how to use QComboBox, which isn't working. My code compiles, but when I run it I get "Object::connect: No such slot gui::on_go_clicked()"
I'm doing exactly what a tutorial says to do. I can't figure out why this isn't working.
Remove gui:: :
class gui : public QDialog{
Q_OBJECT
...
public slots:
void gui::on_go_clicked();
^^^^^
Remove it
I wonder why you code even compiles. No 'extra qualification on member on_go_clicked'.
Remove gui:: from on_go_clicked in your header.
You have two QComboBox objects that you reference.
The first is at the class level:
class gui : public QDialog{
Q_OBJECT
public:
gui(QWidget *parent = 0);
public slots:
void gui::on_go_clicked();
private:
QLabel *label1;
QLabel *label2;
QLineEdit *lineEdit;
QPushButton *goButton;
QComboBox cb; // <<<=== class-level automatic object
};
The second is a local pointer-to-QComboBox object that exists in the constructor
gui::gui(QWidget *parent) : QDialog(parent){
...
QComboBox *cb = new QComboBox(); // <<<=== function-level pointer using the same name
// as the class-level automatic object
To correct the problem, you can change the class-level object to be a pointer and then change the object creation to be a simple assignment instead of a declaration-and-initialisation.
cb = new QComboBox();
Also, once you've done this, you'll need to modify the slot so that the pointer dereference operator is used to access the text() function
void gui::on_go_clicked(){
QMessageBox::information(this, "ASDF", cb->currentText());
}