in Qt Gui how to make a button randomly appear every click - c++

Alright so is there any way to make this program randomly change the variables x and y every time the button is clicked i am new to programming...
#include <QtGui/QApplication>
#include "mainwindow.h"
#include <QtGUI>
#include <QWidget>
#include <cstdlib>
#include <ctime>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *window = new QWidget;
srand(time(0));
int x = 1+(rand()%900);
int y = 1+(rand()%400);
QPushButton *MainInter = new QPushButton("Push me!",window);
QPropertyAnimation *animation = new QPropertyAnimation(MainInter, "pos");
animation->setDuration(0);
animation->setEndValue(QPoint(x,y));
Object::connect(MainInter,SIGNAL(released()),animation,SLOT(start()));
window->resize(900,500);
window->show();
return a.exec();
}

What you can do is, instead of connecting the released() signal of your button directly to your animations start() SLOT, you would create your own custom SLOT. Then you connect the button to it, handle the action, and call the animation.
First read up on how to create a custom QWidget, instead of creating top level object in your main(). Simple example here
A custom widget might look like this:
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class QPushButton;
class QPropertyAnimation;
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget *parent = 0);
private:
QPushButton *button;
QPropertyAnimation *animation;
public slots:
void randomizeAnim();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QPushButton>
#include <QPropertyAnimation>
#include <ctime>
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent)
{
button = new QPushButton("Push me!", this);
animation = new QPropertyAnimation(button, "pos");
animation->setDuration(0);
QObject::connect(button, SIGNAL(released()), this, SLOT(randomizeAnim()));
}
void MyWidget::randomizeAnim()
{
srand(time(0));
int x = 1+(rand()%900);
int y = 1+(rand()%400);
animation->setEndValue(QPoint(x,y));
animation->start();
}
And now your main.cpp can be reduced to the boilerplate code:
#include <QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *window = new MyWidget;
window->resize(900,500);
window->show();
return a.exec();
}
Every time you click, your custom slot will handle the action and do the animation.

Related

Qt calling close() closes the MainWindow instead of the dialog window

In my sample application, the MainWindow closes instead of the dialog window. Why is that and how do I change it?
I've tried setQuitOnLastWindowClosed() but it didn't have any effect.
When clicking the x in the top right corner, the dialog window closes and the MainWindow remains open as expected. But that's of course not what I want.
MainWindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDialog>
#include <QWidget>
#include <QPushButton>
#include <QHBoxLayout>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
void on_mainWindowBtn();
void on_closeBtn();
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
};
#endif // MAINWINDOW_H
MainWindow.cpp:
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *mainWindowWidget = new QWidget(this);
QHBoxLayout *mainWindowHBox = new QHBoxLayout();
QPushButton *mainWindowPushButton = new QPushButton();
mainWindowPushButton->setText("Open Dialog Window");
mainWindowHBox->addWidget(mainWindowPushButton);
mainWindowWidget->setLayout(mainWindowHBox);
this->setCentralWidget(mainWindowWidget);
connect(mainWindowPushButton, &QPushButton::released, this, &MainWindow::on_mainWindowBtn);
}
void MainWindow::on_mainWindowBtn()
{
QDialog *newDialog = new QDialog();
QHBoxLayout *newHBox = new QHBoxLayout();
QPushButton *closeBtn = new QPushButton();
closeBtn->setText("Close Dialog Window");
newHBox->addWidget(closeBtn);
newDialog->setLayout(newHBox);
newDialog->setModal(true);
connect(closeBtn, &QPushButton::released, this, &MainWindow::on_closeBtn);
newDialog->exec();
}
void MainWindow::on_closeBtn()
{
close(); // closes the MainWindow but not the dialog window
}
MainWindow::~MainWindow()
{
}
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
MainWindow w;
w.show();
return a.exec();
}

QT - connecting wrong button from member QWidget

I have a main window which opens a new window and connects a button from the new window to a "close" function. The problem arises when that new window has more than one button; it will always connect the last created button instead of the explicited one. Here is a sample working code:
"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 "screen_char_info.h"
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
QPushButton *button_show_char_info;
Screen_Char_Info *screen_char_info;
QWidget *mainwidget;
QVBoxLayout *layout_main;
MainWindow(QWidget *parent = 0) : QMainWindow(parent) {
button_show_char_info = new QPushButton("Character info", this);
layout_main = new QVBoxLayout();
mainwidget = new QWidget(this);
screen_char_info = NULL;
QObject::connect (button_show_char_info, &QPushButton::clicked, [this]{
if (screen_char_info == NULL) {
screen_char_info = new Screen_Char_Info();
screen_char_info->show();
QObject::connect (screen_char_info->button_return, &QPushButton::clicked, [=] {
screen_char_info->close();
screen_char_info = NULL;
});
}
});
layout_main->addWidget(button_show_char_info);
mainwidget->setLayout(layout_main);
setCentralWidget(mainwidget);
}
~MainWindow()
{
}
};
#endif // MAINWINDOW_H
"screen_char_info.h"
#ifndef SCREEN_CHAR_INFO_H
#define SCREEN_CHAR_INFO_H
#include <QString>
#include <QMenu>
#include <QMenuBar>
#include <QLabel>
#include <QTextEdit>
#include <QPushButton>
#include <QWidget>
#include <QLineEdit>
#include <QGridLayout>
class Screen_Char_Info : public QWidget {
Q_OBJECT
public:
QPushButton *buttons_modify_attributes[15];
QPushButton *button_return;
QGridLayout *layout;
Screen_Char_Info () {
this->setAttribute(Qt::WA_DeleteOnClose);
this->setWindowTitle("Character Info");
layout = new QGridLayout(this);
for (int i = 0; i <= 15; i++) {
buttons_modify_attributes[i] = new QPushButton((i%2 ? "-" : "+"), this);
connect(buttons_modify_attributes[i], &QPushButton::clicked, [this] {
});
layout->addWidget(buttons_modify_attributes[i], (i / 2), (i % 2), 1, 1);
}
layout->addWidget(button_return = new QPushButton("Return", this), 8, 0, 1, 1);
this->setLayout(layout);
}
};
#endif // SCREEN_CHAR_INFO_H
However, if i put the line layout->addWidget(button_return... before the for loop, the button that closes the window is the last "-" button, and not the return one.
The way you do the connect does not appear to be conventional. Try using traditional Qt way:
connect(pButtonToPress, SIGNAL(clicked()), pObjectToHandle, SLOT(onClicked));
Provided QPushButton* pButtonPress actually pointing to QPushButton and pObjectToHandle to some object (can be 'this' pointer):
class ObjHandler
{
public slot:
void onClicked();
};
... should satisfy. SIGNAL and SLOT are macro that work with some help of Qt meta object compiler. That is why having slot: statement is highly critical.
Found the bug, I was declaring a button matrix with 15 elements, but iterating over a 16 element loop. The 16th element was the return button, and was overwritten in the loop.

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.

execution of custom qdialog

I am getting an error while trying to run this Application ... the error message is:
main.cpp(11): error: expression must have class type
int r = dialog.exec(); and I am not sure why!!!
I am using qmake to generate the make file... I have added the necessary files to the *.pro file since Dialog is inherited from QDialog I should have access to the function exec!
#include <QtGui>
#include <QDialog>
#include <QtUtil.h>
#include <Mathematics.h>
#include <Pair.h>
#include "View.h"
class QMesseageBox;
class QAction;
class QDialogButtonBox;
class QLabel;
class QLineEdit;
class QPushButton;
class QTextEdit;
class Dialog : public QDialog {
Q_OBJECT
public:
Dialog() {
QHBoxLayout *layout = new QHBoxLayout;
// prevent left vertical box from growing when main window resized
layout->addStretch(1);
QLabel* lab_Layers = new QLabel(tr("Layers"));
d_inline = new QLineEdit;
d_inline->setText("50");
scene = new QGraphicsScene(0, 0, 500, 500);
view = new View;
layout->addWidget(view);
view->setScene(scene);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(layout);
setLayout(mainLayout);
setWindowTitle(tr("VI Smooth 0.4"));
}
private slots:
// scroll the "after" window when "before" one is scrolled (so they
// remain in sync)
private:
QAction* exitAction;
QtUtil qt;
QLineEdit* d_inline;
QGraphicsScene* scene;
QGraphicsView* view;
};
main class
#include <QApplication>
#include <QMessageBox>
#include "Dialog.h"
int
main(int argc, char **argv) {
QApplication app(argc, argv);
argv++;
Dialog dialog();
// dialog.showMaximized();
int r = dialog.exec();
return 0;
}
It should look something like this. If you create a Dialog object, you need to call show(). And you also need to return app.exec() in main().
#include <QApplication>
#include <QMessageBox>
#include "Dialog.h"
int
main(int argc, char **argv) {
QApplication app(argc, argv);
argv++;
Dialog dialog;
dialog.show()
return app.exec(argc, argv);
}

Global menu in Qt with QtMenuBar

I'm new to C++ and Qt, and I'm having a bit of trouble getting off the ground. I'd really appreciate some help. I want to add a menubar that will remain constant for all app screens. If I add this to the main function, the menubar shows up fine, but I know this shouldn't be in my main function:
#include <QtGui/QApplication>
#include "mainwindow.h"
#include "form.h"
#include "menu.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
QMenuBar *menu = new QMenuBar(0);
QMenu* menu1 = new QMenu("MENU1");
menu1->addMenu(new QMenu("menu1_SubMenu"));
QMenu* menu2 = new QMenu("MENU2");
menu2->addMenu(new QMenu("menu2_SubMenu"));
menu->addMenu(menu1);
menu->addMenu(menu2);
w.show();
return a.exec();
}
If I create a class for the menu bar, it does not appear. The only difference is that I've put the menu code in the constructor of the menu class and then instantiated the menu class from main.cpp:
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
#include "form.h"
#include "menu.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
Menu m;
m.show();
w.show();
return a.exec();
}
menu.h
#ifndef MENU_H
#define MENU_H
#include <QMenuBar>
class Menu : public QMenuBar
{
Q_OBJECT
public:
Menu(QMenuBar *parent = 0);
};
#endif // MENU_H
menu.cpp
#include "menu.h"
Menu::Menu(QMenuBar *parent)
{
QMenuBar *menu = new QMenuBar(0);
QMenu* menu1 = new QMenu("MENU1");
menu1->addMenu(new QMenu("menu1_SubMenu"));
QMenu* menu2 = new QMenu("MENU2");
menu2->addMenu(new QMenu("menu2_SubMenu"));
menu->addMenu(menu1);
menu->addMenu(menu2);
}
What am I doing wrong?
Your Menu class is derived from QMenuBar, but you don't call any methods on it except show(). All addMenu() calls are made for the local variable menu in the constructor, which are allocated and then forgotten. You should call them on this instead:
#include "menu.h"
Menu::Menu(QMenuBar *parent)
{
QMenu* menu1 = new QMenu("MENU1");
menu1->addMenu(new QMenu("menu1_SubMenu"));
QMenu* menu2 = new QMenu("MENU2");
menu2->addMenu(new QMenu("menu2_SubMenu"));
this->addMenu(menu1);
this->addMenu(menu2);
}