Qt segfault trying to show 2 dialogs in test application - qt

I'm just learning Qt. I reproduced my problem in a simple test application. I created a new project. Added 2 dialogs Dialog1 and Dialog2. I added 2 menu entries to call dialog1 and dialog2.
The main window's header file looks like this:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "dialog1.h"
#include "dialog2.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_actiondialog1_triggered();
void on_actiondialog2_triggered();
private:
Ui::MainWindow *ui;
Dialog1 *mDialog1;
Dialog2 *mDialog2;
};
#endif // MAINWINDOW_H
The main window's cpp looks like this:
#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::on_actiondialog1_triggered()
{
if (!mDialog1) {
mDialog1 = new Dialog1(this);
mDialog1->setModal(false);
}
mDialog1->show();
mDialog1->activateWindow();
}
void MainWindow::on_actiondialog2_triggered()
{
if (!mDialog2) {
mDialog2 = new Dialog2(this);
mDialog2->setModal(false);
}
mDialog2->show();
mDialog2->activateWindow();
}
So it is basically as empty as it gets... If I only show one dialog by commenting out the relevant sections it works but as soon as I want to use 2 or more is segfaults. The given dialogs constructor isn't even being called anymore.
I am using:
Qt Creator 4.12.3
Based on Qt 5.14.2 (GCC 5.3.1 20160406 (Red Hat 5.3.1-6), 64 bit)
Built on Jun 16 2020 04:15:35
I don't understand what I'm doing wrong. Can someone please clarify?

First, it is not about Qt. It is about your implementation:In your constructor, I don't see code, which initializes mDialog1 and mDialog2.
So, when go to the slot what is the value of mDialog1 ? It is undefined, especially in Release build.
Here is one of the approaches:
In your constructor, just create the objects:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
mDialog1 = new Dialog1(this);
mDialog2 = new Dialog2(this);
}
Then in slot (you don't need to check the pointer):
void MainWindow::on_actiondialog1_triggered()
{
mDialog1->setModal(false); //Not required, because of show()
mDialog1->show();
mDialog1->activateWindow();
}
Another approach, which creates objects on demand:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//Initalize these members
m_dialog1 = nullptr;
m_dialog2 = nullptr;
}
And then:
void MainWindow::on_actiondialog2_triggered()
{
if (!mDialog2)
{
mDialog2 = new Dialog2(this);
mDialog2->setModal(false);
}
mDialog2->show();
mDialog2->activateWindow();
}

Related

QWidget-Method hide() destroys surface in IVI-enabled Wayland-Compositor

I have a compositor based on the IVI compositor example in which I can manipulate visibility of surfaces via the "visible" property of the respective surface.
However, when a client tries to hide a QWidget via the hide() method, the compositor will destroy the surface instead of just setting the visible property to false.
Is this the intended behavior, and if so, is there a way to change that?
Steps to reproduce:
Build and run the compositor example
Create a new Qt Widgets Project in QtCreator, leave all settings at default
Change mainwindow.h and mainwindow.cpp to look like this:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QTimer *pTimer;
private slots:
void hideWindow();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
pTimer = new QTimer();
pTimer->setInterval(1000);
connect(pTimer, SIGNAL(timeout()), this, SLOT(hideWindow()));
pTimer->start();
}
void MainWindow::hideWindow()
{
if (isVisible())
{
qDebug() << "hide!";
hide();
}
else
{
qDebug() << "show!";
show();
}
}
MainWindow::~MainWindow()
{
delete ui;
}
When you build and run this program, it will periodically hide and show its mainwindow, but the way it does this is not by telling the compositor to set the "visible" property of the widget, and instead destroying and re-creating the surface.
Also note that you need to set some environment variables before starting the app:
To start a Qt application using the ivi-application protocol with the right id, you need to set QT_WAYLAND_SHELL_INTEGRATION to ivi-shell and QT_IVI_SURFACE_ID to 1337

Qt Main Window not repainting MDI area

I have an application that have a main window with an MDI area that uses the whole window. When the application is opened it is not maximized. If i open the child window and then close it, the ghost of the window still shows. If i open a another child window and then move it across the MDI area you get copies of the window one on top of each other only in the area where the ghost was.
If i open the main window, then maximize it, open the child and maximize it, this problem disappears. Then a can get the main window to the original size, open and close child windows, move them around and the background is redrawn correctly.
Is there anything that can be done to solve this behavior?
Calling the mdi window:
void PriceAnalysisTool::on_actionImport_triggered()
{
importprocess = new ImportProcess(working, printer, ui->mdiArea);
importprocess->show();
}
And the initial part of the sub window:
ImportProcess::ImportProcess(DataBase *d, QPrinter *p, QWidget *parent) : QMdiSubWindow(parent), ui(new Ui::ImportProcess)
{
ui->setupUi(this);
Test program showing the same behavior:
main window:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include "subwindow.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_actionOpen_Window_triggered();
private:
Ui::MainWindow *ui;
SubWindow *subwindow;
};
#endif // MAINWINDOW_H
main window.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::on_actionOpen_Window_triggered()
{
subwindow = new SubWindow(ui->mdiArea);
subwindow->show();
}
subwindo.h
#ifndef SUBWINDOW_H
#define SUBWINDOW_H
#include <QWidget>
#include <QMdiSubWindow>
namespace Ui {
class SubWindow;
}
class SubWindow : public QMdiSubWindow
{
Q_OBJECT
public:
explicit SubWindow(QWidget *parent = 0);
~SubWindow();
private:
Ui::SubWindow *ui;
};
#endif // SUBWINDOW_H
subwindw.cpp
#include "subwindow.h"
#include "ui_subwindow.h"
SubWindow::SubWindow(QWidget *parent) : QMdiSubWindow(parent), ui(new Ui::SubWindow)
{
ui->setupUi(this);
}
SubWindow::~SubWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
the ui for the main window has only has a MDI are and the a menu with a single item that calls the subwindow. The subwindow is a widget that has nothing on it.
{
QSqlQuery query;
query.exec("drop table C"+QString::number(markTime.toSecsSinceEpoch()));
query.exec("drop table C"+QString::number(markTime.toSecsSinceEpoch())+"T");
query.exec("drop table C"+QString::number(markTime.toSecsSinceEpoch())+"S");
query.exec("drop table C"+QString::number(markTime.toSecsSinceEpoch())+"F");
delete ui;
}

Connecting Signals and Slots between Child and Parent (invalid use of incomplete type)

I'm trying to connect signals from a child window (QDialog named VolumePage) to its parent (QMainWindow named MockUI). I'm running into a:
invalid use of incomplete type 'class Ui::VolumePage'
error when I attempt to make the connection.
I'm trying to connect inside the MockUI.cpp when I make the volume page. (Happens on a button press)
void MockUI::on_pushButton_3_clicked()
{
//Non-Modal Approach
volPage = new VolumePage(this);
volPage->show();
connect(volPage->ui->verticalSlider,SIGNAL(valueChanged(int)),ui->progressBar,SLOT(setValue(int)));
}
I've made Ui::VolumePage *ui; public.
Here's the entire error:
error: invalid use of incomplete type 'class Ui::VolumePage'
connect(volPage->ui->verticalSlider,SIGNAL(valueChanged(int)),ui->progressBar,SLOT(setValue(int)));
Can anyone help me understand what the problem is, or another clean way to do what I'm trying to do?
Edit: (Additional Source)
VolumePage.h:
#ifndef VOLUMEPAGE_H
#define VOLUMEPAGE_H
#include <QDialog>
namespace Ui {
class VolumePage;
}
class VolumePage : public QDialog
{
Q_OBJECT
public:
explicit VolumePage(QWidget *parent = 0);
Ui::VolumePage *ui;
~VolumePage();
private slots:
void on_verticalSlider_valueChanged(int value);
private:
};
#endif // VOLUMEPAGE_H
mockUI.cpp:
#include "mockUI.h"
#include "ui_mock_ics.h"
#include <QLCDNumber>
#include "volumepage.h"
MockUI::MockUI(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MockUI)
{
ui->setupUi(this);
}
MockUI::~MockUI()
{
delete ui;
}
void MockUI::on_pushButton_3_clicked()
{
//Modal Approach
//VolumePage volPage;
//volPage.setModal(true);
//volPage.exec();
//Non-Modal Approach
volPage = new VolumePage(this);
volPage->show();
connect(volPage->ui->verticalSlider,SIGNAL(valueChanged(int)),ui->progressBar,SLOT(setValue(int)));
}
volumepage.cpp:
#include "volumepage.h"
#include "mockUI.h"
#include "ui_volumepage.h"
VolumePage::VolumePage(QWidget *parent) :
QDialog(parent),
ui(new Ui::VolumePage)
{
ui->setupUi(this);
setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);
//Mock_ICS* ics = (Mock_ICS*)parent;
//connect(ui->verticalSlider,SIGNAL(valueChanged(int)),ics->ui->progressBar,SLOT(setValue(int)));
//connect(ui->verticalSlider,SIGNAL(valueChanged(int)),this->parent()->progressBar,SLOT(setValue(int)));
}
VolumePage::~VolumePage()
{
delete ui;
}
Ui::VolumePage *ui should remain private. Instead create a signal on the volPage, something like verticalSliderValueChanged(int value). See below...
mockui.h
#ifndef MOCKUI_H
#define MOCKUI_H
#include <QMainWindow>
#include "volumepage.h"
namespace Ui {
class MockUI;
}
class MockUI : public QMainWindow
{
Q_OBJECT
public:
explicit MockUI(QWidget *parent = 0);
~MockUI();
VolumePage* volPage;
private slots:
void on_pushButton_3_clicked();
private:
Ui::MockUI *ui;
};
#endif // MOCKUI_H
mockui.cpp
#include "mockui.h"
#include "ui_mockui.h"
#include "volumepage.h"
MockUI::MockUI(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MockUI)
{
ui->setupUi(this);
}
MockUI::~MockUI()
{
delete ui;
}
void MockUI::on_pushButton_3_clicked()
{
//Non-Modal Approach
volPage = new VolumePage(this);
volPage->show();
connect(volPage,SIGNAL(verticalSliderValueChanged(int)),ui->progressBar,SLOT(setValue(int)));
}
volumepage.h
#ifndef VOLUMEPAGE_H
#define VOLUMEPAGE_H
#include <QDialog>
namespace Ui {
class VolumePage;
}
class VolumePage : public QDialog
{
Q_OBJECT
public:
explicit VolumePage(QWidget *parent = 0);
~VolumePage();
signals:
void verticalSliderValueChanged(int value);
private slots:
void on_verticalSlider_valueChanged(int value);
private:
Ui::VolumePage *ui;
};
#endif // VOLUMEPAGE_H
volumepage.cpp
#include "volumepage.h"
#include "ui_volumepage.h"
VolumePage::VolumePage(QWidget *parent) :
QDialog(parent),
ui(new Ui::VolumePage)
{
ui->setupUi(this);
}
VolumePage::~VolumePage()
{
delete ui;
}
void VolumePage::on_verticalSlider_valueChanged(int value)
{
emit verticalSliderValueChanged(value);
}
This is an example of the pImpl idiom in C++. Class VolumePage is the one you should be using - this is the "public" interface of what Qt Creator has generated. Ui::VolumePage contains the complicated details you should not worry about.
So, in your code you should be using VolumePage, not Ui::VolumePage. You shouldn't have make Ui::VolumePage public.

How to use qAction submenu in Qt

I want to implement simple commands like a qDebug() when I click on a sub menu in the mainwindow. I was referring to sample program given along with the Qt 5 IDE (...\Qt\Qt5.2.0\5.2.0\msvc2010\examples\widgets\mainwindows\menus), and using it, I managed to construct the code. I do not receive any compile time or run time errors.
I created the mainwindow.ui using the design mode. It has an object of the QAction class called actionInterval.
But when I click on it, nothing happens, I am not able to implement the command in void interval(). I guess I am not connecting properly. What am I missing here? Please advise.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
void createActions();
private slots:
void interval();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
createActions();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::createActions()
{
ui->actionInterval = new QAction(tr("&Interval"), this);
ui->actionInterval->setStatusTip(tr("Set the interval for capturing delta & reference images"));
connect(ui->actionInterval, SIGNAL(triggered()), this, SLOT(interval()));
}
void MainWindow::interval()
{
qDebug()<<"inside interval qdialog";
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
void MainWindow::createActions()
{
ui->actionInterval->setStatusTip(tr("Set the interval for capturing delta & reference images"));
connect(ui->actionInterval, SIGNAL(triggered()), this, SLOT(interval()));
}
You shouldn't need that ui->actionInterval = new QAction(tr("&Interval"), this); line, the ui->setupUi() handles that for you, so it's potentially causing an incorrect reference so when you do click on it it's not firing correctly.

Signal and Slot in Qt4 - not working

I am using Qt4 and Qt Creator. I cannot write a custom slot to a progress bar in the UI. How to write a custom slot for a specific widget in the ui file ? In my scenario, signal is not from the ui element.
the below code produces an error while running:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QFile>
#include<QFileInfo>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_btcopy_clicked();
void on_btquit_clicked();
void ChangeValue(qint64 val);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
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::on_btcopy_clicked()
{
QFileInfo *qfi=new QFileInfo("C:\\Users\\kiran\\Desktop\\test\\a.iso");
qDebug("%d" ,qfi->size());
QFile *qf=new QFile();
QFile fromFile("C:\\Users\\kiran\\Desktop\\test\\a.iso");
QFile toFile("C:\\Users\\kiran\\Desktop\\test\\b.iso");
ui->pbar->setMaximum(fromFile.size());
fromFile.copy(toFile.fileName());
connect(&toFile, SIGNAL(bytesWritten(qint64)), ui->pbar, SLOT(CangeValue(qint64)));
qDebug("completed");
}
void MainWindow::on_btquit_clicked()
{
exit(0);
}
void MainWindow::CangeValue(qint64 val)
{
ui->pbar->setValue(val);
}
Error Message
Object::connect: No such slot ProgressBar::CangeValue(qint64)in..\untitled\mainwindow.cpp:26
Object::connect: (receiver name: 'pbar')
CangeValue is a slot in your MainWindow (for the record: it should be called ChangeValue).
Therefore the third parameter in your connect(..) statement must be your main window, not the progress bar. Replace ui->pbar by this in your connect statement.

Resources