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

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);
}
}

Related

How to use QMenu signals?

It is very straightforward to connect to QMenu::triggered or QMenu::hovered signals by calling QObject::connect and pass the appropriate QAction.
However, I do not know how to use QMenu::aboutToHide signal, as there is no action passed to that signal.
How to use QMenu::aboutToHide and QMenu::aboutToShow signals or those are just virtual functions that can be overridden?
The signals in the world of Qt are not functions, never invoke them. The signals notify that something has happened with the QObject and send information if necessary.
In the case of triggered and hovered it is necessary to send the QAction because several QActions in a QMenu, then the developer thought that it is necessary to know with which QAction was interacting. On the other hand with aboutToShow and aboutToHide the signal does not send anything because it wants to notify is that if the QMenu was shown or hidden, respectively. Is there any need to know that QMenu was shown or hidden if he did it ? no, because the sender did it, I do not use other properties that we do not have at hand.
Example of use:
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow w;
QMenu *foo_menu = w.menuBar()->addMenu("Foo Menu");
for(const QString & name: {"action1", "action2", "action3"}){
foo_menu->addAction(name);
}
QObject::connect(foo_menu, &QMenu::aboutToShow, [](){
qDebug()<<"aboutToShow";
});
QObject::connect(foo_menu, &QMenu::aboutToHide, [](){
qDebug()<<"aboutToHide";
});
QObject::connect(foo_menu, &QMenu::triggered, [](QAction *action){
qDebug()<< "triggered: " <<action->text();
});
QObject::connect(foo_menu, &QMenu::hovered, [](QAction *action){
qDebug()<< "hovered: " <<action->text();
});
w.show();
return a.exec();
}
And what happens if you have several QMenu that connect to the same slot? How do I know QMenu was shown or hidden?
The solution is to use sender() which is a method that belongs to the QObject class that returns the object that emitted the signal, in this case the QMenu.
Example:
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QDebug>
class MainWindow: public QMainWindow{
public:
MainWindow(QWidget *parent=nullptr):
QMainWindow(parent)
{
for(const QString & name_of_menubar: {"bar1", "bar2", "bar3"}){
QMenu *menu = menuBar()->addMenu(name_of_menubar);
connect(menu, &QMenu::aboutToShow, this, &MainWindow::on_aboutToShow);
connect(menu, &QMenu::aboutToHide, this, &MainWindow::on_aboutToHide);
for(const QString & name: {"action1", "action2", "action3"}){
menu->addAction(name);
}
}
}
private slots:
void on_aboutToShow(){
if(QMenu *menu = qobject_cast<QMenu *>(sender()))
qDebug()<<"aboutToShow" << menu->title();
}
void on_aboutToHide(){
if(QMenu *menu = qobject_cast<QMenu *>(sender()))
qDebug()<<"aboutToHide" << menu->title();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

Qt: How to link hand coded UI with UI builder?

I am looking for an easy way to link hand coded design to the UI for widgets applications in Qt. I plan to use the UI builder to easily adjust the layouts and obtain proper spacing, which I find hard to do without the UI builder.
I want to create a 3x3 grid of buttons for which I plan to use QVector< QVector<QPushButton*> > (I am not sure how I would do this in UI builder.)
Here is what I have tried, Why are the buttons not displayed even when I set the parent of each button to the widget ?
main.cpp
#include "window.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Window w;
w.show();
return a.exec();
}
window.h
#ifndef WINDOW_H
#define WINDOW_H
#include <QWidget>
#include <QPushButton>
namespace Ui {
class Window;
}
class Window : public QWidget
{
Q_OBJECT
public:
explicit Window(QWidget *parent = 0);
~Window();
private:
Ui::Window *ui;
static const int tiles = 50, height = 600, width = 500;
QVector< QVector<QPushButton*> > cells;
};
#endif // WINDOW_H
window.cpp
#include "window.h"
#include "ui_window.h"
Window::Window(QWidget *parent) :
QWidget(parent),
ui(new Ui::Window)
{
ui->setupUi(this);
this->resize(width, height);
int j = 0;
for(auto &row : cells)
{
int i = 0;
for(auto &col : row)
{
col = new QPushButton(this);
col->setGeometry(i, j, tiles, tiles);
i += tiles;
}
j += tiles;
}
}
Window::~Window()
{
delete ui;
for(auto &row : cells)
{
for(auto &col : row)
{
delete col;
}
}
}
Any help would be appreciated.
The vectors are empty, so you iterate over nothing. Instead of managing these manually, you could leverage the grid layout.
Alas, you're complicating things unnecessarily with all the manual memory management and geometry management. It's unnecessary. All you need to do is to add widgets to the layout you allude to. And even then, I don't see how relegating the layout to a .ui file helps you since there the layout must be empty. So yes: you can set spacings, but you won't see them until you run the code. So it seems like a pointless exercise, unless you have other elements you're not telling us about (why aren't you - you went so far already).
Below is a minimum example that simplifies it as much as practicable, but see this answer and the links therein for more idea.
// https://github.com/KubaO/stackoverflown/tree/master/questions/button-grid-43214317
#include <QtWidgets>
namespace Ui { class Window {
public:
// Approximate uic output
QGridLayout *layout;
void setupUi(QWidget * widget) {
layout = new QGridLayout(widget);
}
}; }
class Window : public QWidget
{
Q_OBJECT
Ui::Window ui;
QPushButton * buttonAt(int row, int column) {
auto item = ui.layout->itemAtPosition(row, column);
return item ? qobject_cast<QPushButton*>(item->widget()) : nullptr;
}
public:
explicit Window(QWidget *parent = {});
};
Window::Window(QWidget *parent) : QWidget(parent) {
ui.setupUi(this);
for (int i = 0; i < 5; ++i)
for (int j = 0; j < 6; ++j)
{
auto b = new QPushButton(QStringLiteral("%1,%2").arg(i).arg(j));
ui.layout->addWidget(b, i, j);
}
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Window w;
w.show();
return a.exec();
}
#include "main.moc"

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

Qt Widget temporarily fullscreen

Consider a QWidget, normally a child in some Layout.
Supposed I want to make it fullScreen for a while, then have it return to it's old spot.
QWidget::setFullScreen() requires that the widget needs to be an independent window - any ideas how to work it out?
The simplest way I can see is to reparent to 0. Something like this:
#include <QApplication>
#include <QPushButton>
class MyButton : public QPushButton
{
public:
MyButton(QWidget* parent) : QPushButton(parent) {}
void mousePressEvent(QMouseEvent*) {
this->setParent(0);
this->showMaximized();
this->show();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget mainWidget;
MyButton button(&mainWidget);
mainWidget.show();
return a.exec();
}
I have modified the previous example. The previous example never goes back to normal screen.
Just copy paste the code and it will run.
#include <QApplication>
#include <QPushButton>
class MyButton : public QPushButton
{
public:
MyButton(QWidget* parent) : QPushButton(parent) {
m_pParent = parent;
maxMode = false;
}
QWidget * m_pParent;
bool maxMode;
Qt::WindowFlags m_enOrigWindowFlags;
QSize m_pSize;
void mousePressEvent(QMouseEvent*) {
if (maxMode== false)
{
m_enOrigWindowFlags = this->windowFlags();
m_pSize = this->size();
this->setParent(0);
this->setWindowFlags( Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
this->showMaximized();
maxMode = true;
}
else
{
this->setParent(m_pParent);
this ->resize(m_pSize);
this->overrideWindowFlags(m_enOrigWindowFlags);
this->show();
maxMode = false;
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget mainWidget;
MyButton button(&mainWidget);
mainWidget.show();
return a.exec();
}

Storing variables from dialog and using it in a qvtkwidget

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
}

Resources