I have a Qdialog like the following:
and another one which gets triggered when I click "OK" without selecting the image and classifier files both, like here
I have linked the Browse... buttons to QFileDialog. Now, when I click on Browse for the Image button, it opens a file dialog, then when I select the file and press OK, it reopens it. Same thing happens with the other browse button and the dialog containing the label.
Any idea, why is it happening 2 times when the event has only occurred once?
Here are the slots:
void MySecondQtProject::on_pushImage_clicked()
{
image =
QFileDialog::getOpenFileName(this, tr("open file"), "C:/Users/mankum93/Documents/Visual Studio 2013/Projects/BananaClassifierOpenCV/BananaClassifierOpenCV",
"Images (*.png *.xpm *.jpg)");
}
void MySecondQtProject::on_pushClassifier_clicked()
{
classifier =
QFileDialog::getOpenFileName(this, tr("open file"), "C:/Users/mankum93/Documents/Visual Studio 2013/Projects/BananaClassifierOpenCV/BananaClassifierOpenCV",
"XML files (*.xml)");
}
void MySecondQtProject::on_pushOK_clicked()
{
accept();
//Now lets compare for invalidity of any string:
if (image.isNull() || classifier.isNull())
{
ShowErrorDialog dialog(this);
dialog.exec();
}
else
{
//Convert Qstring to std::string
String imageFileName = image.toLocal8Bit().constData();
String cascadeFileName = classifier.toLocal8Bit().constData();
// Now, we can go to main detection logic
detectObject(imageFileName, cascadeFileName);
}
}
PS: I am a newbie to QT
EDIT 1: The meta object code
void MySecondQtProject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
MySecondQtProject *_t = static_cast<MySecondQtProject *>(_o);
switch (_id) {
case 0: _t->on_pushImage_clicked(); break;
case 1: _t->on_pushClassifier_clicked(); break;
case 2: _t->on_pushOK_clicked(); break;
default: ;
}
}
Q_UNUSED(_a);
}
EDIT2 : Code for UI files
/********************************************************************************
** Form generated from reading UI file 'mysecondqtprojectHp7256.ui'
**
** Created by: Qt User Interface Compiler version 5.4.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef MYSECONDQTPROJECTHP7256_H
#define MYSECONDQTPROJECTHP7256_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QDialog>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MySecondQtProjectClass
{
public:
QPushButton *pushOK;
QWidget *layoutWidget;
QVBoxLayout *verticalLayout;
QPushButton *pushImage;
QPushButton *pushClassifier;
void setupUi(QDialog *MySecondQtProjectClass)
{
if (MySecondQtProjectClass->objectName().isEmpty())
MySecondQtProjectClass->setObjectName(QStringLiteral("MySecondQtProjectClass"));
MySecondQtProjectClass->resize(600, 272);
pushOK = new QPushButton(MySecondQtProjectClass);
pushOK->setObjectName(QStringLiteral("pushOK"));
pushOK->setGeometry(QRect(290, 220, 91, 31));
layoutWidget = new QWidget(MySecondQtProjectClass);
layoutWidget->setObjectName(QStringLiteral("layoutWidget"));
layoutWidget->setGeometry(QRect(200, 100, 181, 91));
verticalLayout = new QVBoxLayout(layoutWidget);
verticalLayout->setSpacing(6);
verticalLayout->setContentsMargins(11, 11, 11, 11);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
verticalLayout->setContentsMargins(0, 0, 0, 0);
pushImage = new QPushButton(layoutWidget);
pushImage->setObjectName(QStringLiteral("pushImage"));
verticalLayout->addWidget(pushImage);
pushClassifier = new QPushButton(layoutWidget);
pushClassifier->setObjectName(QStringLiteral("pushClassifier"));
verticalLayout->addWidget(pushClassifier);
retranslateUi(MySecondQtProjectClass);
QObject::connect(pushImage, SIGNAL(clicked()), MySecondQtProjectClass, SLOT(on_pushImage_clicked()));
QObject::connect(pushClassifier, SIGNAL(clicked()), MySecondQtProjectClass, SLOT(on_pushClassifier_clicked()));
QObject::connect(pushOK, SIGNAL(clicked()), MySecondQtProjectClass, SLOT(on_pushOK_clicked()));
QMetaObject::connectSlotsByName(MySecondQtProjectClass);
} // setupUi
void retranslateUi(QDialog *MySecondQtProjectClass)
{
MySecondQtProjectClass->setWindowTitle(QApplication::translate("MySecondQtProjectClass", "MySecondQtProject", 0));
pushOK->setText(QApplication::translate("MySecondQtProjectClass", "OK", 0));
pushImage->setText(QApplication::translate("MySecondQtProjectClass", "Browse for the Image", 0));
pushClassifier->setText(QApplication::translate("MySecondQtProjectClass", "Browse for the classifier", 0));
} // retranslateUi
};
namespace Ui {
class MySecondQtProjectClass: public Ui_MySecondQtProjectClass {};
} // namespace Ui
QT_END_NAMESPACE
#endif // MYSECONDQTPROJECTHP7256_H
Now, code for the other errordialog:
/********************************************************************************
** Form generated from reading UI file 'showerrordialogmU7256.ui'
**
** Created by: Qt User Interface Compiler version 5.4.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef SHOWERRORDIALOGMU7256_H
#define SHOWERRORDIALOGMU7256_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QDialog>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
QT_BEGIN_NAMESPACE
class Ui_ShowErrorDialog
{
public:
QLabel *label;
void setupUi(QDialog *ShowErrorDialog)
{
if (ShowErrorDialog->objectName().isEmpty())
ShowErrorDialog->setObjectName(QStringLiteral("ShowErrorDialog"));
ShowErrorDialog->resize(400, 65);
label = new QLabel(ShowErrorDialog);
label->setObjectName(QStringLiteral("label"));
label->setGeometry(QRect(70, 20, 241, 21));
retranslateUi(ShowErrorDialog);
QMetaObject::connectSlotsByName(ShowErrorDialog);
} // setupUi
void retranslateUi(QDialog *ShowErrorDialog)
{
ShowErrorDialog->setWindowTitle(QApplication::translate("ShowErrorDialog", "ShowErrorDialog", 0));
label->setText(QApplication::translate("ShowErrorDialog", "Please properly select the Image or the classifier", 0));
} // retranslateUi
};
namespace Ui {
class ShowErrorDialog: public Ui_ShowErrorDialog {};
} // namespace Ui
QT_END_NAMESPACE
#endif // SHOWERRORDIALOGMU7256_H
Code for main Cpp file
#include "mysecondqtproject.h"
#include "showerrordialog.h"
#include <QFileDialog>
#include "objectdetect.h"
MySecondQtProject::MySecondQtProject(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
}
MySecondQtProject::~MySecondQtProject()
{
}
void MySecondQtProject::on_pushImage_clicked()
{
image =
QFileDialog::getOpenFileName(this, tr("open file"), "C:/Users/mankum93/Documents/Visual Studio 2013/Projects/BananaClassifierOpenCV/BananaClassifierOpenCV",
"Images (*.png *.xpm *.jpg)");
}
void MySecondQtProject::on_pushClassifier_clicked()
{
classifier =
QFileDialog::getOpenFileName(this, tr("open file"), "C:/Users/mankum93/Documents/Visual Studio 2013/Projects/BananaClassifierOpenCV/BananaClassifierOpenCV",
"XML files (*.xml)");
}
void MySecondQtProject::on_pushOK_clicked()
{
accept();
//Now lets compare for invalidity of any string:
if (image.isNull() || classifier.isNull())
{
ShowErrorDialog dialog(this);
dialog.exec();
}
else
{
//Convert Qstring to std::string
String imageFileName = image.toLocal8Bit().constData();
String cascadeFileName = classifier.toLocal8Bit().constData();
// Now, we can go to main detection logic
detectObject(imageFileName, cascadeFileName);
}
}
EDIT 3 : Here are the rest of the useful files you might wanna see
/********************************************************************************
** Form generated from reading UI file 'mysecondqtproject.ui'
**
** Created by: Qt User Interface Compiler version 5.4.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MYSECONDQTPROJECT_H
#define UI_MYSECONDQTPROJECT_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QDialog>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MySecondQtProjectClass
{
public:
QPushButton *pushOK;
QWidget *layoutWidget;
QVBoxLayout *verticalLayout;
QPushButton *pushImage;
QPushButton *pushClassifier;
void setupUi(QDialog *MySecondQtProjectClass)
{
if (MySecondQtProjectClass->objectName().isEmpty())
MySecondQtProjectClass->setObjectName(QStringLiteral("MySecondQtProjectClass"));
MySecondQtProjectClass->resize(600, 272);
pushOK = new QPushButton(MySecondQtProjectClass);
pushOK->setObjectName(QStringLiteral("pushOK"));
pushOK->setGeometry(QRect(290, 220, 91, 31));
layoutWidget = new QWidget(MySecondQtProjectClass);
layoutWidget->setObjectName(QStringLiteral("layoutWidget"));
layoutWidget->setGeometry(QRect(200, 100, 181, 91));
verticalLayout = new QVBoxLayout(layoutWidget);
verticalLayout->setSpacing(6);
verticalLayout->setContentsMargins(11, 11, 11, 11);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
verticalLayout->setContentsMargins(0, 0, 0, 0);
pushImage = new QPushButton(layoutWidget);
pushImage->setObjectName(QStringLiteral("pushImage"));
verticalLayout->addWidget(pushImage);
pushClassifier = new QPushButton(layoutWidget);
pushClassifier->setObjectName(QStringLiteral("pushClassifier"));
verticalLayout->addWidget(pushClassifier);
retranslateUi(MySecondQtProjectClass);
QObject::connect(pushImage, SIGNAL(clicked()), MySecondQtProjectClass, SLOT(on_pushImage_clicked()));
QObject::connect(pushClassifier, SIGNAL(clicked()), MySecondQtProjectClass, SLOT(on_pushClassifier_clicked()));
QObject::connect(pushOK, SIGNAL(clicked()), MySecondQtProjectClass, SLOT(on_pushOK_clicked()));
QMetaObject::connectSlotsByName(MySecondQtProjectClass);
} // setupUi
void retranslateUi(QDialog *MySecondQtProjectClass)
{
MySecondQtProjectClass->setWindowTitle(QApplication::translate("MySecondQtProjectClass", "MySecondQtProject", 0));
pushOK->setText(QApplication::translate("MySecondQtProjectClass", "OK", 0));
pushImage->setText(QApplication::translate("MySecondQtProjectClass", "Browse for the Image", 0));
pushClassifier->setText(QApplication::translate("MySecondQtProjectClass", "Browse for the classifier", 0));
} // retranslateUi
};
namespace Ui {
class MySecondQtProjectClass: public Ui_MySecondQtProjectClass {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MYSECONDQTPROJECT_H
And the second one:
/********************************************************************************
** Form generated from reading UI file 'showerrordialog.ui'
**
** Created by: Qt User Interface Compiler version 5.4.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_SHOWERRORDIALOG_H
#define UI_SHOWERRORDIALOG_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QDialog>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
QT_BEGIN_NAMESPACE
class Ui_ShowErrorDialog
{
public:
QLabel *label;
void setupUi(QDialog *ShowErrorDialog)
{
if (ShowErrorDialog->objectName().isEmpty())
ShowErrorDialog->setObjectName(QStringLiteral("ShowErrorDialog"));
ShowErrorDialog->resize(400, 65);
label = new QLabel(ShowErrorDialog);
label->setObjectName(QStringLiteral("label"));
label->setGeometry(QRect(70, 20, 241, 21));
retranslateUi(ShowErrorDialog);
QMetaObject::connectSlotsByName(ShowErrorDialog);
} // setupUi
void retranslateUi(QDialog *ShowErrorDialog)
{
ShowErrorDialog->setWindowTitle(QApplication::translate("ShowErrorDialog", "ShowErrorDialog", 0));
label->setText(QApplication::translate("ShowErrorDialog", "Please properly select the Image or the classifier", 0));
} // retranslateUi
};
namespace Ui {
class ShowErrorDialog: public Ui_ShowErrorDialog {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_SHOWERRORDIALOG_H
Related
I want to start my QT6 Application, but got exit code 139 (interrupted by signal 11: SIGSEGV).
Login extends QMainWindow with the following code in the main.cpp:
#include <QApplication>
#include <QPushButton>
#include "Login.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
auto login = new Login();
a.setActiveWindow(login);
login->show();
return a.exec();//QApplication::exec();
}
Edit: Adding Code of my Login.h and Login.cpp to provide minimal working example.
My Login.h:
#ifndef RESTCLIENT_LOGIN_H
#define RESTCLIENT_LOGIN_H
#include <QWidget>
#include <QPushButton>
#include <QLineEdit>
#include "QMainWindow"
QT_BEGIN_NAMESPACE
namespace Ui { class Login; }
QT_END_NAMESPACE
class Login : public QMainWindow {
Q_OBJECT
QPushButton * loginButton;
QLineEdit * passwordInput;
QLineEdit * usernameInput;
public slots:
void buttonPressed();
public:
explicit Login(QWidget *parent = nullptr);
~Login() override;
private:
Ui::Login *ui;
};
#endif //RESTCLIENT_LOGIN_H
And Login.cpp:
#include "Login.h"
#include "ui_Login.h"
Login::Login(QWidget *parent) :
QMainWindow(parent), ui(new Ui::Login) {
ui->setupUi(this);
QObject::connect(loginButton, &QPushButton::clicked, this, &Login::buttonPressed);
this ->setCentralWidget(new QWidget(this));
}
Login::~Login() {
delete ui;
}
void Login::buttonPressed() {
//todo process login
}
There is no more errors when running it, as far as I undestand it, there is no problem with finding it.
My Login GUI is very simple, I'm connecting my loginButton to the buttonPressed method in the Login.cpp, but that should be fine.
My Login.h is basically method definiton and definition of the QT elements.
Some help would be very nice, cause I can't find any usefull stuff about this (As you see, I'm new to c++ and QT)
Editi 2:
my ui_login.h:
/********************************************************************************
** Form generated from reading UI file 'Login.ui'
**
** Created by: Qt User Interface Compiler version 6.2.4
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_LOGIN_H
#define UI_LOGIN_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_Login
{
public:
QLabel *label;
QLabel *label_2;
QLineEdit *usernameInput;
QLineEdit *passwordInput;
QPushButton *loginButton;
void setupUi(QWidget *Login)
{
if (Login->objectName().isEmpty())
Login->setObjectName(QString::fromUtf8("Login"));
Login->resize(1216, 835);
label = new QLabel(Login);
label->setObjectName(QString::fromUtf8("label"));
label->setGeometry(QRect(230, 180, 121, 51));
label->setLineWidth(2);
label_2 = new QLabel(Login);
label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setGeometry(QRect(220, 340, 111, 41));
usernameInput = new QLineEdit(Login);
usernameInput->setObjectName(QString::fromUtf8("usernameInput"));
usernameInput->setGeometry(QRect(490, 190, 141, 51));
passwordInput = new QLineEdit(Login);
passwordInput->setObjectName(QString::fromUtf8("passwordInput"));
passwordInput->setGeometry(QRect(490, 360, 151, 41));
loginButton = new QPushButton(Login);
loginButton->setObjectName(QString::fromUtf8("loginButton"));
loginButton->setGeometry(QRect(520, 480, 88, 34));
retranslateUi(Login);
QObject::connect(loginButton, &QPushButton::clicked, loginButton, qOverload<>(&QPushButton::click));
QMetaObject::connectSlotsByName(Login);
} // setupUi
void retranslateUi(QWidget *Login)
{
Login->setWindowTitle(QCoreApplication::translate("Login", "Login", nullptr));
label->setText(QCoreApplication::translate("Login", "Username:", nullptr));
label_2->setText(QCoreApplication::translate("Login", "Password:", nullptr));
loginButton->setText(QCoreApplication::translate("Login", "Login", nullptr));
} // retranslateUi
};
namespace Ui {
class Login: public Ui_Login {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_LOGIN_H
I am following this book and it builds some kind of todo GUI app. We firstly create a MainWindow class:
// MainWindow.hpp
#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP
#include <QMainWindow>
#include <QVector>
#include "Task.hpp" // <- irrelevant to my question
namespace Ui {
class MainWindow;
}
class MainWindow
: public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void add_task();
private:
Ui::MainWindow *ui; // <- this is what I am having problems with
QVector<Task*> m_tasks_vec;
};
#endif // MAINWINDOW_HPP
In the UI designer we add a couple of widgets and one is called tasks_layout:
Then we go on defining members of MainWindow:
// MainWindow.cpp
#include "MainWindow.hpp"
#include "ui_MainWindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_tasks_vec()
{
ui->setupUi(this);
connect(ui->add_task_button, &QPushButton::clicked, this, &MainWindow::add_task);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::add_task()
{
qDebug() << "User clicked on the button!";
auto default_task_name = "Untitled task";
auto *task = new Task(default_task_name);
m_tasks_vec.append(task);
ui->tasks_layout->addWidget(task); // problem here
}
ui->tasks_layout->addWidget(task); part causes the problem:
no member named 'tasks_layout' in 'Ui::MainWindow'
Looking at the picture above, it seems that tasks_layout maybe nested inside centralWidget, so I thought it might be typo in the book and tried ui->centralWidget->tasks_layout->addWidget(task);, but it didn't fix anything:
no member named 'tasks_layout' in 'QWidget'
What am I doing wrong?
The closest thing to my question I found is this, and it didn't help me
This is the auto-generated ui_MainWindow.h:
/********************************************************************************
** Form generated from reading UI file 'MainWindow.ui'
**
** Created by: Qt User Interface Compiler version 5.12.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QToolBar>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QWidget *centralWidget;
QLabel *status_label;
QPushButton *add_task_button;
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(420, 361);
centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
status_label = new QLabel(centralWidget);
status_label->setObjectName(QString::fromUtf8("status_label"));
status_label->setGeometry(QRect(10, 10, 111, 21));
add_task_button = new QPushButton(centralWidget);
add_task_button->setObjectName(QString::fromUtf8("add_task_button"));
add_task_button->setGeometry(QRect(320, 10, 80, 21));
MainWindow->setCentralWidget(centralWidget);
menuBar = new QMenuBar(MainWindow);
menuBar->setObjectName(QString::fromUtf8("menuBar"));
menuBar->setGeometry(QRect(0, 0, 420, 20));
MainWindow->setMenuBar(menuBar);
mainToolBar = new QToolBar(MainWindow);
mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
statusBar = new QStatusBar(MainWindow);
statusBar->setObjectName(QString::fromUtf8("statusBar"));
MainWindow->setStatusBar(statusBar);
retranslateUi(MainWindow);
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr));
status_label->setText(QApplication::translate("MainWindow", "Status: 0 todo / 0 done", nullptr));
add_task_button->setText(QApplication::translate("MainWindow", "Add task", nullptr));
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAINWINDOW_H
Your build system hasn't updated ui_MainWindow.h following changes to MainWindow.ui, it's also lacking the spacers. You need to ensure that it re-runs uic.
That should be done by QCreator's build action, but if it has gotten confused you may have to clean and/or rebuild.
When I press the close button on the tab widget, that tab must close, and the corresponding member of the identifyedWidgetMap must be copied into the deletedWidgetMap. However, the copying does not happen.
For instance, I close Tab_3 but there is in the deletedWidgetMap some information: 4, QWidget(0x17424a1).
Help if you can. Thank you.
That code lines I created are located below.
Header
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QWidget>
#include <QTextEdit>
#include <QMap>
#include <QList>
#include <iostream>
#include <QDebug>
#include <QString>
#include <QFont>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
void setMainWindowPropertiesAndItems();
QMenuBar* menuBar;
QMenu* fileMenu;
QAction* newTabAction;
QAction* openAction;
QTabWidget* tabWidget;
QMap<int, QWidget*> identifyedWidgetMap;
QMap<int, QWidget*> deletedWidgetMap;
QList<QTextEdit*> textEditList;
QVBoxLayout* vBoxLayout;
private slots:
void newTabActionHandler();
void openActionHandler();
void tryingToCloseConcreteTab(int);
};
#endif // MAINWINDOW_H
Source
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setMainWindowPropertiesAndItems();
}
MainWindow::~MainWindow()
{
}
void MainWindow::setMainWindowPropertiesAndItems()
{
setWindowTitle("Notepad");
setGeometry(0, 0, 500, 250);
move(270, 270);
menuBar = new QMenuBar(this);
setMenuBar(menuBar);
fileMenu = new QMenu("&File", this);
menuBar->addMenu(fileMenu);
newTabAction = new QAction("&New Tab", this);
fileMenu->addAction(newTabAction);
connect(newTabAction, SIGNAL(triggered()), this,
SLOT(newTabActionCommandsHandler()));
openAction = new QAction("&Open", this);
fileMenu->addAction(openAction);
connect(openAction, SIGNAL(triggered()), this,
SLOT(openActionCommandsHandler()));
identifyedWidgetMap.insert(0, new QWidget(this));
textEditList.append(new QTextEdit(this));
tabWidget = new QTabWidget(this);
tabWidget->addTab(identifyedWidgetMap.value(0), QString("Tab
%1").arg(identifyedWidgetMap.size()-1));
tabWidget->setMovable(true);
tabWidget->setTabsClosable(true);
connect(tabWidget, SIGNAL(tabCloseRequested(int)), this,
SLOT(tryingToCloseConcreteTab(int)));
vBoxLayout = new QVBoxLayout();
identifyedWidgetMap.value(0)->setLayout(vBoxLayout);
vBoxLayout->addWidget(textEditList[0]);
textEditList[0]->setCurrentFont(QFont("Monospace Regular", 14));
setCentralWidget(tabWidget);
}
void MainWindow::newTabActionCommandsHandler()
{
if(bool(deletedWidgetMap.isEmpty()) == true)
{
identifyedWidgetMap.insert(identifyedWidgetMap.size(), new
QWidget(this));
textEditList.append(new QTextEdit(this));
tabWidget->
addTab(identifyedWidgetMap.value(identifyedWidgetMap.size()-1),
QString("Tab %1").arg(identifyedWidgetMap.size()-1));
tabWidget->
setCurrentWidget(identifyedWidgetMap.
value(identifyedWidgetMap.size()-1));
vBoxLayout = new QVBoxLayout();
identifyedWidgetMap.value(identifyedWidgetMap.size()-1)->
setLayout(vBoxLayout);
vBoxLayout->addWidget(textEditList[textEditList.size()-1]);
textEditList[textEditList.size()-1]->setCurrentFont(QFont("Monospace
Regular", 14));
}
}
void MainWindow::openActionCommandsHandler()
{
QWidget* currentWidget = tabWidget->currentWidget();
std::cout<<"The currentWidget address is: "<<currentWidget<<std::endl;
qDebug()<<"The complete identifyedWidgetMap address set is: ";
foreach(int widgetIdentifyer, identifyedWidgetMap.keys())
{
qDebug()<<widgetIdentifyer<<", "
<<identifyedWidgetMap.value(widgetIdentifyer);
}
int currentWidgetIndex = 0;
currentWidgetIndex = tabWidget->currentIndex();
std::cout<<"The currentWidgetIndex is: "<<currentWidgetIndex<<std::endl;
qDebug()<<"The complete deletedWidgetMap set is: ";
foreach(int widgetIdentifyer, deletedWidgetMap.keys())
{
qDebug()<<widgetIdentifyer<<", "
<<deletedWidgetMap.value(widgetIdentifyer);
}
}
void MainWindow::tryingToCloseConcreteTab(int concreteIndex)
{
tabWidget->removeTab(concreteIndex);
std::cout<<"Deleted identifyer is: "<<concreteIndex<<std::endl;
deletedWidgetMap.insert(identifyedWidgetMap.key(tabWidget-
>widget(concreteIndex)),
identifyedWidgetMap.value(identifyedWidgetMap.key(tabWidget-
>widget(concreteIndex))));
}
The problem I see is you first remove the tab from the tabWidget. This results in an index change, the next tab will shift to left when you remove the tab. When you try to access the tab with tabWidget->widget(concreteIndex)you access the next tab.
You may consider adding tab to the deletedWidgetMap before removing it.
I used the QT Designer to create a simple dialog and put a pushbutton on it. Then I added a custom slot on pressed() signal called test_button(). I see the generated code and can see that there is a setupUI function that has the following in it:
QObject::connect(pushButton, SIGNAL(clicked()), TestUIClass, SLOT(test_button()));
I have a testui.cpp and a testui.h:
#include <QtWidgets/QMainWindow>
#include "ui_testui.h"
class TestUI : public QMainWindow
{
Q_OBJECT
public:
TestUI(QWidget *parent = 0);
~TestUI();
virtual void test_button();
private:
Ui::TestUIClass ui;
};
This is the testui.cpp
#include "testui.h"
#include <QMessageBox>
TestUI::TestUI(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
TestUI::~TestUI()
{
}
void TestUI::test_button()
{
QMessageBox msgBox;
msgBox.setText("The document has been modified.");
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
}
My understanding is this is all I have to do, but I cant get the message box to come up.
/********************************************************************************
** Form generated from reading UI file 'testui.ui'
**
** Created by: Qt User Interface Compiler version 5.9.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_TESTUI_H
#define UI_TESTUI_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QToolBar>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_TestUIClass
{
public:
QWidget *centralWidget;
QPushButton *pushButton;
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;
void setupUi(QMainWindow *TestUIClass)
{
if (TestUIClass->objectName().isEmpty())
TestUIClass->setObjectName(QStringLiteral("TestUIClass"));
TestUIClass->resize(600, 400);
centralWidget = new QWidget(TestUIClass);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
pushButton = new QPushButton(centralWidget);
pushButton->setObjectName(QStringLiteral("pushButton"));
pushButton->setGeometry(QRect(120, 70, 187, 57));
TestUIClass->setCentralWidget(centralWidget);
menuBar = new QMenuBar(TestUIClass);
menuBar->setObjectName(QStringLiteral("menuBar"));
menuBar->setGeometry(QRect(0, 0, 600, 47));
TestClass->setMenuBar(menuBar);
mainToolBar = new QToolBar(TestUIClass);
mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
TestUIClass->addToolBar(Qt::TopToolBarArea, mainToolBar);
statusBar = new QStatusBar(EyeGazeUIClass);
statusBar->setObjectName(QStringLiteral("statusBar"));
TestUIClass->setStatusBar(statusBar);
retranslateUi(TestUIClass);
QObject::connect(pushButton, SIGNAL(clicked()), TestUIClass, SLOT(test_button()));
QMetaObject::connectSlotsByName(TestUIClass);
} // setupUi
void retranslateUi(QMainWindow *TestUIClass)
{
TestUIClass->setWindowTitle(QApplication::translate("TestUIClass", "TestUI", Q_NULLPTR));
pushButton->setText(QApplication::translate("TestUIClass", "PushButton", Q_NULLPTR));
} // retranslateUi
};
namespace Ui {
class TestUIClass: public Ui_TestUIClass {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_TestUI_H
First, you need to tell Qt that your slots actually are slots:
public slots: // or protected/private
void test_button();
There is no need for having the slot virtual...
Second, slots for 'clicked' signal are expected to accept a boolean parameter:
void test_button(bool);
For a normal push button, you can ignore the value, though.
Finally, but that's just a hint: Qt introduced with version 5 a new syntax for connecting signals/slots:
QObject::connect(pushButton, &QPushButton::clicked, theUI, &TestUIClass::test_button);
I prefer it, but it is up to you which one you use...
I have the following main.cpp file:
#include <QApplication>
#include "ui_checkabder.h"
#include <QDialog>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Ui::CheckAbder ui;
QDialog *dialog = new QDialog;
ui.setupUi(dialog);
dialog->show();
return app.exec();
}
And, get the following errors when trying to run the program:
C:/Users/avbder/Desktop/abder/main.cpp:7: error: 'CheckAbder' is not a member of 'Ui'
C:/Users/avbder/Desktop/abder/main.cpp:7: error: expected ';' before 'ui'
C:/Users/avbder/Desktop/abder/main.cpp:7: error: expected ';' before 'ui'
C:/Users/avbder/Desktop/abder/main.cpp:9: error: 'ui' was not declared in this scope
The contents of ui_checkabder.h is as follows:
/********************************************************************************
** Form generated from reading UI file 'checkabder.ui'
**
** Created: Mon Apr 18 10:01:09 2011
** by: Qt User Interface Compiler version 4.7.3
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_CHECKABDER_H
#define UI_CHECKABDER_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QHBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QPushButton>
#include <QtGui/QVBoxLayout>
#include <QtGui/QWidget>
QT_BEGIN_NAMESPACE
class Ui_Form
{
public:
QVBoxLayout *verticalLayout;
QHBoxLayout *horizontalLayout;
QLabel *label;
QLineEdit *lineEdit;
QHBoxLayout *horizontalLayout_2;
QPushButton *okButton;
QPushButton *cancelButton;
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(400, 300);
verticalLayout = new QVBoxLayout(Form);
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
horizontalLayout = new QHBoxLayout();
horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
label = new QLabel(Form);
label->setObjectName(QString::fromUtf8("label"));
QFont font;
font.setFamily(QString::fromUtf8("Comic Sans MS"));
font.setPointSize(16);
label->setFont(font);
horizontalLayout->addWidget(label);
lineEdit = new QLineEdit(Form);
lineEdit->setObjectName(QString::fromUtf8("lineEdit"));
horizontalLayout->addWidget(lineEdit);
verticalLayout->addLayout(horizontalLayout);
horizontalLayout_2 = new QHBoxLayout();
horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
okButton = new QPushButton(Form);
okButton->setObjectName(QString::fromUtf8("okButton"));
okButton->setEnabled(false);
QFont font1;
font1.setFamily(QString::fromUtf8("Comic Sans MS"));
font1.setBold(true);
font1.setWeight(75);
okButton->setFont(font1);
horizontalLayout_2->addWidget(okButton);
cancelButton = new QPushButton(Form);
cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
cancelButton->setFont(font1);
horizontalLayout_2->addWidget(cancelButton);
verticalLayout->addLayout(horizontalLayout_2);
retranslateUi(Form);
QMetaObject::connectSlotsByName(Form);
} // setupUi
void retranslateUi(QWidget *Form)
{
Form->setWindowTitle(QApplication::translate("Form", "Form", 0, QApplication::UnicodeUTF8));
label->setText(QApplication::translate("Form", "Name", 0, QApplication::UnicodeUTF8));
okButton->setText(QApplication::translate("Form", "OK", 0, QApplication::UnicodeUTF8));
cancelButton->setText(QApplication::translate("Form", "CANCEL", 0, QApplication::UnicodeUTF8));
} // retranslateUi
};
namespace Ui {
class Form: public Ui_Form {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_CHECKABDER_H
Any ideas on how to solve those problems?
Thanks.
Your class name is Ui_Form and Ui::Form and not CheckAbder. You should rename it in Designer.
You need to understand uic a little bit. File name has nothing to do with generated Ui namespaces content. Your widget in .ui file is named "Form" not CheckAbder. You can solve your problem in two ways:
Start using Ui::Form in your .cpp file
Rename Form to CheckAbder in you .ui file
Also make sure, your .ui file is added to project, so it will automaticly generate new ui_*.h file after you change .ui
namespace Ui {
class Form: public Ui_Form {};
} // namespace Ui
should be
namespace Ui {
class CheckAbder: public Ui_Form {};
} // namespace Ui