Qt C++ - Aligning QProgressBar inside a QSplashScreen - c++

I am putting a QProgressBar inside a QSplashScreen by subclassing QSplashScreen. It overrides the drawContents() method.
I thought I had set the geometry correctly, but it renders at both the top and bottom of the screen. I don't know why. Perhaps there's another way to align it. The numbers are correct, as the image is 380x284, so a 19 height progress bar should be 265 pixels down.
Sorry for crappy picture, splash screen wasn't showing up with print screen button. It's just a 1 color white splash screen at the moment, but as you can see, progress bar at top and bottom (they're both the same colors, its the lighting from the camera).
http://i.imgur.com/p1LoJ.jpg
Another issue will be the showMessage() method of QSplashScreen. I want the message to appear above the progress bar, right-aligned... if anyone has any ideas how to do that.
splashscreen.cpp
#include "splashscreen.h"
SplashScreen::SplashScreen(QApplication *app, QWidget *parent) :
QSplashScreen(parent)
{
this->app = app;
this->setPixmap(QPixmap(":/images/splashscreen.png"));
this->setCursor(Qt::BusyCursor);
// if I dont make it a child, it *only* renders at the top
progress = new QProgressBar(this);
progress->setGeometry(0, 265, 380, 19); // puts it at bottom
progress->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
progress->setValue(0);
progress->setMaximum(100);
progress->setEnabled(true);
this->showMessage("Hello", Qt::AlignBottom);
connect(progress, SIGNAL(valueChanged(int)), this, SLOT(progressBarUpdated(int)));
}
void SplashScreen::drawContents(QPainter *painter)
{
QSplashScreen::drawContents(painter);
this->progress->render(painter);
}
void SplashScreen::progressBarUpdated(int value)
{
this->repaint();
this->app->processEvents();
}
splashscreen.h
#ifndef SPLASHSCREEN_H
#define SPLASHSCREEN_H
#include <QSplashScreen>
#include <QProgressBar>
#include <QApplication>
class SplashScreen : public QSplashScreen
{
Q_OBJECT
public:
explicit SplashScreen(QApplication *app, QWidget *parent = 0);
QProgressBar *progress;
QWidget *spacer;
QApplication *app;
public slots:
void progressBarUpdated(int value);
protected:
void drawContents(QPainter *painter);
};
#endif // SPLASHSCREEN_H
main.cpp
#include <QtGui/QApplication>
#include <time.h>
#include "splashscreen.h"
#include "mainwindow.h"
int main(int argc, char *argv[])
{
srand(time(0));
QApplication a(argc, argv);
SplashScreen *splash = new SplashScreen(&a);
splash->show();
// snip.. loading a ton of stuff into memory at startup
// if you're testing this you might have to sleep/timer here iono
MainWindow w;
splash->finish(&w);
w.show();
return app.exec();
}

You can paint progress directly, without creating QProgressBar. For example:
sp.h:
#ifndef SPLASHSCREEN_H
#define SPLASHSCREEN_H
#include <QSplashScreen>
#include <QApplication>
class SplashScreen : public QSplashScreen
{
Q_OBJECT
public:
explicit SplashScreen(QApplication *app, QWidget *parent = 0);
int m_progress;
QApplication *app;
public slots:
void setProgress(int value)
{
m_progress = value;
if (m_progress > 100)
m_progress = 100;
if (m_progress < 0)
m_progress = 0;
update();
}
protected:
void drawContents(QPainter *painter);
};
#endif // SPLASHSCREEN_H
sp.cpp
#include "sp.h"
SplashScreen::SplashScreen(QApplication *aApp, QWidget *parent) :
QSplashScreen(parent), app(aApp), m_progress(0)
{
this->setPixmap(QPixmap(":/images/splashscreen.png"));
this->setCursor(Qt::BusyCursor);
this->showMessage("Hello", Qt::AlignBottom);
}
void SplashScreen::drawContents(QPainter *painter)
{
QSplashScreen::drawContents(painter);
// Set style for progressbar...
QStyleOptionProgressBarV2 pbstyle;
pbstyle.initFrom(this);
pbstyle.state = QStyle::State_Enabled;
pbstyle.textVisible = false;
pbstyle.minimum = 0;
pbstyle.maximum = 100;
pbstyle.progress = m_progress;
pbstyle.invertedAppearance = false;
pbstyle.rect = QRect(0, 265, 380, 19); // Where is it.
// Draw it...
style()->drawControl(QStyle::CE_ProgressBar, &pbstyle, painter, this);
}
May be this helps you.

Related

Qt widget takes a long time until it starts to receive mouse events in full screen mode on macOS

In normal screen mode, Qt widgets receive mouse events immediately after creation. In full-screen mode on macOS, however, it takes a while until the widget starts receiving those events. From my tests, it takes ~700ms on average until a widget receives its first mouse event versus ~30ms in normal screen mode. Why does it take so long for mouse events to stream in when using full-screen mode? Is there a way to force Qt to receive those events earlier? See my test in the GIF animation below.
The source code for my test follows below.
/**
* main.cpp
*/
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return QApplication::exec();
}
/**
* mainwindow.h
*/
#pragma once
#include "popupwindow.h"
#include <QWidget>
#include <QPushButton>
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
private slots:
void handleFullScreenButton();
void handleNormalScreenButton();
private:
PopupWindow* m_fullScreenWindow;
QPushButton* m_fullScreenButton;
QPushButton* m_normalScreenButton;
PopupWindow* m_normalScreenWindow;
};
/**
* popupwindow.h
*/
#pragma once
#include <QWidget>
#include <QLabel>
class PopupWindow : public QWidget
{
Q_OBJECT
public:
explicit PopupWindow(QWidget* parent = nullptr);
protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
private:
void showText(const QString &text);
QLabel* m_text;
qint64 m_creationTimestamp;
bool m_eventReceived;
};
/**
* mainwindow.cpp
*/
#include "mainwindow.h"
#include <QDebug>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: m_normalScreenWindow(nullptr)
, m_fullScreenWindow(nullptr)
{
auto *layout = new QVBoxLayout(this);
m_normalScreenButton = new QPushButton("Popup screen");
m_fullScreenButton = new QPushButton("Popup full screen");
connect(m_normalScreenButton, &QPushButton::released, this, &MainWindow::handleNormalScreenButton);
connect(m_fullScreenButton, &QPushButton::released, this, &MainWindow::handleFullScreenButton);
layout->addWidget(m_normalScreenButton);
layout->addWidget(m_fullScreenButton);
}
void MainWindow::handleNormalScreenButton() {
m_normalScreenWindow = new PopupWindow(this);
m_normalScreenWindow->show();
m_normalScreenWindow->activateWindow();
m_normalScreenWindow->raise();
}
void MainWindow::handleFullScreenButton() {
m_fullScreenWindow = new PopupWindow(this);
m_fullScreenWindow->showFullScreen();
m_fullScreenWindow->activateWindow();
m_fullScreenWindow->raise();
}
/**
* popupwindow.cpp
*/
#include "popupwindow.h"
#include <QDateTime>
#include <QDebug>
#include <QHBoxLayout>
PopupWindow::PopupWindow(QWidget *parent)
: m_creationTimestamp(QDateTime::currentMSecsSinceEpoch())
, m_eventReceived(false)
, m_text(nullptr)
{
setAttribute(Qt::WA_DeleteOnClose);
setMouseTracking(true);
}
void PopupWindow::mouseMoveEvent(QMouseEvent *event) {
if (m_eventReceived) {
return;
}
auto deltaTimeMs = QDateTime::currentMSecsSinceEpoch() - m_creationTimestamp;
showText(QString("First mouse event received after %1 ms.").arg(deltaTimeMs));
m_eventReceived = true;
}
void PopupWindow::mousePressEvent(QMouseEvent *event) {
showNormal();
close();
}
void PopupWindow::showText(const QString &text) {
m_text = new QLabel(text);
m_text->setStyleSheet("font: 26pt;");
auto *layout = new QVBoxLayout(this);
layout->addWidget(m_text, Qt::AlignCenter);
}

How to drag the QLabel from one window to another in Qt?

I am learning Qt for fun. And I got a question:
How could I drag and drop the QLabel in Qt among two different windows?
Here is what I have so far:
As you can tell from the .gif(which does not want to become downloaded and visible here for some reasons, but if you click on the link to it, you can clearly see it) provided above right now there are two main problems:
I can not move the QLabel outside of the window (and hence am not able to register the drag and drop event).
The label is flashing for some reasons when I am moving it.
Here is the relevant part of the implementation from the .gif:
#ifndef DRAGGERP_H
#define DRAGGERP_H
#include <QLabel>
#include <QApplication>
#include <QMouseEvent>
#include <QPoint>
class DraggerP : public QLabel
{
QPoint offset;
QPoint startingPosition;
public:
DraggerP(QWidget* parent = nullptr) : QLabel(parent){ }
protected:
void enterEvent(QEvent* event) override
{
QApplication::setOverrideCursor(Qt::PointingHandCursor);
}
void leaveEvent(QEvent* event) override
{
QApplication::restoreOverrideCursor();
}
void mousePressEvent(QMouseEvent* event) override
{
startingPosition = pos();
offset = QPoint(
event->pos().x() - pos().x() + 0.5*width(),
event->pos().y() - pos().y() + 0.5*height()
);
}
void mouseMoveEvent(QMouseEvent* event) override
{
move(event->pos() + offset);
}
void mouseReleaseEvent(QMouseEvent* event) override
{
move(startingPosition);
}
};
#endif // DRAGGERP_H
This is the extension of the QLabel I am using to create the drag and drop effect.
I do not need the whole solution, at least an idea of how to accomplish this and what am I doing wrong here.
Here is a pretty good example and I used it as a starting point.
That strange movement that the QLabel suffers is because the position of the QLabel now depends on the layout, the job of the layout is to establish the position of the widgets depending on the policies you establish.
The solution is not to implement those actions in the QLabel but in the MainWindow as I show below:
#include <QApplication>
#include <QLabel>
#include <QMainWindow>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QTime>
#include <QDrag>
#include <QMimeData>
#include <QMouseEvent>
class MainWindow: public QMainWindow {
QScrollArea scrollArea;
QWidget contentWidget;
QVBoxLayout lay;
public:
MainWindow(QWidget* parent=nullptr): QMainWindow(parent){
qsrand((uint) QTime::currentTime().msec());
setCentralWidget(&scrollArea);
scrollArea.setWidget(&contentWidget);
contentWidget.setLayout(&lay);
scrollArea.setWidgetResizable(true);
for(int i=0; i< 20; i++){
QLabel *label = new QLabel(QString("label %1").arg(i));
QPalette pal = label->palette();
pal.setColor(QPalette::Background, QColor(10 +qrand() % 240, 10 +qrand() % 240, 10 +qrand() % 240));
label->setAutoFillBackground(true);
label->setPalette(pal);
lay.addWidget(label);
}
setAcceptDrops(true);
}
protected:
void mousePressEvent(QMouseEvent *event){
QMainWindow::mousePressEvent(event);
QWidget *child = childAt(event->pos());
if(qobject_cast<QLabel *>(child))
createDrag(event->pos(), child);
}
void dropEvent(QDropEvent *event){
QByteArray byteArray = event->mimeData()->data("Label");
QWidget * widget = *reinterpret_cast<QWidget**>(byteArray.data());
QLabel * new_label = qobject_cast<QLabel *>(widget);
QWidget *current_children = childAt(event->pos());
QLabel * current_label = qobject_cast<QLabel*>(current_children);
int index = 0;
if(new_label){
if(current_label)
index = lay.indexOf(current_label);
else{
index = 0;
QLayoutItem *item = lay.itemAt(index);
while(item->widget()->pos().y() < event->pos().y() && item)
item = lay.itemAt(index++);
}
lay.insertWidget(index, new_label);
}
}
private:
void createDrag(const QPoint &pos, QWidget *widget){
if(widget == Q_NULLPTR)
return;
QByteArray byteArray(reinterpret_cast<char*>(&widget),sizeof(QWidget*));
QDrag *drag = new QDrag(this);
QMimeData * mimeData = new QMimeData;
mimeData->setData("Label",byteArray);
drag->setMimeData(mimeData);
QPoint globalPos = mapToGlobal(pos);
QPoint p = widget->mapFromGlobal(globalPos);
drag->setHotSpot(p);
drag->setPixmap(widget->grab());
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
protected:
void dragEnterEvent(QDragEnterEvent *event){
if(event->mimeData()->hasFormat("Label"))
event->acceptProposedAction();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w1;
MainWindow w2;
w1.show();
w2.show();
return a.exec();
}

Change position of submenus in a QMenu

In my project, I have a QMenu with a submenu item. The submenu has a lot of items so it's height is relatively large.
I want to vertically center the submenu relative to the item that executed the submenu.
I have already subclassed the submenu I want to reposition and tried changing the geometry on "aboutToShow" just to test things, but this has no effect:
class MySubMenu : public QMenu
{
Q_OBJECT
public:
QuickMod();
~QuickMod();
private slots:
void centerMenu();
};
MySubMenu::MySubMenu()
{
connect(this, SIGNAL(aboutToShow()), this, SLOT(centerMenu()));
}
MySubMenu::~MySubMenu()
{
}
void MySubMenu::centerMenu()
{
qDebug() << x() << y() << width() << height();
setGeometry(x(), y()-(height()/2), width(), height());
}
Here is an image I quickly MS Painted that I hope visually explains what I'm trying to achieve: (Before and After)
Thanks for your time!
aboutToShow is emited before the geometry is updated so the changes are overwritten later. The solution is to change the position an instant after they are displayed, for this we can use a QTimer with a small time.
Example:
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QTimer>
class CenterMenu: public QMenu{
Q_OBJECT
public:
CenterMenu(QWidget *parent = Q_NULLPTR):QMenu{parent}{
connect(this, &CenterMenu::aboutToShow, this, &CenterMenu::centerMenu);
}
CenterMenu(const QString &title, QWidget *parent = Q_NULLPTR): QMenu{title, parent}{
connect(this, &CenterMenu::aboutToShow, this, &CenterMenu::centerMenu);
}
private slots:
void centerMenu(){
QTimer::singleShot(0, [this](){
move(pos() + QPoint(0, -height()/2));
});
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow w;
auto fileMenu = new QMenu("Menu1");
w.menuBar()->addMenu(fileMenu);
fileMenu->addAction("action1");
fileMenu->addAction("action2");
auto children_menu = new CenterMenu("children menu");
children_menu->addAction("action1");
children_menu->addAction("action2");
children_menu->addAction("action3");
children_menu->addAction("action4");
children_menu->addAction("action5");
children_menu->addAction("action6");
fileMenu->addMenu(children_menu);
w.show();
return a.exec();
}
#include "main.moc"

Dynamically resizing two QLabel implementations

I'm trying to create a simple frame in Qt with a tick and some text. I made two new label implementations because I wanted the labels to dynamically fill all the available space but when I resize the window the sizes are off, as shown by the qDebug output, which represents the size of the image label:
Resized: 244 , 244 <-- Window first created
Resized: 305 , 305 <-- Window maximized
Resized: 135 , 135 <-- Window restored to original size
As you can see, when the window is restored to its original size the image is not. The last size should be 244, 244.
The code which describes the behaviour of the two widgets is the following:
"widgets.h":
/*
* This file includes many custom widgets.
*/
#ifndef APOCRYPHA_WIDGETS
#define APOCRYPHA_WIDGETS
#include <QWidget>
#include <QLabel>
#include <QTimer>
#include <QPixmap>
#include <QResizeEvent>
#include <QPaintEvent>
class AutoTextLabel : public QLabel {
Q_OBJECT
public:
explicit AutoTextLabel(QWidget* parent);
AutoTextLabel(QWidget* parent, QString text);
protected:
void resizeEvent(QResizeEvent* event) override;
private:
QTimer* resizeTimer;
private slots:
void onResizeEnd();
};
class AutoImageLabel : public QLabel {
Q_OBJECT
public:
explicit AutoImageLabel(QWidget* parent);
AutoImageLabel(QWidget* parent, const QPixmap& pixmap);
void setFillOrientation(int orientation);
QSize sizeHint() const override;
public slots:
void setPixmap(const QPixmap &newPix);
void resizeEvent(QResizeEvent* event) override;
protected:
// void paintEvent(QPaintEvent* event) override;
private:
int fillOrientation;
int widthForHeight(int h) const;
int heightForWidth(int w) const override;
QPixmap scaledPixmap() const;
QPixmap labelPixmap;
};
#endif //APOCRYPHA_WIDGETS
"widgets.cpp":
/*
* This file includes many custom widgets.
*/
#include "widgets.h"
#include <QPainter>
#include <QDebug>
AutoTextLabel::AutoTextLabel(QWidget *parent, QString text) : QLabel(text, parent){
// Enable antialiasing
QFont aaFont(font());
aaFont.setStyleStrategy(QFont::PreferAntialias);
setFont(aaFont);
// This timer is used to fire a slot when a window is resized
resizeTimer = new QTimer();
resizeTimer->setSingleShot(true);
connect(resizeTimer, SIGNAL(timeout()), SLOT(onResizeEnd()));
}
AutoTextLabel::AutoTextLabel(QWidget *parent) : AutoTextLabel(parent, "") {}
void AutoTextLabel::resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
// Only fire when 25ms have passed since the last resize.
resizeTimer->start(25);
}
void AutoTextLabel::onResizeEnd() {
QFont updatedFont(font());
// Resize Text
if (!text().isEmpty()){
int fontSize = 1;
updatedFont.setPixelSize(fontSize);
QRect boundingRectangle;
// Update bounding rectangle
if (wordWrap())
boundingRectangle = QFontMetrics(updatedFont).boundingRect(contentsRect(), Qt::TextWordWrap, text());
else
boundingRectangle = QFontMetrics(updatedFont).boundingRect(text());
while (boundingRectangle.height() <= contentsRect().height()) {
fontSize++;
updatedFont.setPixelSize(fontSize);
// Update bounding rectangle
if (wordWrap())
boundingRectangle = QFontMetrics(updatedFont).boundingRect(contentsRect(), Qt::TextWordWrap, text());
else
boundingRectangle = QFontMetrics(updatedFont).boundingRect(text());
}
updatedFont.setPixelSize(fontSize - 1);
setFont(updatedFont);
}
}
/* Auto Image Label */
AutoImageLabel::AutoImageLabel(QWidget *parent, const QPixmap &pixmap) : QLabel(parent) {
setMinimumSize(1, 1);
setScaledContents(false);
setPixmap(pixmap);
}
AutoImageLabel::AutoImageLabel(QWidget *parent) : QLabel(parent) {
setScaledContents(false);
}
void AutoImageLabel::resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
if(!labelPixmap.isNull())
QLabel::setPixmap(scaledPixmap());
qDebug() << "Resized: " << scaledPixmap().width() << ", " << scaledPixmap().height();
}
int AutoImageLabel::widthForHeight(int h) const {
return labelPixmap.isNull() ? width() : (labelPixmap.width() * h) / labelPixmap.height();
}
int AutoImageLabel::heightForWidth(int w) const {
return labelPixmap.isNull() ? height() : (labelPixmap.height() * w) / labelPixmap.width();
}
void AutoImageLabel::setFillOrientation(int orientation) {
this->fillOrientation = orientation;
}
QSize AutoImageLabel::sizeHint() const {
if (fillOrientation == Qt::Horizontal)
return QSize(width(), heightForWidth(width()));
else
return QSize(widthForHeight(height()), height());
}
QPixmap AutoImageLabel::scaledPixmap() const {
return labelPixmap.scaled(sizeHint(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
void AutoImageLabel::setPixmap(const QPixmap &newPix) {
labelPixmap = newPix;
QLabel::setPixmap(scaledPixmap());
}
"other_frames.h":
//
// Created by Riccardo on 18/09/2017.
//
#ifndef APOCRYPHA_OTHER_FRAMES_H
#define APOCRYPHA_OTHER_FRAMES_H
#include <QFrame>
#include <QLabel>
#include <QGridLayout>
#include <QWidget>
#include <QResizeEvent>
#include <QPixmap>
#include <QTimer>
#include "widgets.h"
class ConfirmationFrame : public QFrame {
Q_OBJECT
public:
explicit ConfirmationFrame(QWidget* parent);
ConfirmationFrame(QWidget* parent, const QString& text);
private:
QGridLayout* layout;
AutoImageLabel* imageLabel;
AutoTextLabel* textLabel;
};
#endif //APOCRYPHA_OTHER_FRAMES_H
"other_frames.cpp":
//
// Created by Riccardo on 18/09/2017.
//
#include "other_frames.h"
#include <QDebug>
ConfirmationFrame::ConfirmationFrame(QWidget* parent, const QString &text) : QFrame(parent) {
textLabel = new AutoTextLabel(this, text);
QPixmap pix(":/images/check-tick.png");
imageLabel = new AutoImageLabel(this, pix);
textLabel->setAlignment(Qt::AlignCenter);
imageLabel->setAlignment(Qt::AlignCenter);
textLabel->setWordWrap(true);
// Green Background
setStyleSheet("background-color: rgba(106, 242, 94, 1);");
layout = new QGridLayout();
layout->setSpacing(0);
layout->setContentsMargins(32, 32, 32, 32);
layout->setRowStretch(0, 1);
layout->setRowStretch(1, 1);
layout->addWidget(imageLabel, 0, 1);
layout->addWidget(textLabel, 1, 1);
setLayout(layout);
}
ConfirmationFrame::ConfirmationFrame(QWidget *parent) : ConfirmationFrame(parent, "") {
}
"window_main.h":
#ifndef WINDOW_MAIN_H
#define WINDOW_MAIN_H
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QGridLayout>
#include <QFrame>
#include <QScreen>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
QFrame *mainFrame;
void center(QScreen* screen);
void autoSetSize(QScreen* screen);
private:
void createMenu();
// Components
QGridLayout *mainLayout;
QMenuBar *menuBar;
QMenu *fileMenu;
};
#endif // WINDOW_MAIN
"window_main.cpp":
#include "window_main.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
mainFrame = new QFrame();
mainLayout = new QGridLayout();
mainLayout->setSpacing(0);
mainLayout->setContentsMargins(0, 0, 0, 0);
createMenu();
mainFrame->setStyleSheet("background-color: red;");
mainFrame->setLayout(mainLayout);
setCentralWidget(mainFrame);
}
void MainWindow::createMenu(){
menuBar = new QMenuBar;
fileMenu = new QMenu(tr("&File"), this);
menuBar->addMenu(fileMenu);
setMenuBar(menuBar);
}
void MainWindow::center(QScreen *screen) {
QSize size = screen->availableSize();
int x = size.width() / 2 - width() / 2;
int y = size.height() / 2 - height() / 2;
move(x, y);
}
void MainWindow::autoSetSize(QScreen *screen) {
QSize screenSize = screen->availableSize();
// TODO Math.round
setMinimumSize(QSize((int)(screenSize.width() / 1.25), (int)(screenSize.height() / 1.25)));
}
"main.cpp":
#include <QApplication>
#include <iostream>
#include <QFile>
#include "quiz/choice.h"
#include "quiz/question.h"
#include "quiz/quizmaker.h"
#include <QSettings>
#include <QStandardPaths>
#include <QDebug>
#include <src/user_interface/other_frames.h>
#include "user_interface/window_main.h"
#include <QScreen>
#include <QFontDatabase>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
// Set Application Parameters
QCoreApplication::setOrganizationName("Riccardo Fagiolo");
QCoreApplication::setOrganizationDomain("kopharex.me");
QCoreApplication::setApplicationName("Apocrypha");
// Set application font
const int id = QFontDatabase::addApplicationFont(":/fonts/montserrat/Montserrat-Regular.otf");
QString family = QFontDatabase::applicationFontFamilies(id).at(0);
QFont font(family);
font.setStyleStrategy(QFont::PreferAntialias);
a.setFont(font);
// App Settings
QSettings settings;
settings.setValue("data_dir", QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
// Create UI
auto* window = new MainWindow();
ConfirmationFrame* cframe = new ConfirmationFrame(window, "But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?");
window->mainFrame->layout()->addWidget(cframe);
window->autoSetSize(a.primaryScreen());
//cframe->updateTextLabel();
window->show();
window->center(a.primaryScreen());
// [...] - Nothing related to user interface.
return a.exec();
}
Here is a screenshot of the current MainWindow and ConfirmationFrame to give you an idea of what i'm trying to accomplish:
Window Screenshot
All comments regarding the code are welcome.
Thanks for any help,
Riccardo
Hello I tried to fix the resizing issue with an hack.
Before starting the timer to resize the text, just reduce its font to a 1 pixel font:
void AutoTextLabel::resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
// set a very small font, then start the timer
QFont updatedFont(font());
updatedFont.setPixelSize(1);
setFont(updatedFont);
// Only fire when 25ms have passed since the last resize.
resizeTimer->start(25);
}
Can the effect be acceptable in your opinion?

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.