Storing variables from dialog and using it in a qvtkwidget - qt

I've created a dialog where I ask for some lengths of a number of slices, as xmax, ymax, and zmax as the number of slices. I intend to use those numbers in the mainwindow in the qvtkwidget. I'll simplify and make the example to only one variable so you can understand and help me.
Here's my dialog.cpp
#include <QtGui/QApplication>
#include <QDir>
#include <iostream>
using namespace std;
#include "dialog.h"
#include "ui_dialog.h"
// Create getters to transfer variables to main.cpp
double Dialog::getxpax()
{
return xpax;
}
// Start the mainwindow
void Dialog::startplanevolume()
{
// Getting some proprieties for the lenght of the volume
QString XMAX=ui->lineEdit->text();
xpax=XMAX.toDouble();
if (xpax==0)
{
ui->label_17->setText("Error: Can't start, invalid \nmeasures");
ui->label_17->setStyleSheet("QLabel { color : red; }");
}
else
{
this->accept();
}
}
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
// Control volume measures
// Making the lineedit objects only accept numbers
ui->lineEdit->setValidator(new QDoubleValidator(this));
// Start planevolume
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(startplanevolume()));
connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(hide()));
}
The pushbutton is the ok button and the pushbutton_2 is the cancel button.
In my mainwindow I created a setter function to set the value of the xmax.
here's some code.
// Get stored data from dialog
void planevolume::setxpax(double xpax)
{
xp=xpax;
}
and when I use qDebug() the xp inside the settter shows me that the xp actually gets the xpax value.
here's my main.cpp
#include <QtGui/QApplication>
#include <iostream>
using namespace std;
#include "planevolume.h"
#include "dialog.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Dialog *dialog= new Dialog;
if (dialog->exec())
{
planevolume mainwindow;
mainwindow.setxpax(dialog->getxpax());
mainwindow.show();
return app.exec();
}
return 0;
}
So the only problem is that is here, at mainwindow as planevolume.cpp when I need it, the value has not been set,
planevolume::planevolume(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::planevolume)
{
ui->setupUi(this);
// My vtk statements are here in the code, but they are
// executed before the setter gives the value to my new
// variable xp, so when I need the value it has not been set yet.
Any ideas guys?

If the planevolume constructor needs these data, they could be passed as parameter to the constructor itself (you can also make the dialog return all the variables inside a struct to have a single parameter to pass, instead of having an accessor for each one).
Another solution would be to call the vtk part after the event loop has started by putting it in a slot and schedule its execution with a QTimer::singleShot.
In that last case, your code should like this:
planevolume::planevolume(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::planevolume)
{
ui->setupUi(this);
QTimer::singleShot(0, this, SLOT(setupVtk()));
}
// declared as a slot in the class
void planevolume::setupVtk()
{
// Your VTK statements would be here
}

Related

Dynamically adding widgets to gridLayout Qt

I am having a bit of difficulty with some code. I am super rather new to Qt so it is entirely possible that I am simply ignorant to the problem I am having.
Basically, I am blocking out a program so that I can add the specifics of it later. I want to be able to create a grid of buttons, and when one of those buttons is pressed, another shape to replace it.
I am able to make my button grid, have it be scrollable, and have the button call it its position on the grid when pressed. However, when I try and use those coordinates to add another button to the grid, Qt crashes.
Here's my code so far:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <cmath>
#include <QLabel>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QApplication>
#include <QPushButton>
#include <QScrollArea>
#include <QDebug>
#include <QString>
#include <QSignalMapper>
#include <QStringList>
#include <QLayoutItem>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
populateViewGrid(); //I wanted to see if I could add in a scrollbar
//from outside the main window. Could this be causing
// the issue?
}
void MainWindow::populateViewGrid()
{
QScrollArea*scrollArea = new QScrollArea(this);
QWidget*central = new QWidget(this);
QGridLayout*gridLayout = new QGridLayout(central);
QSignalMapper *signalMapper = new QSignalMapper(central);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
QString position= QString("%1,%2").arg(i).arg(j);
QPushButton* button = new QPushButton("addTrack",central);
gridLayout->addWidget(button, i, j);
connect(button, SIGNAL(clicked()),signalMapper, SLOT(map()));
signalMapper->setMapping(button, position);
}
}
connect(signalMapper, SIGNAL(mapped(QString)),this, SLOT(addTrack(QString )));
central->setLayout(gridLayout);
scrollArea->setWidget(central);
setCentralWidget(scrollArea);
}
void MainWindow::addTrack(QString position)
{
QStringList query = position.split(",");
int x;
x=query.at(0).toInt();
int y;
y=query.at(1).toInt() ;
QPushButton *Ifthisworks=new QPushButton(this);
//This first line is where is crashes. I know this due to having the code
//laced with qDebugs. From all of my google searches and such, it seems that
// something simple should be wrong and I can't find it.
QLayoutItem * existingitem = gridLayout->itemAtPosition(x, y);
if(existingitem) {
gridLayout->removeItem(existingitem);
delete existingitem;
}
// before I included the above to remove the button from the grid point, the
//program would crash here.
gridLayout->addWidget(Ifthisworks, x, y);
}
MainWindow::~MainWindow()
{
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();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <cmath>
#include <QLabel>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QApplication>
#include <QPushButton>
#include <QMainWindow>
#include <QScrollArea>
#include <QSignalMapper>
#include <QHash>
//unrelated question, do I need the above in my code? I know not all of them
//used, but do I need includes in this file as well?
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void populateViewGrid();
QGridLayout *gridLayout;
public slots:
void addTrack(QString);
private:
QScrollArea*scrollArea;
QWidget * central;
QPushButton *Ifthisworks;
QSignalMapper *signalMapper;
QPushButton *clockViews;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
If you could help me understand how to not make Qt crash there and also add a button, that would be fantastic =)
So some background real quick incase you are looking at my code and are scratching your head. I'm a mechanical engineer who should have probably been an electrical or computer engineer and knows enough about coding to get myself into these kinds of messes. For the most part, I searched for what I wanted Qt to do and hacked it all together to hopefully make it work. Any bit of deeper understanding you can share would be more than welcome.
Thank you for your time.
You are initializing a local variable called gridLayout in your MainWindow::populateViewGrid() method:
QGridLayout*gridLayout = new QGridLayout(central);
Then in your MainWindow::addTrack(QString position) method, you are trying to access the member variable called gridLayout which is never initialized.
To fix this, simply initialize the member variable instead of creating a local variable in your MainWindow::populateViewGrid() method:
gridLayout = new QGridLayout(central);
You are doing the same mistake with your other member variables as well. Fix them the same way.
I would go for a different implementation.
Move gridlayout, signalmapper,... to be class members. I personally like also to keep a list of my widgets QList<QPushButton*> for manually deleting or keeping a button cache.
Make the signalmapper to map to index in list or QWidget*. For the example i`ll go with the QWidget* pointer.
QPushButton *newButton = new QPushButton("The new Thing");
QPushButton *oldButton = static_cast<QPushButton*>(widgetPointer);
gridLayout->replaceWidget(oldButton ,newButton);
buttonList->takeAt(buttonList->indexOf(oldButton))->deleteLater()); //if you keep a list..
buttonList->insert(buttonList->indexOf(oldButton),newButton);

use QCamera in Qt console application

I want to use the camera in a headless (console) qt application (at least for unit testing).
But I facing a problem with Qt. As soon I use my code in a console application, the camera won't work - the readyForCaptureChanged event of QCameraImageCapture will not be called.
If I use exactly the same code in a gui application, the event gets triggered and I can capture images.
The common code I use is that:
camera = new QCamera(cameras.at(config->cameraNumber()));
imageCapture = new QCameraImageCapture(camera);
connect(imageCapture, SIGNAL(readyForCaptureChanged(bool)), this, SLOT(readyForCapture(bool)));
camera->start(); // to start the viewfinder
// ——
void ImageCapture::readyForCapture(bool b) {
qDebug() << "ready for capture "<<b;
}
when I call this code in the gui application directly in the constructor of my MainWindow, it works (event will be triggered).
When I call this code in my qt console application, it does not work (event will not be triggered).
Can anybody help me? Thanks
** UPDATE 29. August - full code **
Console Application:
main.cpp
#include <QCoreApplication>
#include <QTest>
#include <QTimer>
#include <QDebug>
#include <runoneventloop.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
RunOnEventLoop * run = new RunOnEventLoop(&a);
QTimer::singleShot(0, run, SLOT(run()));
return a.exec();
}
RunOnEventLoop.cpp
#include "runoneventloop.h"
RunOnEventLoop::RunOnEventLoop(QObject *parent) :
QObject(parent)
{
}
void RunOnEventLoop::run() {
qDebug() << "hier run";
camera = new QCamera(0);
imageCapture = new QCameraImageCapture(camera);
connect(imageCapture, SIGNAL(readyForCaptureChanged(bool)), this, SLOT(readyForCapture(bool)));
camera->start(); // to start the viewfinder
}
void RunOnEventLoop::readyForCapture(bool b) {
qDebug() << "ready of capture "<<b;
}
RunOnEventLoop.h
#ifndef RUNONEVENTLOOP_H
#define RUNONEVENTLOOP_H
#include <QObject>
#include <QDebug>
#include <QCamera>
#include <QCameraImageCapture>
class RunOnEventLoop : public QObject
{
Q_OBJECT
public:
explicit RunOnEventLoop(QObject *parent = 0);
private:
QCamera* camera;
QCameraImageCapture* imageCapture;
signals:
public slots:
void run();
void readyForCapture(bool);
};
#endif // RUNONEVENTLOOP_H
GUI Application
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
qDebug() << "hier";
camera = new QCamera(0);
imageCapture = new QCameraImageCapture(camera);
connect(imageCapture, SIGNAL(readyForCaptureChanged(bool)), this, SLOT(readyForCapture(bool)));
camera->start(); // to start the viewfinder
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::readyForCapture(bool b) {
qDebug() << "ready of capture "<<b;
}
again, it's the same code. Console App does not call the readyForCapture method, while the gui application calls it.
you can download the archive here: DOWNLOAD
If would be nice if you could provide something more of your console-based Qt application... the code you presented, how is it called by your main code?
Anyway, just guessing, if no events are raised at all maybe it is because you are not running any event loop... are you sure that your code at some point call exec() on your QCoreApplication object? Are you sure that the owner of the object from which you call connect() is the thread of QCoreApplication?

How to update the QT Mainwindow at each loop in mainwindow.cpp

My main.cpp look like this:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
An in my mainwindow.cpp I want to show a different image at each loop in "while", so it would look like this:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
image = load_an_image
int i=0;
while (i<15)
{
show image in the MainWindow
waitkey (wait until I press a key or wait some time)
do something to this image for the next loop
i++
}
}
However the Mainwindow does not show up until the "while" is finished and I cannot find how to show the MainWindow at each loop.
Can anyone give me any advice ?
GUI will not update itself until gui thread is free of other tasks. However, you can force it using
qApp->processEvents();
Following is example of very bad coding style, but that might be what you want.
#include "mainwindow.h"
#include <QApplication>
#include <thread>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
qint8 k = 15;
using namespace Qt;
QPalette pal;
QColor col = red;
while (k--)
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
pal.setBrush(w.backgroundRole(), QBrush(col));
w.setPalette(pal);
col = col == red ? blue : red;
qApp->processEvents();
}
return a.exec();
}
To run this, you will have to add QMAKE_CXXFLAGS += -std=c++11 to your '.pro' file.
And if you want to understand things better, i recommend to read about qt events.
You could delay handling the image by using a Qtimer. Something like this: -
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTimer::singleShot(5, this, SLOT(timeout());
}
// create as a slot in the MainWindow derived class
void MainWindow::timeout()
{
image = load_an_image();
int i=0;
while (i<15)
{
// show image in the MainWindow
// waitkey (wait until I press a key or wait some time)
// do something to this image for the next loop
i++
}
}
However, it would be better handled by loading the first image and then reacting to key events, rather than waiting directly in the main thread...
void MainWindow::keyReleaseEvent(QKeyEvent* keyEvent)
{
if(keyEvent->key() == Qt::Key_Space) // use the space bar, for example
{
if(m_imageFrame < 15)
{
// update the image
}
}
else
{
QMainWindow::keyReleaseEvent(keyEvent);
}
}

Qt call to update not triggering call to paintEvent() while drawing data from serial port to scrollArea

I am newbie to Qt 5.1.0. My problem with Qt is showed directly as follows. Data from serial port is received by readdata(), then call the draw() in mainwindow.cpp to deliver the data to newpaint() in paint.cpp. Two classes are created in this project:class mainwindow is mainly responsible for receiving data from serial port,class paint is for drawing the data (actually the data is coordinates of a mathematical function) on the scroll area widget which is on the mainwindow.
But in paint.cpp, paintevent is not invoked by update().UpdateEnabled() returns true depicting that the problem doesn't exist in the use of update().
Main part is pasted below.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
QPainterPath linepath;
linepath.moveTo(0,0);
ui->setupUi(this);
paintwiget=new paint(linepath,ui->scrollArea);
ui->scrollArea->setWidget(paintwiget);
paintwiget->show();
ui->closeserial->setEnabled(false);
ui->sendData->setEnabled(false);
serial=new QSerialPort(this);
connect(serial,SIGNAL(readyRead()),this,SLOT(readData()));
}
void paint::newpaint(qreal *aa1, int len1)
{
if (!aa.isEmpty())
aa.clear();
int i;
for (i=0;i<len1;i++)
aa.append(aa1[i]);
// qDebug()<<aa.size();
//qDebug()<<"aa[0:3]"<<aa[0]<<" "<<aa[1]<<" "<<aa[2]<<" "<<aa[3];
len=len1;
// this->setVisible(true);
qDebug()<<this->isVisible();//now returns true
this->update();
//qDebug()<<"okla";
}
void paint::paintEvent(QPaintEvent *)
{
qDebug()<<"ok~~";
QPointF currentpoi;
QPainter painter(this);
int ii=0;
qDebug()<<len;
for (ii=0;ii<len/2;ii++)
{
currentpoi=path.currentPosition();
qDebug()<<"currentpoi"<<currentpoi;
path.moveTo(currentpoi);
path.lineTo(aa[2*ii],aa[2*ii+1]);
// painter.setRenderHint(QPainter::Antialiasing);
painter.drawPath(path);
}
}
paint.h
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QTabWidget>
//#include <mainwindow.h>
class paint : public QWidget
{
public:
explicit paint(QPainterPath &path,QWidget *parent=0);
void newpaint(qreal *,int);
QVector <qreal>aa;
int len;
QWidget *parent;
private:
QPointF point;
QPainterPath path;
protected:
void paintEvent(QPaintEvent *event);
};
Hard to say for sure that this is the only issues you are facing, but there are at least three issues:
Issue 1
The following code tells me that you have a member of MainWindow called paint * paintwiget:
void MainWindow::draw(qreal *aa,int len)
{
// ...
paintwiget->newpaint(dist,len);
}
Then, this code tells me that you are creating a new temporary variable of the same name:
MainWindow::MainWindow(QWidget *parent)
{
// ...
paint *paintwiget=new paint(linepath,ui->scrollArea->viewport());
}
The compiler should have probably given you a warning for this. Replace this line by:
paintwiget = new paint(linepath,ui->scrollArea->viewport());
(notice the lack of paint *), and tell me if this solves the problem.
Issue 2
You have to change this:
void paint::newpaint(qreal *aa, int len)
{
// ...
aa[i]=aa[i];
len=len;
}
by this:
void paint::newpaint(qreal *aa_new, int len_new)
{
// ...
aa[i]=aa_new[i];
len=len_new;
}
Otherwise, your aa[i]=aa[i] has no effect: it replaces the parameter of the method by itself, instead of replacing your member by the parameter of the method. Using a parameter with the same name than a member "hides" the member: you can't access it anymore, either at the left hand side or the right hand side of an assignment.
Issue 3
I'm not quite sure what you are doing with scrollArea->viewport() in the constructor of paint, but something tells me you are doing it wrong. The constructor of paint should NOT use it, but instead, you should do:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPainterPath linepath;
paintwiget = new paint(linepath); // Do NOT pass viewport in parameter
ui->scrollArea->setWidget(paintwiget);
paintwiget->show();
// ...
}

PopUP Window in Qt

I am creating an application in Qt and I have a problem. I have a main window and I want that when I push a button, a popup window appears. I dont know how can I do it. I tried to call the show() method when I push the button but dont work. I think that I must use the exec() method from QApplication but I dont know how can call it if I created it in the main class.
My classes:
#include "mainwindow.h"
#include "dialog.h"
#include <QApplication>
#include "popup1.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
MainWindow:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
#include <QApplication>
int posiciones[10];
std::string port="";
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
for (int i=1; i<10; i++){
if(i==7){
posiciones[i]=90;
}
posiciones[i]=0;
}
//Mandar el vector para mover
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
PopUp:
#include "popup1.h"
#include "ui_popup1.h"
Popup1::Popup1(QWidget *parent) :
QDialog(parent),
ui(new Ui::Popup1)
{
ui->setupUi(this);
}
Popup1::~Popup1()
{
delete ui;
}
Anyone knows how can I show the popup window? Thanks for your time.
Connect your button signal clicked() with exec() slot of your popup window:
connect(pushButton, SIGNAL(clicked()), popupWindow, SLOT(exec()));
Where pushButton - pointer to your button, and popupWindow - pointer to your popup window. You can write this code in QMainWindow constructor.
Include your pop-up class in your MainWindow.h:
include "popup.h"
Define a pointer to your pop-up class in the MainWindow.h:
popup1 *mpPopUp1;
Create an object in the MainWindow.cpp file:
mpPopUp1 = new popup1;
Define a slot in MainWindow.h and call it, for example, showPopUp():
void showPopUp();
Create the slot showPopUp() in your MainWindow.cpp and write the following statement inside it:
mpPopUp1 ->show();
Connect your pushButton to the slot showPopUp():
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(showPopUp()));
Run you app, click on pushButton and voila

Resources