Possible to make QDialog shake in OSx - c++

Since Qt is using Cocoa under OSX, is it possible to make a modal QDialog to shake if the user enters the wrong password for example? Im not able to find anything about it but it would be really nice to implement on mac.
Thanks!

I'm not aware of a built-in way to do it, but you could implement the shaking yourself, like this:
header.h
#include <QtGui>
class ShakyDialog : public QDialog
{
Q_OBJECT
public slots:
void shake()
{
static int numTimesCalled = 0;
numTimesCalled++;
if (numTimesCalled == 9) {
numTimesCalled = 0;
return;
}
vacillate();
QTimer::singleShot(40, this, SLOT(shake()));
}
private:
void vacillate()
{
QPoint offset(10, 0);
move(((shakeSwitch) ? pos() + offset : pos() - offset));
shakeSwitch = !shakeSwitch;
}
bool shakeSwitch;
};
main.cpp
#include "header.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ShakyDialog dialog;
QHBoxLayout layout(&dialog);
QPushButton button("Push me.");
layout.addWidget(&button);
QObject::connect(&button, SIGNAL(clicked()), &dialog, SLOT(shake()));
dialog.show();
return app.exec();
}

Related

Switching two mainwindows

I am new to QT GUI programming.
I am trying to test switching two mainwindows continously by using show and hide.
I have created a simple code in main.cpp
main(){
QApplication a(argc , argv)
Mainwinodw1 *window1 = new Mainwindow1();
Mainwinodw1 *window2 = new Mainwindow2();
for (;;)
{
window1->show();
delay();
window1->hide();
window2->show();
delay();
window2->hide();
}
return a.exec();
}
The test can display the windows only one time , but duirng the second iteration they dont show and hide.
Can somebody help to fix this.
Try to use Qt timers instead of hardcoded delay function.
main.cpp file:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Mainwindow1 *window1 = new Mainwindow1();
Mainwindow2 *window2 = new Mainwindow2();
WindowSwitcher ws(window1, window2, 2000);
window1->show();
return a.exec();
}
WindowSwitcher source code:
#include "windowswitcher.h"
#include <QTimer>
WindowSwitcher::WindowSwitcher(QMainWindow *w1, QMainWindow *w2, int delay) : QObject(), window1(w1), window2(w2)
{
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(switchWindow()));
timer->start(delay);
}
void WindowSwitcher::switchWindow()
{
if (window1->isVisible())
{
window1->hide();
window2->show();
}
else
{
window1->show();
window2->hide();
}
}
WindowSwitcher header file:
#include <QObject>
#include <QMainWindow>
class WindowSwitcher : public QObject
{
Q_OBJECT
public:
explicit WindowSwitcher(QMainWindow *w1, QMainWindow *w2, int delay);
private:
QMainWindow *window1;
QMainWindow *window2;
public slots:
void switchWindow();
};

how to force Qt mainWindow to wait for some changes

I am designing UI for my opencv application and I'm new in Qt.
I have a QString in my Qt code that is a licence plate. and it can be change when a car arrive to our camera, but we don't know when it change.
and when car arrive we need to show it's plate on a QTableView on MainWindow.
how can I handle it in Qt?
I make my code simple here:
mainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
.
.
.
public slots:
void set_plate(QString p);
signals:
void plate_changed(QString newPlate);
private:
Ui::MainWindow *ui;
QString plate;
};
mainWindow.cpp
void MainWindow::set_plate(QString newPlate)
{
if(plate != newPlate){
plate = newPlate;
emit plate_changed(newPlate);
}
}
MainWindow::MainWindow(QString p, QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
plate(p)
{
.
.
.
QTableWidgetItem* item2;
item2 = new QTableWidgetItem(plate);
ui->table->setItem(table->rowCount() - 1, 0, item2);
}
main.cpp
int main(int argc, char *argv[])
{
QString plate;
.
.
.
//some changes on plate
QApplication a(argc, argv);
MainWindow w(plate);
w.show();
return a.exec();
}
thanks
When you detect a car, send a signal to your instance. Connect your emitted signal to your slot and that's all.
https://wiki.qt.io/Qt_for_Beginners#Creating_custom_signals_and_slots
Let's begin with a paraphrase of the code for main that you've posted
void someChangesOnPlate(QString &);
int main(int argc, char *argv[])
{
QString plate;
someChangesOnPlate(plate);
QApplication a(argc, argv);
MainWindow w(plate);
w.show();
return a.exec();
}
It seems that someChangesOnPlate would be a plate detection code that runs continuously in a loop, taking images from the camera, detecting plates, and extracting the plate numbers.
The main mistake in your approach is: while the plate detection code is running, the application window isn't shown yet - the code after someChangesOnPlate hasn't executed yet! The execution is within someChangesOnPlate, after all.
What you need to do, instead, is to run someChangesOnPlate in a separate thread, and to have that thread invoke the main window's newPlate method in a thread-safe fashion. Given C++11, this is a very straightforward change:
void someChangesOnPlate(MainWindow *);
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w(plate);
w.show();
std::thread thread(someChangesOnPlate, &w);
int rc = a.exec();
thread.join(); // wait for the thread to finish
return rc;
}
Within the someChangesOnPlate code, the thread-safe call to newPlate is done as follows:
void someChangesOnPlate(MainWindow * w) {
while (...) {
// process camera images
...
QString plate = ....;
...
QMetaObject::invoke(w, "newPlate", Qt::QueuedConnection, Q_ARG(QString, plate));
...
}
}
Finally, I understand that you want a new item to be added to the table whenever a new plate is indicated. Here's how to do it:
class MainWindow : public QMainWindow {
Q_OBJECT
Ui::MainWindow ui; // no need for it to be a pointer
QString m_lastPlate;
public:
MainWindow(QWidget * parent = 0) : QMainWindow(parent) {
ui.setupUi(this);
}
Q_SLOT void newPlate(const QString & plate) {
if (plate == m_lastPlate) return;
m_lastPlate = plate;
auto item = new QTableWidgetItem(plate);
ui->table->setItem(table->rowCount() - 1, 0, item);
}
}

How to finish Qt programm from any place?

My example:
main.cpp:
QApplication a(argc, argv);
MainWindow w;
w.start();
return a.exec();
w.start():
if (cf.exec()){
this->show();
} else {
qDebug()<<"Need exit";
//here should be exit
}
At comment place, I tried to do: qApp->exit() and qApp->quit() and this->close() (but 'this' not shown and of cource close() is not working). How can I finish app from any place of code?
Whole code:
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.start();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "CadrForm.h"
#include "TeacherForm.h"
#include "DepartmentForm.h"
#include "CategoriesForm.h"
#include "PostForm.h"
#include "RanksAndDegreesForm.h"
#include "TeachersRankAndDegreeForm.h"
#include "ConnectionForm.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
void start();
~MainWindow();
signals:
void widgetChanged(QWidget*);
private slots:
void on_actionCadr_triggered();
void resetMainLayout(QWidget* w);
void on_actionTeacher_triggered();
void on_actionDepartment_triggered();
void on_actionPost_triggered();
void on_actionCategories_triggered();
void on_actionRanksAndDegrees_triggered();
void on_actionTeachersRD_triggered();
private:
ConnectionForm cf;
CadrForm *cadrForm;
TeacherForm *teacherForm;
DepartmentForm *departmentForm;
CategoriesForm *categoriesForm;
PostForm *postForm;
RanksAndDegreesForm *ranksAndDegreesForm;
TeachersRankAndDegreeForm *teachersRankAndDegreeForm;
QWidget *current;
Ui::MainWindow *ui;
void addWidgetToMainLayout(QWidget *w);
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
connect(this, SIGNAL(widgetChanged(QWidget*)), this, SLOT(resetMainLayout(QWidget*)));
ui->setupUi(this);
cadrForm = new CadrForm(this);
teacherForm = new TeacherForm(this);
departmentForm = new DepartmentForm(this);
categoriesForm = new CategoriesForm(this);
postForm = new PostForm(this);
ranksAndDegreesForm = new RanksAndDegreesForm(this);
teachersRankAndDegreeForm = new TeachersRankAndDegreeForm(this);
addWidgetToMainLayout(cadrForm);
addWidgetToMainLayout(teacherForm);
addWidgetToMainLayout(departmentForm);
addWidgetToMainLayout(categoriesForm);
addWidgetToMainLayout(postForm);
addWidgetToMainLayout(ranksAndDegreesForm);
addWidgetToMainLayout(teachersRankAndDegreeForm);
}
void MainWindow::start()
{
if (cf.exec()){
this->show();
} else {
qDebug()<<"Need exit";
qApp->quit();
qDebug()<<"still working";
}
}
void MainWindow::addWidgetToMainLayout(QWidget *w)
{
ui->mainLayout->insertWidget(0, w);
ui->mainLayout->itemAt(0)->widget()->hide();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::resetMainLayout(QWidget *w)
{
int index;
if (current)
{
index = ui->mainLayout->indexOf(current);
ui->mainLayout->itemAt(index)->widget()->hide();
}
index = ui->mainLayout->indexOf(w);
if (index != -1) ui->mainLayout->itemAt(index)->widget()->show();
else {
addWidgetToMainLayout(w);
resetMainLayout(w);
}
current = w;
setWindowTitle(current->windowTitle());
}
void MainWindow::on_actionCadr_triggered()
{
emit widgetChanged(cadrForm);
}
void MainWindow::on_actionTeacher_triggered()
{
emit widgetChanged(teacherForm);
}
void MainWindow::on_actionDepartment_triggered()
{
emit widgetChanged(departmentForm);
}
void MainWindow::on_actionPost_triggered()
{
emit widgetChanged(postForm);
}
void MainWindow::on_actionCategories_triggered()
{
emit widgetChanged(categoriesForm);
}
void MainWindow::on_actionRanksAndDegrees_triggered()
{
emit widgetChanged(ranksAndDegreesForm);
}
void MainWindow::on_actionTeachersRD_triggered()
{
emit widgetChanged(teachersRankAndDegreeForm);
}
And ConnectionForm - it's just a QDialog with some GUI and without any additional code.
It looks like the problem is you're not allowed to call QApplication::quit() or QApplication::exit() until the QApplication event loop has actually started. The event loop gets started by QApplication::exec(), so you're calling quit()/exit() too soon for it to have an effect.
You can fix this either by moving the quit()/exit() call so that it's in the event loop (e.g. by moving your MainWindow::start() code to the QMainWindow::showEvent() slot), or by changing your MainWindow::start() to return a value, inspect that value in main, and exit (without calling QApplication::exec()`) if it's a value that indicates your process should exit early.
Since you start the dialog event loop "early" - which is blocking -, you do not get to the event loop of the application.
If this is an intentional design, you better call exit(3) and remove the application event loop.
If you want to have the application event loop running, then you will need to make sure that it runs before you get to the point of your dialog execution.
The quick fix would be to start a single shot QTimer right just before the application event loop is started and that would trigger your "start" method call.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.start();
QTimer::singleShot(200, w, SLOT(start()));
return a.exec();
}
and change the start to a slot, respectively.
In the long run, you may wish to consider a button and so on for bringing your dialog up, however.
The idiomatic way of queuing a method call until the event loop gets a chance to run is:
QMetaObject::invokeMethod(&w, "start", Qt::QueuedConnection);
Thus, your main would become:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
QMetaObject::invokeMethod(&w, "start", Qt::QueuedConnection);
return a.exec();
}

Qt signals/slots do not work [very basic] [duplicate]

This question already has answers here:
C++ Qt signal and slot not firing
(3 answers)
Closed 8 years ago.
I am very new to Qt and it looks like i have some very basic misunderstanding about how this library works. I am currently reading a book by m. Schlee but i do not want to continue until i do understand how to make this simple program work.
#include <QtWidgets>
#include <QApplication>
#include <QStackedWidget>
#include <QPushButton>
#include <QObject>
struct wizard : public QObject
{
QStackedWidget* p;
wizard(QStackedWidget* pp) : p(pp) { }
public slots:
void change()
{
int to = p->currentIndex();
if (to == p->count() - 1)
to = 0;
else
++to;
emit chIndex(to);
}
signals:
void chIndex(int);
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStackedWidget qsw;
QPushButton qpb("magic");
qsw.resize(500, 500);
qsw.move(500, 300);
qsw.setWindowTitle("test qsw");
qpb.move(330, 300);
qpb.setWindowTitle("test qpb");
QWidget* pw1 = new QWidget();
QPalette pal1;
pal1.setColor(pw1->backgroundRole(), Qt::blue);
pw1->setPalette(pal1);
pw1->resize(500, 500);
pw1->setAutoFillBackground(true);
QWidget* pw2 = new QWidget();
QPalette pal2;
pal2.setColor(pw2->backgroundRole(), Qt::yellow);
pw2->setPalette(pal2);
pw2->resize(500, 500);
pw2->setAutoFillBackground(true);
qsw.addWidget(pw1);
qsw.addWidget(pw2);
wizard stupidity(&qsw);
QObject::connect(&qpb, SIGNAL(clicked()), &stupidity, SLOT(change()));
QObject::connect(&stupidity, SIGNAL(chIndex(int)), &qsw, SLOT(setCurrentIndex(int)));
qpb.show();
qsw.show();
return a.exec();
}
The idea is to launch 2 separate windows: one with painted background, and another with button that changes color (blue->yellow->blue->.. etc).
They appear, but nothing happens if i press the button. Please help.
Except for struct being a class and a missing Q_OBJECT macro the code is fine
Try the following:
create a main.h file having this content:
#ifndef MAIN_H
#define MAIN_H
#include <QObject>
#include <QStackedWidget>
class wizard : public QObject
{
Q_OBJECT
public:
QStackedWidget* p;
wizard(QStackedWidget* pp) : p(pp) { }
public slots:
void change()
{
int to = p->currentIndex();
if (to == p->count() - 1)
to = 0;
else
++to;
emit chIndex(to);
}
signals:
void chIndex(int);
};
#endif // MAIN_H
change your main.cpp to the following content:
#include <QtWidgets>
#include <QApplication>
#include <QPushButton>
#include <main.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStackedWidget qsw;
QPushButton qpb("magic");
qsw.resize(500, 500);
qsw.move(500, 300);
qsw.setWindowTitle("test qsw");
qpb.move(330, 300);
qpb.setWindowTitle("test qpb");
QWidget* pw1 = new QWidget();
QPalette pal1;
pal1.setColor(pw1->backgroundRole(), Qt::blue);
pw1->setPalette(pal1);
pw1->resize(500, 500);
pw1->setAutoFillBackground(true);
QWidget* pw2 = new QWidget();
QPalette pal2;
pal2.setColor(pw2->backgroundRole(), Qt::yellow);
pw2->setPalette(pal2);
pw2->resize(500, 500);
pw2->setAutoFillBackground(true);
qsw.addWidget(pw1);
qsw.addWidget(pw2);
wizard stupidity(&qsw);
QObject::connect(&qpb, SIGNAL(clicked()), &stupidity, SLOT(change()));
QObject::connect(&stupidity, SIGNAL(chIndex(int)), &qsw, SLOT(setCurrentIndex(int)));
qpb.show();
qsw.show();
return a.exec();
}
qmake doesn't work very well with Q_OBJECT macro directly in cpp file. Btw. run qmake after changes applied.

Set icon to custom QFontDialog

I created my own font dialog from QFontDialog (new SLOT added). After that, I can't set icon (*.png) to my new font dialog (with func. setWindowIcon). If I use setWindowIcon to default QFontDialog - everything is OK. So, how to set icon to my new font dialog?
FontDialog.h
#include <QtGui>
#include <QtCore>
class FontDialog: public QFontDialog {
public:
FontDialog();
~FontDialog();
public slots:
void someSlot(void);
};
FontDialog.cpp
#include "FontDialog.h"
FontDialog::FontDialog() {
}
FontDialog::~FontDialog() {
}
void someSlot(void) {
}
main.cpp
#include "FontDialog.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
FontDialog *fontDialog = new FontDialog();
fontDialog->setWindowIcon(QIcon(".//icon.png")); // !!!NOT WORKING!!! for custom QFontDialog
fontDialog->show();
app.exec();
}
I'm using Qt 4.8.5 with Qt Designer 2.7.1 environment.
Thanks for any help.
The below works under Qt 4.8.4 on both OS X and Windows 7. It also works on 5.1.1 on Windows, but not on OS X :(
#include <QFontDialog>
#include <QApplication>
#include <QIcon>
#include <QPainter>
class Dialog : public QFontDialog {
public:
Dialog(QWidget *parent = 0) : QFontDialog(parent) {}
Dialog(const QFont & initial, QWidget *parent = 0) : QFontDialog(initial, parent) {}
};
QIcon myIcon(const QColor & color)
{
QIcon icon;
QPixmap pm(128, 128);
pm.fill(Qt::transparent);
QPainter p(&pm);
p.translate(64, 64);
p.scale(50, 50);
p.setBrush(color);
p.setPen(QPen(Qt::lightGray, 0.1));
p.drawEllipse(-1, -1, 2, 2);
icon.addPixmap(pm);
return icon;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setWindowIcon(myIcon(Qt::red));
Dialog d;
d.setWindowIcon(myIcon(Qt::blue));
d.show();
return a.exec();
}