How to rotate the second hand of the clock with Qt - c++

I am using the code below to try to rotate the pointer simulating the second hand of the clock, but when he turns it cuts, the square of the background is fixed and it seems I'm not able to rotate all:
QPixmap shipPixels(":/new/prefix1/imagem/ponteiro.png");
QPixmap rotatePixmap(shipPixels.size());
rotatePixmap.fill(Qt::transparent);
QPainter p(&rotatePixmap);
p.translate(rotatePixmap.size().width() / 2, rotatePixmap.size().height() / 2);
p.rotate(90);
p.translate(-rotatePixmap.size().width() / 2, -rotatePixmap.size().height() / 2);
p.drawPixmap(0, 0, shipPixels);
p.end();
shipPixels = rotatePixmap;
ui->label->setPixmap(rotatePixmap);
The pointer looks like this:
Now with it rotated 90 ยบ

Qt Analog Clock example:
http://qt-project.org/doc/qt-5/qtwidgets-widgets-analogclock-example.html
Maybe before rotating QPixmaps, try drawing a line. After the line is in place and drawing correctly work backwards from there.
UPDATE:
Some sample code for rotating images.
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPaintEvent>
#include <QPixmap>
#include <QTime>
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
signals:
public slots:
void paintEvent(QPaintEvent *);
private:
QPixmap bg;
QPixmap second_hand;
QTime time;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QPainter>
#include <QTimer>
#include <QTime>
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
time.restart();
this->resize(256, 256);
// both images are 256x256 in this example
bg.load("./images/bg.png");
second_hand.load("./images/second_hand.png");
QTimer * t = new QTimer;
t->setSingleShot(false);
t->setInterval(15);
QObject::connect(t,SIGNAL(timeout()), this, SLOT(update()));
t->start();
}
void Widget::paintEvent(QPaintEvent * e)
{
QPainter p(this);
p.drawPixmap(QPoint(0,0),bg);
qreal seconds = ((qreal)(time.elapsed() % 60000))/1000;
p.translate(this->width()/2, this->height()/2);
p.rotate(seconds/60*360);
p.drawPixmap(QPoint(-this->width()/2, -this->height()/2),second_hand);
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
Hope that helps.

Related

Fix the Qt application orientation to landscape

Developing a tablet based qt application in windows platform. As per our requirement need to fix the application to landscape mode but not able to fix that. We were using QMainWindow.
Referred few links to fix the issue but didn't worked.
Reference1 , Reference2 : Tried by overriding functions.
Reference3 : Also tried this in our qt application, but not worked.
Below code is our sample code:
mainwindow.h
#include <QMainWindow>
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
int heightForWidth(int w) const;
QSize sizeHint() const;
private:
Ui::MainWindow *ui;
};
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QVBoxLayout>
#include <QDebug>
#include "windows.h"
#include "qt_windows.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// typedef BOOL (WINAPI* SETAUTOROTATION)(BOOL bEnable);
// SETAUTOROTATION SetAutoRotation = (SETAUTOROTATION)GetProcAddress(GetModuleHandle(TEXT("user32.dll")),
// (LPCSTR)2507);
// if (SetAutoRotation != nullptr)
// {
// qDebug() << "bEnable: " << SetAutoRotation;
// SetAutoRotation(FALSE);
// }
// qDebug() << "bEnable: " << SetAutoRotation;
MainWindow w;
w.showMaximized();
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "windows.h"
#include "qt_windows.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
QSizePolicy currPolicy = this->sizePolicy();
currPolicy.setHeightForWidth(true);
this->setSizePolicy(currPolicy);
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
int MainWindow::heightForWidth(int w) const
{
return (w * 240 )/320;
}
QSize MainWindow::sizeHint() const
{
int w = 1366;
return QSize(w, heightForWidth(w) );
}
Can anyone help me on fixing this. Please let me know if am doing anything wrong in above code.
Had the same problem and unfortunately, the best solution was just to disable rotation in Windows settings. I doubt there is a reasonable way to do that from application but i'am not 100% sure.
Only other solution i found was to draw your view according to Windows rotation (so the view would be drawn rotated).
Here is how to read Windows current rotation.

QMdiArea is returning the wrong height and width

I am trying to arrange my subWindows in the QMdiArea vertically. I saw lot of examples online and they all were doing the same thing as I am doing here.
I have two textEdits which needs to be tiled vertically both covering half of the screen. So in the constructor of the MainWindow I add the two textEdits as subWindow to the qMdiArea and then find the height and width of the qMdiArea divide the height by 2 and resize the subWindow. Please see the code below.
My mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->showMaximized();
qMdiArea = new QMdiArea();
qTextEdit1 = new QTextEdit();
qTextEdit2 = new QTextEdit();
setCentralWidget(qMdiArea);
qMdiArea->adjustSize();
qMdiArea->addSubWindow(qTextEdit1);
qMdiArea->addSubWindow(qTextEdit2);
QPoint position(0, 0);
foreach (QMdiSubWindow *window, qMdiArea->subWindowList())
{
QRect rect(0, 0, qMdiArea->width(), qMdiArea->height() / qMdiArea->subWindowList().count());
window->setGeometry(rect);
window->move(position);
position.setY(position.y() + window->height());
}
}
MainWindow::~MainWindow()
{
delete ui;
}
My window.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMdiArea>
#include <QTextEdit>
#include <QPoint>
#include <QMdiSubWindow>
#include <QRect>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QMdiArea *qMdiArea;
QTextEdit *qTextEdit1;
QTextEdit *qTextEdit2;
};
#endif // MAINWINDOW_H
and my Main File :
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
But its not happening as expected. The window just occupy a part of the screen though they are tiled vertically. My screen resolution is 1920x1200
The height() and width() of mdiArea are invalid at that stage, because the widget hasn't been exposed/shown yet. Calling show() only schedules a widget for display, the act of sizing it and showing it on screen happens later when the control has returned to the event loop.
As a solution, you can override the resizeEvent handler. Once you do, your project will work again:
Definition in mainwindow.h:
virtual void resizeEvent(QResizeEvent *ev) override;
Implementation in mainwindow.cpp:
void MainWindow::resizeEvent(QResizeEvent *ev)
{
Q_UNUSED(ev)
QPoint position(0, 0);
foreach (QMdiSubWindow *window, qMdiArea->subWindowList())
{
QRect rect(0, 0, qMdiArea->contentsRect().width(), qMdiArea->contentsRect().height() / qMdiArea->subWindowList().count());
window->setGeometry(rect);
window->move(position);
position.setY(position.y() + window->height());
}
}
Also it seems that you don't really need to have this->showMaximized(); call inside MainWindow's constructor. You can call it from main.cpp, for example.

Ball bounce off the walls in C++ using Qt

I'm trying to create a simple animation of a ball that is wandering on a screen and simply bounces off on walls. Since I'm fairly new to C++, I've got some problems with this task. I'm also using the Qt-library.
The ball just stays on the same spot and moves back and forth a little which is odd, because I create a SceneRect with the same size as my graphicsView.
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGraphicsScene>
#include <QtWidgets>
float movement_x = 2.5;
float movement_y = 2.0;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::showEvent(QShowEvent *event){
scene = new QGraphicsScene(this);
scene -> setSceneRect(ui->graphicsView->geometry().x(), ui->graphicsView->geometry().y(),
ui->graphicsView->geometry().width(), ui->graphicsView->geometry().height());
ui->graphicsView->setScene(scene);
QPen redpen(Qt::red);
QBrush brush(Qt::green);
//QBrush brush2(Qt::black);
QPen mypen(Qt::blue);
mypen.setWidth(7);
ellipse = scene->addEllipse(100.0,100.0,20.0,20.0,mypen,brush);
timer1 = startTimer(50);
timer2 = startTimer(600);
}
void MainWindow::timerEvent(QTimerEvent *event){
// check for radius
if(ellipse->pos().x() >= scene->sceneRect().right() || ellipse->pos().x() <= scene->sceneRect().left()){
movement_x = -movement_x;
}
if(ellipse->pos().y() >= scene->sceneRect().bottom() || ellipse->pos().y() <= scene->sceneRect().top()){
movement_y = -movement_y;
}
ellipse->moveBy(movement_x, movement_y);
}
MainWindow::~MainWindow()
{
delete ui;
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QGraphicsScene>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void showEvent(QShowEvent* event);
void timerEvent(QTimerEvent* event);
private:
Ui::MainWindow *ui;
QGraphicsScene *scene;
QGraphicsEllipseItem *ellipse;
};
#endif // MAINWINDOW_H
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.resize(800,600);
w.show();
return a.exec();
}
The initial value of pos is (0,0). Because of this your update oscillate between two values. After addEllipse you have to set an initial position within the scene rect. For example
ellipse->setPos(100,100);
You should map the ellipse position from the scene to find the boundaries :
QPoint posOfEclps = ellipse->mapToScene(ellipse->pos());
if(posOfEclps.x() >= scene->sceneRect().right() || posOfEclps.x() <= scene->sceneRect().left())
{
movement_x = -movement_x;
}
if(posOfEclps.y() >= scene->sceneRect().bottom() || posOfEclps.y() <= scene->sceneRect().top())
{
movement_y = -movement_y;
}
ellipse->moveBy(movement_x, movement_y);

Fastest code changing pixels in Qt for animation

I want to animate small (100x20) image by changing the color of its pixels by the same value. For example, increase red-channel value by 1 every frame and then decrease back. The image has alpha channel, the animation speed is 30...100 fps (platform dependent; 30 is enough for linux, but windows requires ~70 to look smooth).
As i know, drawing is faster when done in QImage, but displaying is faster with QPixmap.
I like QGraphicsEffects, and QPropertyAnimations. White doesn't colorize, but black does.
#include <QLabel>
#include <QPixmap>
#include <QGraphicsColorizeEffect>
#include <QTimerEvent>
#include <QPropertyAnimation>
#include <QShowEvent>
#include <QDebug>
class Widget : public QLabel
{
Q_OBJECT
Q_PROPERTY(qreal redness READ getRedness WRITE setRedness)
public:
Widget(QWidget *parent = 0)
{
QPixmap p(300, 300);
p.fill(Qt::black);
this->setPixmap(p);
colorize = new QGraphicsColorizeEffect();
colorize->setColor(Qt::red);
redness = 0;
colorize->setStrength(redness);
this->setGraphicsEffect(colorize);
animation = new QPropertyAnimation(this,"redness");
animation->setDuration(2000);
animation->setLoopCount(10);
animation->setStartValue(0.0);
animation->setEndValue(1.0);
animation->setEasingCurve(QEasingCurve::CosineCurve);
animation->start();
}
~Widget(){}
qreal getRedness()
{
return redness;
}
void setRedness(qreal val)
{
redness = val;
colorize->setStrength(redness);
this->update();
// qDebug() << redness;
}
public slots:
void showEvent(QShowEvent *)
{
animation->start();
}
private:
qreal redness;
QGraphicsColorizeEffect * colorize;
QPropertyAnimation * animation;
};
and here is the main.cpp
#include <QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
Hope that helps.

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

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.