Qt Closing Previous Window - c++

So this is the code of the main.cpp:
#include <QApplication>
#include <QtGui>
#include <mainwidget.h>
int main(int argc, char **argv)
{
QPushButton button ("Hello world!");
button.show();
mainWidget widget;
widget.show();
return app.exec();
}
I want a button from the "widget" to close the "Hello world!" window. I have already added that button in "widget" and made a function for it in mainwidget.h (which also shows a message box) and connected them. I just want to know how can that same button close the Hello World window. I guess I have to add something to the function in mainwidget.h but I don't know what it is. The instructor says we should use the QWidget close() function.

I will answer to your question but before I'll explain you how a basic Qt application looks like.
In Qt, a basic main is like :
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Here as you can see a QApplication is created then a MainWindow.
So What's the MainWindow class ?
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
};
#endif // MAINWINDOW_H
It's the MainWindow.h. As you can see MainWindow inherit to the QMainWindow class. It's the main window class to create a graphic user interface.
the Q_OBJECT define is for qmake. Indeed qmake I'll create a moc_mainwindow.cpp for this class to manage the Qt signals.
Now you get an empty window if you create an Empty constructor and destructor like:
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
}
MainWindow::~MainWindow()
{
}
then after you wish to write "Hello world !" in the window so in Qt to write a text you can use a QLabel. So to write "Hello World !" you get:
#include "mainwindow.h"
#include <QLabel>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
QWidget *widget = new QLabel("Hello world !", this);
}
MainWindow::~MainWindow()
{
}
then after to create a button as you made you ll use the QPushButton class.
so you get:
#include "mainwindow.h"
#include <QLabel>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
QWidget *widget = new QLabel("Hello world !", this);
setCentralWidget(widget);
QPushButton *button = new QPushButton("close", this);
}
MainWindow::~MainWindow()
{
}
(I Choose to set the QLabel to the central Widget to don't get the label behind the button but after and in real Qt application a QMainWindow's central widget is mostly usualy a QWidget I'll explain you why after)
now you have a button. But when you click on it nothing append.
Why ? Because nothing link the Button and the Window. to link it in Qt we use the connect function. [http://qt-project.org/doc/qt-4.8/qobject.html][1]
so with connect to close the window when you click on the button you get:
#include "mainwindow.h"
#include <QLabel>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
QWidget *widget = new QLabel("Hello world !", this);
setCentralWidget(widget);
QPushButton *button = new QPushButton("close", this);
connect(button, SIGNAL(clicked()), this, SLOT(close()));
}
MainWindow::~MainWindow()
{
}
As you can see with connect. In first parameter, we put the object which ll send the signal here the button. in second parameter, we put the signal to link here it's clicked() to do this we write SIGNAL(clicked()). In third, the object which will receive the signal, here the window to close. In fourth parameter the function to launch when the signal is received. We write this SLOT(close()).
Why SIGNAL and SLOT ? because in Qt to create a signal we use signal: in the .hh and to create a slot et use (public or protected or private) slots:
example:
Class Object
{
Q_OBJECT
...
signals:
void aSignal();
public slots:
void aSlot();
...
};
NOTE: the signal and the slot must have same return and parameters.
after to organize your objects you ll use the labels in the QWidget in the centralWidget so you have:
#include "mainwindow.h"
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
QWidget* centralWid = new QWidget(this);
setCentralWidget(centralWid);
QVBoxLayout *layout = new QVBoxLayout(centralWid);
QWidget *widget = new QLabel("Hello world !", this);
QPushButton *button = new QPushButton("close", this);
layout->addWidget(widget);
layout->addWidget(button);
centralWid->setLayout(layout);
connect(button, SIGNAL(clicked()), this, SLOT(close()));
}
MainWindow::~MainWindow()
{
}

Related

Widget initialized later will not show in MainWindow

I am learning Qt using Qt 5.13 on MacOS.
First I define MyWidget inherited from QWidget. MyWidget has a QPushButton, but this button will be created in a slot function called 'fresh', not in constructor.
I add MyWidget in MainWindow (inherited from QMainWindow), and defined another button_2 to emit signal to callMyWidget's 'fresh' function to create button.
If I did not hide MyWidget in MainWindow first, MyWidget's button will not show. If I hide MyWidget first, everything seems OK.
I hope to know the reason. Thanks
I tried to repaint or update MyWidget in 'fresh' function, but did not help.
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include<QPushButton>
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = nullptr);
~MyWidget();
public slots:
void fresh();
private:
QPushButton* myButton;
};
#endif // WIDGET_H
mywidget.cpp
#include "mywidget.h"
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent)
{
}
MyWidget::~MyWidget()
{
}
void MyWidget::fresh()
{
myButton = new QPushButton(this);
myButton->setStyleSheet("QPushButton { background-color: green;}");
show();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include"mywidget.h"
#include<QHBoxLayout>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
signals:
public slots:
private:
MyWidget* myWidget;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
QWidget* qwidget = new QWidget;
myWidget = new MyWidget(this);
QPushButton* button = new QPushButton("Show",this);
QHBoxLayout* mainLayout = new QHBoxLayout;
mainLayout->addWidget(myWidget);
mainLayout->addWidget(button);
qwidget->setLayout(mainLayout);
setCentralWidget(qwidget);
//myWidget->hide();
connect(button,&QPushButton::clicked,myWidget,&MyWidget::fresh);
}
main.cpp
#include "mywidget.h"
#include"mainwindow.h"
#include<QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
If I add myWidget->hide(); in mainwindow.cpp, it seems right.
If I remove it, the green button will not show, even if I repaint or update or show in fresh function.
'mywidget' is taking the whole space, if you want to know if it is taking all the space or not :
mywidget->setStyleSheet("* {border: 4px solid orange;}")
Since you are using a layout, you might want to determine the minimum size of a QPushButton. the QPushButton has a default horizontal size policy : "Minimum", by default. Maybe if you set the minimum width using this function : "setMinimumWidth(int width)", might fix your problem.
Also, don't forget to call this :
myButton->show();
Every object that inherits from QObject should be shown with this func ".show".
Here is all the flags for QSizePolicy will help you understand what is going on in layouts (layouts work a lot with QSizePlicy flags) : https://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum .
Unless you don't want the layout, you have to specify the position and the size in this way :
mywidget->setGeometry(QPoint(x, y), QSize(width, height));
and the same thing for your buttons.

hiding the main Window after opening the secondWindow?Also, when the secondWindow is closed by the user, how can the main window reappear?

Basically, when second window is opened from a push button in the main window, the main window will be closed. When the second window is closed, the main window will reappear.
QWidget *wdg = new QWidget;
wdg->show();
hide();
I put this under the class of mainwindow.cpp
I tried using this..but it doesn't seem to do anything?
this are the code I have so far. Everything is working but I just don't know how to hide the window when the second window is opened and also when the second window is closed the main window will reappear.
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 = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
public:
void show();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
secwindow.h
#ifndef SECWINDOW_H
#define SECWINDOW_H
#include <QDialog>
namespace Ui {
class SecWindow;
}
class SecWindow : public QDialog
{
Q_OBJECT
public:
explicit SecWindow(QWidget *parent = nullptr);
~SecWindow();
private:
Ui::SecWindow *ui;
};
#endif // SECWINDOW_H
source code
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QPixmap>
#include "secwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPixmap pix("C:/Users/Charlene/Downloads/Charlene Back-up/MAPUA/2nd Term/Object Oriented Programming/GOW-Gui/GOW-GUI/intro pic/intro.png");
ui->label->setPixmap(pix.scaled(230,250,Qt::KeepAspectRatio));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked() // Modal approach..mainwindow cannot be moved when secwindow is displayed.
{
SecWindow secwindow;
secwindow.setModal(true); //it'll set the secwindow
secwindow.exec(); //shows secwindow when button is pressed
}
secwindow.cpp
#include "secwindow.h"
#include "ui_secwindow.h"
SecWindow::SecWindow(QWidget *parent) :
QDialog(parent),
ui(new Ui::SecWindow)
{
ui->setupUi(this);
}
SecWindow::~SecWindow()
{
delete ui;
}
EDIT:
#Serhiy Kulish
What I added so far:
secWindow.h
class Dialog : public QDialog
{
Dialog();
};
mainwindow.cpp
#include <QDialog>
void MainWindow::show()
{
Dialog *dialog = new Dialog(this); //Error:no matching constructor for initialization of 'Diaolog'
connect(dialog, SIGNAL(accepted()), this, SLOT(show()));
connect(dialog, SIGNAL(rejected()), this, SLOT(show()));
dialog->show();
hide();
}
These are the errors I'm having so far.
Add your own class derived from QDialog. Then connect signals accepted and rejected with MainWindow::show().
Dialog *dialog = new Dialog(this);
connect(dialog, SIGNAL(accepted()), this, SLOT(show()));
connect(dialog, SIGNAL(rejected()), this, SLOT(show()));
dialog->show();
hide();
It works fine on Windows 10.
Also, depends your OS you maybe need
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
in main.cpp to prevent app closing. But in this case you have to quit from your app manually

QT message box not popus on button click

I just started learning QT and what i wanted to accomplish is to get popup message on buttons click.
Here is how my file looks like:
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QDialog>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QWidget>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow *mainWindow = new MainWindow();
QLabel *text = new QLabel("Some text");
QPushButton *btn = new QPushButton("Click");
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(btn);
layout->addWidget(text);
QObject::connect(btn, SIGNAL(clicked()), &app, SLOT(popup()));
mainWindow->setLayout(layout);
mainWindow->show();
return app.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::popUp()
{
QMessageBox::information(this, "New Box", "Message");
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMessageBox>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void popUp();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Can you please explain what i've done wrong or maybe there is something missing in my code.
I recommend that the graphical part implement it inside the class MainWindow since the member ui that is private handles the design.
#include <QMessageBox>
#include <QLabel>
#include <QLayout>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QLabel *text = new QLabel("Some text");
QPushButton *btn = new QPushButton("Click");
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(btn);
layout->addWidget(text);
ui->centralWidget->setLayout(layout);
connect(btn, &QPushButton::clicked, this, &MainWindow::popUp);
}
Do not make any changes to main.cpp, the code should look like this:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Wrong connection. You should connect the clicked() signal to the mainWindow's slot popUp(), because it is a member of the MainWindow class. And don't forget about case sensitivity of c++ (popUp, not popup):
QObject::connect(btn, SIGNAL(clicked()), mainWindow, SLOT(popUp()));
You're connecting to a private slot from outside mainwindow.
The application output probably shows you a warning like this:
QObject::connect: No such slot QApplication::popup()
Usually what you'd want to do is put stuff used inside mainwindow, inside mainwindow class.
Eg: Create the layout inside the constructor.
You can use the parent argument when creating the objects to get them destroyed when you're done with mainwindow.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QLabel *text = new QLabel("Some text", this);
QPushButton *btn = new QPushButton("Click", this);
QHBoxLayout *layout = new QHBoxLayout;
QObject::connect(btn, SIGNAL(clicked()), this, SLOT(popUp()));
ui->centralWidget->setLayout(layout);
this->show();
}
You have to use ui->centralWidget, because that's how mainwindow works. The application output should have given you a warning for that as well.
Like this:
QWidget::setLayout: Attempting to set QLayout "" on MainWindow "MainWindow", which already has a layout
Ok, you have to work on the file mainwindow.cpp. You have already create the slot, so connect it adding this code in MainWindow's constructor (if you don't know witch is the mw constructor it is the function where is written ui->setupUi(this);)
connect(ui->btn, SIGNAL(clicked()), SLOT(popUp()));
now in the slot MainWindow::popUp(); put this code:
QMessageBox msgBox;
msgBox.setText("text to write");
msgBox.exec();
remember to include QMessageBox in mainwindow.cpp, you shouldn't write code on main.cpp, it must be this:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

SIGNAL is not emitted

I have issue with SIGNAL not being emitted. Here is minimal example of this issue:
main.cpp - standard main
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QVBoxLayout>
#include "combobox.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
QWidget *mainWidget = new QWidget;
setCentralWidget(mainWidget);
QVBoxLayout *mainLayout = new QVBoxLayout;
combobox combo_box;
mainLayout->addWidget(combo_box.box);
mainWidget->setLayout(mainLayout);
}
MainWindow::~MainWindow()
{
}
combobox.h
#ifndef COMBOBOX_H
#define COMBOBOX_H
#include <QComboBox>
#include <QDebug>
class combobox : public QWidget
{
Q_OBJECT
public:
combobox();
~combobox();
QComboBox *box = new QComboBox;
public slots:
void selection_changed();
};
#endif // COMBOBOX_H
combobox.cpp
#include "combobox.h"
combobox::combobox()
{
QString string = "test 1";
box->addItem(string);
string = "test 2";
box->addItem(string);
box->setCurrentIndex(0);
connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(selection_changed()));
}
combobox::~combobox()
{
}
void combobox::selection_changed()
{
qDebug() << "Selection changed";
box->setCurrentIndex(-1);
}
You need to run qmake before compiling.
When I run this program and change combobox index selection_changed is not executed. Why?
SIGNAL and SLOT connection definitely works, because if I add box->setCurrentIndex(1); at the end of combobox constructor, selection_changed will be executed once.
I am using QT 5.4 with QT Creator
Thanks in advance!
This problem because of you create your ComboBox class object at stack. So if you write some debug information at destructor of this class you can see object destroyed immediately after MainWindow constructor out of scope:
ComboBox::~ComboBox()
{
qDebug() << Q_FUNC_INFO;
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setupUi(this);
QWidget *mainWidget = new QWidget;
setCentralWidget(mainWidget);
QVBoxLayout *mainLayout = new QVBoxLayout;
ComboBox combo_box;
mainLayout->addWidget(combo_box.box);
mainWidget->setLayout(mainLayout);
qDebug() << Q_FUNC_INFO;
}
And qDebug() got the following result:
MainWindow::MainWindow(QWidget*)
virtual ComboBox::~ComboBox()
Thats why signal don't emitted. So you need create object on the heap or make something tricks.
Also, you have dynamically allocated object *box at your ComboBox class and don't specify parent of this object, so it seems memory leak is possible. Specify parent or delete object at destructor of ComboBox class.

C++ - Adding item to QListWidget from QPushButton

Hello I am trying to add items to a QListWidget from a QPushButton. Both the QListWidget and QPushButton are added as individual widgets inside of a QGraphicsScene. I want the effect of a box that fills with text lines
main.c
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
QGraphicsView view;
QGraphicsScene *scene = new QGraphicsScene(0, 0, 1200, 1200, &view);
scene->setBackgroundBrush(Qt::gray);
view.setScene(scene);
QPushButton *PushButton1;
PushButton1 = new QPushButton();
PushButton1->setGeometry(QRect(19, 20, 154, 4));
QListWidget *ListWidget;
ListWidget = new QListWidget;
scene->addWidget(ListWidget);
scene->addWidget(PushButton1);
QObject::connect(PushButton1, SIGNAL(clicked()),&w, SLOT(handleClick(*QListWidget)));
view.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handleClick(QListWidget *List)
{
int test;
List->addItem("TESTING");
//QApplication::quit();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QListWidget>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
public slots:
void handleClick(QListWidget *List);
};
#endif // MAINWINDOW_H
This code compiles fine. How I get the following error in the console when the application is running
QObject::connect: No such slot MainWindow::handleClick(*ListWidget) in ..\MenuTest\main.cpp:48
Can someone help me do this? I've seen several tutorials but it's using the designer to make the GUI and I'd like to know how to do it in code without using designer. Thanks.
Your slot accepts QListWidget but you're connecting with ListWidget as the parameter, the signature has to be an exact match due to the way signals and slots work in Qt.
Put handleClick under public slots: and change this line:
QObject::connect(PushButton1, SIGNAL(clicked()),&w, SLOT(handleClick(*ListWidget)));
To this:
QObject::connect(PushButton1, SIGNAL(clicked()),&w, SLOT(handleClick(*QListWidget)));
Update:
I see I missed a key point, the signatures have to match, as in parameter to parameter, so the line up there will not work.
To fix this remove the parameter completely, since PushButton1 can't send it automatically.
QObject::connect(PushButton1, SIGNAL(clicked()),&w, SLOT(handleClick()));
Also remove it here:
void MainWindow::handleClick()
To access the QListWidget you'll have to reference it directly, either by passing it to MainWindow's constructor or iterating the window's controls.