Animation on qwidget is not working - c++

I want a widget to animate its opacity when it is shown/hidden. I used the below code, but it does not work.
If I animate the property "maximumHeight", it gets animated in show(), but not in hide(). Could someone tell me where I am going wrong?
Header file
byeform.h
#include <QWidget>
#include <QPropertyAnimation>
namespace Ui {
class ByeForm;
}
class ByeForm : public QWidget
{
Q_OBJECT
public:
explicit ByeForm(QWidget *parent = 0);
~ByeForm();
private:
Ui::ByeForm *ui;
QPropertyAnimation *mpTransition;
protected:
bool eventFilter(QObject *obj, QEvent *event);
};
Source file
byeform.cpp
#include "byeform.h"
#include "ui_byeform.h"
#include <QDebug>
ByeForm::ByeForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::ByeForm)
{
ui->setupUi(this);
this->installEventFilter(this);
mpTransition = new QPropertyAnimation(this, "windowOpacity");
mpTransition->setDuration(1000);
mpTransition->setStartValue(0.00);
mpTransition->setEndValue(1.00);
}
ByeForm::~ByeForm()
{
delete ui;
}
bool ByeForm::eventFilter(QObject *obj, QEvent *event)
{
if (this == obj && QEvent::Show == event->type())
{
qDebug() << Q_FUNC_INFO << "in show";
mpTransition->setDirection(QAbstractAnimation::Forward);
mpTransition->start();
}
else if (this == obj && (QEvent::Hide == event->type() ||
QEvent::Close == event->type()))
{
mpTransition->setDirection(QAbstractAnimation::Backward);
mpTransition->start();
}
return false;
}

Does this fix it?
bool ByeForm::eventFilter(QObject *obj, QEvent *event)
{
if (this == obj && QEvent::Show == event->type())
{
qDebug() << Q_FUNC_INFO << "in show";
mpTransition->setDirection(QAbstractAnimation::Forward);
mpTransition->start();
return true; // you might want to remove this line
}
else if (this == obj && (QEvent::Hide == event->type() ||
QEvent::Close == event->type()))
{
mpTransition->setDirection(QAbstractAnimation::Backward);
mpTransition->start();
return true; // you might want to remove this line
}
return QWidget::eventFilter(obj, event);
}
Ofcourse, it doesn't work because it's already hidden when you start the animation. You need to prolong the visibility until your animation has finished.
Like this, maybe:
void ByeForm::setVisible(bool visible)
{
if(isVisible() && !visible) // transition to hide
{
// m_bHideCalled = true;
mpTransition->setDirection(QAbstractAnimation::Backward);
mpTransition->start();
QTimer::singleShot(1000, this, SLOT(hide());
}
if(!isVisible() && visible) // transition to show
{
mpTransition->setDirection(QAbstractAnimation::Forward);
mpTransition->start();
show();
}
// if(m_bHideCalled)
// {
// m_bHideCalled = false;
// hide();
// }
}
Note that you MIGHT need the m_bHideCalled. Set it to false in the constructor. The name could be better though.

It works, but I think that it not good way to do this (I think that you should be do animate before close event will coming)
bool ByeForm::eventFilter(QObject *obj, QEvent *event)
{
if (this == obj && QEvent::Show == event->type())
{
qDebug() << Q_FUNC_INFO << "in show";
mpTransition->setDirection(QAbstractAnimation::Forward);
mpTransition->start();
}
else if (this == obj && (QEvent::Hide == event->type() ||
QEvent::Close == event->type()))
{
mpTransition->setDirection(QAbstractAnimation::Backward);
mpTransition->start();
while (mpTransition->state() == QAbstractAnimation::Running)
{
QApplication::processEvents();
}
}
return false;
}
Other method
Also you can override closeEvent method like this:
void MainWindow::closeEvent(QCloseEvent* e)
{
mpTransition->setDirection(QAbstractAnimation::Backward);
mpTransition->start();
e->ignore();
}
but in this case you should do something after animate will finished (for example connect on signal finished and call some method for closing window/application/etc).
Also you should be check, would manually call close event or by user operations.

Related

QGraphicsSceneHoverEvent not called while mouse is pressed

I have a scene that extends QGraphicsScene and has an event filter to handle all my scene logic and subsequent hover events etc happen correctly unless the mouse button is held down.
For example I have child elements in groups that have hoverEnterEvent and hoverLeaveEvent that get called correctly unless I'm holding the mouse. I've tried adjusting the code according to some answers and the documentation but I think I may be overlooking something really simple like a scene setting
The element header:
#ifndef IOELEMENT_H
#define IOELEMENT_H
#include <QGraphicsEllipseItem>
#include <QGraphicsItemGroup>
#include <QPen>
class IOElement : public QGraphicsEllipseItem {
public:
IOElement(QGraphicsItemGroup *parent=nullptr);
...
protected:
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
...
};
#endif // IOELEMENT_H
The element cpp:
#include "ioelement.h"
#include <QBrush>
#include <QDebug>
#include "../nodescene.h"
#include "../nodestyles.h"
IOElement::IOElement(QGraphicsItemGroup *parent) : QGraphicsEllipseItem(parent) {
...
setAcceptHoverEvents(true);
setFlags(QGraphicsItem::GraphicsItemFlag::ItemIsSelectable |
QGraphicsItem::GraphicsItemFlag::ItemSendsScenePositionChanges |
QGraphicsItem::ItemSendsGeometryChanges);
}
void IOElement::hoverEnterEvent(QGraphicsSceneHoverEvent *event) {
NodeScene *nodeScene = dynamic_cast<NodeScene *>(scene());
nodeScene->setChildHover(this);
QPen pen;
pen.setColor(NodeStyles::Color::Pen_Hover_Normie);
pen.setWidth(2);
setPen(pen);
update();
QGraphicsEllipseItem::hoverEnterEvent(event);
}
void IOElement::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) {
NodeScene *nodeScene = dynamic_cast<NodeScene *>(scene());
nodeScene->setChildHover(nullptr);
QPen pen;
pen.setColor(NodeStyles::Color::IO_Pen_Normie);
pen.setWidth(1);
setPen(pen);
update();
QGraphicsEllipseItem::hoverLeaveEvent(event);
}
These hover routines work as expected and I can handle the rest of the mouse logic in the scene with a filter like so
The scene header:
#ifndef NODESCENE_H
#define NODESCENE_H
#include <QGraphicsScene>
class NodeScene : public QGraphicsScene {
Q_OBJECT
public:
using QGraphicsScene::QGraphicsScene;
explicit NodeScene(QObject *parent = nullptr);
...
IOElement * getChildHover() const;
void setChildHover(IOElement * hover=nullptr);
protected:
bool eventFilter(QObject *watched, QEvent *event);
private:
...
IOElement *hoverIO;
...
};
#endif // NODESCENE_H
The scene cpp:
#include "nodescene.h"
...
#include <QGraphicsSceneMouseEvent>
#include <QKeyEvent>
#include <QDebug>
NodeScene::NodeScene(QObject *parent) : QGraphicsScene(parent) {
...
// Events
installEventFilter(this);
}
IOElement * NodeScene::getChildHover() const { return hoverIO; }
void NodeScene::setChildHover(IOElement * hover) {
hoverIO = hover;
}
bool NodeScene::eventFilter(QObject *watched, QEvent *event) {
if(watched == this) {
QGraphicsSceneMouseEvent *mouseSceneEvent;
if(event->type() == QEvent::GraphicsSceneMousePress) { // Mouse Down
if(hoverIO) {
if(hoverIO->IsOutput()) {
activeConnection = new Connection(this, hoverIO->scenePos().x()+6, hoverIO->scenePos().y()+6);
} else {
// Check if connected first
qDebug() << "Grabbing intput";
}
}
}
else if (event->type() == QEvent::GraphicsSceneMouseRelease) { // Mouse Up
delete activeConnection;
activeConnection = nullptr;
}
else if (event->type() == QEvent::GraphicsSceneMouseMove) { // Mouse Move
mouseSceneEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
int x = mouseSceneEvent->lastScenePos().rx();
int y = mouseSceneEvent->lastScenePos().ry();
if(activeConnection) {
activeConnection->DrawTo(x, y);
}
}
QKeyEvent *keyEvent;
if(event->type() == QEvent::KeyPress) { // Key Press
keyEvent = static_cast<QKeyEvent *>(event);
qDebug() << keyEvent->key();
}
}
return QGraphicsScene::eventFilter(watched, event);
}
When the mouse buttons are pressed nothing at all triggers in the hover events

Define shortcut with multiple letter in Qt C++

I define a shortcut using following Qt C++ code:
QShortcut *shortcut = new QShortcut(QKeySequence("Ctrl+Shift+S"), this);
QObject::connect(shortcut, &QShortcut::activated, [=]{qDebug()<<"Example";});
How I can define shortcut with multiple letter, for example Ctrl+Shift+S+D+F. If the user hold Ctrl+Shift and press S, D and F in order.
Note: I use Qt 5.15.2 in Linux Ubuntu 20.04.
AFAIK, QShortcut currently does not support the feature you are described.
A workaround is to install an event filter yourself.
#include <QCoreApplication>
#include <QKeyEvent>
#include <QVector>
class QMultipleKeysShortcut : public QObject
{
Q_OBJECT
public:
explicit inline QMultipleKeysShortcut(const QVector<int> &Keys, QObject *pParent) :
QObject{pParent}, _Keys{Keys}
{
pParent->installEventFilter(this);
}
Q_SIGNALS:
void activated();
private:
QVector<int> _Keys;
QVector<int> _PressedKeys;
inline bool eventFilter(QObject *pWatched, QEvent *pEvent) override
{
if (pEvent->type() == QEvent::KeyPress)
{
if (_PressedKeys.size() < _Keys.size())
{
int PressedKey = ((QKeyEvent*)pEvent)->key();
if (_Keys.at(_PressedKeys.size()) == PressedKey) {
_PressedKeys.append(PressedKey);
}
}
if (_PressedKeys.size() == _Keys.size()) {
emit activated();
}
}
else if (pEvent->type() == QEvent::KeyRelease)
{
int ReleasedKey = ((QKeyEvent*)pEvent)->key();
int Index = _PressedKeys.indexOf(ReleasedKey);
if (Index != -1) {
_PressedKeys.remove(Index, _PressedKeys.size() - Index);
}
}
return QObject::eventFilter(pWatched, pEvent);
}
};
And usage:
QMultipleKeysShortcut *pMultipleKeysShortcut = new QMultipleKeysShortcut{{Qt::Key_Control, Qt::Key_Shift, Qt::Key_S, Qt::Key_D, Qt::Key_F}, this};
connect(pMultipleKeysShortcut, &QMultipleKeysShortcut::activated, [=] {qDebug() << "Example"; });

How to move window using custom titleBar in Qt

I'm beginner in Qt and I want to drag and move Window using my own custom titleBar(QLabel).
The Qt code:
void MainWindow::mousePressEvent(QMouseEvent *event)
{
mpos = event->pos();
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
{
QPoint diff = event->pos() - mpos;
QPoint newpos = this->pos() + diff;
this->move(newpos);
}
}
This code allow me to move window by mouse pressed on any QWidget but I want to move window by mouse pressed on QLabel.
I know that its kinda late, but I solved this issue. The code is very similar to the implementation that Farhad suggested, but to solve the "jumping" window, you need to update the current position of the mouse also in the event filter:
if (object == ui->frame_title && event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* mouseEvent = (QMouseEvent*)event;
if (pressed == false){
current = mouseEvent->pos();
}
pressed = true;
return true;
}
Adding this, you get the current mouse location when the user first press the left-click.
Here is the full implementation:
void MainWindow::mousePressEvent(QMouseEvent *event)
{
current = event->pos();
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if(pressed)
this->move(mapToParent(event->pos() - current));
}
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if (object == ui->frame_title && event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* mouseEvent = (QMouseEvent*)event;
if (pressed == false){
current = mouseEvent->pos();
}
pressed = true;
return true;
}
if (object == ui->frame_title && event->type() == QEvent::MouseButtonRelease)
{
pressed = false;
return true;
}
else
return false;
}
Then in your constructor, just add (frame_title is my titlebar):
ui->frame_title->installEventFilter(this);
I suggest you to use eventFilter to get event MousePress and MouseRelease:
void MainApp::mousePressEvent(QMouseEvent *event)
{
current = event->pos();
}
void MainApp::mouseMoveEvent(QMouseEvent *event)
{
if(pressed)
this->move(mapToParent(event->pos() - current));
}
bool MainApp::eventFilter(QObject *object, QEvent *event)
{
if (object == ui->label && event->type() == QEvent::MouseButtonPress)
{
pressed = true;
return true;
}
if (object == ui->label && event->type() == QEvent::MouseButtonRelease)
{
pressed = false;
return true;
}
else
return false;
}
This is a sample project for your question on github download here.
You can re-implement QLabel class and impalement mousePressEvent
Example :
header file
#ifndef MYLABLE_H
#define MYLABLE_H
#include <QEvent>
#include <QObject>
#include <QLabel>
class MyLable : public QLabel
{
Q_OBJECT
public:
explicit MyLable(QWidget *parent = 0);
QPoint mpos;
signals:
public slots:
// QWidget interface
protected:
void mousePressEvent(QMouseEvent *);
};
#endif // MYLABLE_H
.cpp
#include "mylable.h"
#include <QMouseEvent>
MyLable::MyLable(QWidget *parent) : QLabel(parent)
{
}
void MyLable::mousePressEvent(QMouseEvent * event)
{
if (event->buttons() & Qt::LeftButton)
{
QPoint diff = event->pos() - mpos;
QPoint newpos = this->pos() + diff;
this-> parentWidget()->move(newpos);
}
}

The reference to the main window in QT

I made in QT character creator that allows you to draw individual parts of clothing, but I would like to add an option to the user himself can choose the appearance, for example shoes available, so I created a new window for shoes and there I set the 6 buttons, which are simply images of these shoes and I would so the user can click on a button in the main window receives an interesting picture of him in qlabel, but not too much know how to connect. I would ask for help! I would be really very grateful!!! Sorry for my English, but I'm from Poland.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_przycisk_zamykania_clicked();
void on_przycisk_informacje_clicked();
void on_przycisk_powrotu_clicked();
void on_przycisk_graj_clicked();
void on_powrot_clicked();
void on_losuj7_clicked();
void on_losuj6_clicked();
void on_losuj5_clicked();
void on_losuj4_clicked();
void on_losuj3_clicked();
void on_losuj2_clicked();
void on_losuj1_clicked();
void on_wybierz7_clicked();
private:
Ui::MainWindow* ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QPixmap"
#include "QPalette"
#include "buty.h"
#include "QObject"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->opis->setTextFormat(Qt::RichText);
ui->opis->setTextInteractionFlags(Qt::TextBrowserInteraction);
ui->opis->setOpenExternalLinks(true);
ui->copyright->setTextFormat(Qt::RichText);
ui->copyright >setTextInteractionFlags(Qt::TextBrowserInteraction);
ui->copyright->setOpenExternalLinks(true);
QPalette *palette1 = new QPalette();
palette1->setColor(QPalette::Text,Qt::white);
ui->imie->setPalette(*palette1);
QPalette *palette2 = new QPalette();
palette2->setColor(QPalette::Text,Qt::white);
ui->nazwisko->setPalette(*palette2);
QPalette *palette3 = new QPalette();
palette3->setColor(QPalette::Text,Qt::white);
ui->wiek->setPalette(*palette3);
QPalette *palette4 = new QPalette();
palette4->setColor(QPalette::Text,Qt::white);
ui->info->setPalette(*palette4);
QPalette *palette5 = new QPalette();
palette5->setColor(QPalette::Text,Qt::white);
ui->ocena->setPalette(*palette5);
//Buty = new Buty(this);
//connect(Buty,SIGNAL(on_buty1_clicked()),this,SLOT(on_buty1_clicked));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_przycisk_zamykania_clicked()
{
close();
}
void MainWindow::on_przycisk_informacje_clicked()
{
ui->stackedWidget->setCurrentIndex(1);
}
void MainWindow::on_przycisk_powrotu_clicked()
{
ui->stackedWidget->setCurrentIndex(0);
}
void MainWindow::on_przycisk_graj_clicked()
{
ui->stackedWidget->setCurrentIndex(2);
}
void MainWindow::on_powrot_clicked()
{
ui->stackedWidget->setCurrentIndex(0);
}
void MainWindow::on_losuj7_clicked()
{
ui->pytajnik7->setStyleSheet("background-color:#040f1e;");
int losowanie7;
srand (time(NULL));
losowanie7 = rand() % 6 + 1;
if (losowanie7 == 1)
{
QPixmap b1(":/pliki_buty/img/losowanie_img/buty_img/buty1_wynik.png");
ui->pytajnik7->setPixmap(b1);
}
if (losowanie7 == 2)
{
QPixmap b2(":/pliki_buty/img/losowanie_img/buty_img/buty2_wynik.png");
ui->pytajnik7->setPixmap(b2);
}
if (losowanie7 == 3)
{
QPixmap b3(":/pliki_buty/img/losowanie_img/buty_img/buty3_wynik.png");
ui->pytajnik7->setPixmap(b3);
}
if (losowanie7 == 4)
{
QPixmap b4(":/pliki_buty/img/losowanie_img/buty_img/buty4_wynik.png");
ui->pytajnik7->setPixmap(b4);
}
if (losowanie7 == 5)
{
QPixmap b5(":/pliki_buty/img/losowanie_img/buty_img/buty5_wynik.png");
ui->pytajnik7->setPixmap(b5);
}
if (losowanie7 == 6)
{
QPixmap b6(":/pliki_buty/img/losowanie_img/buty_img/buty6_wynik.png");
ui->pytajnik7->setPixmap(b6);
}
}
void MainWindow::on_losuj6_clicked()
{
ui->pytajnik6->setStyleSheet("background-color:#040f1e;");
int losowanie6;
srand (time(NULL));
losowanie6 = rand() % 6 + 1;
if (losowanie6 == 1)
{
QPixmap s1(":/pliki_spodnie/img/losowanie_img/spodnie_img/spodnie1_wynik.png");
ui->pytajnik6->setPixmap(s1);
}
if (losowanie6 == 2)
{
QPixmap s2(":/pliki_spodnie/img/losowanie_img/spodnie_img/spodnie2_wynik.png");
ui->pytajnik6->setPixmap(s2);
}
if (losowanie6 == 3)
{
QPixmap s3(":/pliki_spodnie/img/losowanie_img/spodnie_img/spodnie3_wynik.png");
ui->pytajnik6->setPixmap(s3);
}
if (losowanie6 == 4)
{
QPixmap s4(":/pliki_spodnie/img/losowanie_img/spodnie_img/spodnie4_wynik.png");
ui->pytajnik6->setPixmap(s4);
}
if (losowanie6 == 5)
{
QPixmap s5(":/pliki_spodnie/img/losowanie_img/spodnie_img/spodnie5_wynik.png");
ui->pytajnik6->setPixmap(s5);
}
if (losowanie6 == 6)
{
QPixmap s6(":/pliki_spodnie/img/losowanie_img/spodnie_img/spodnie6_wynik.png");
ui->pytajnik6->setPixmap(s6);
}
}
void MainWindow::on_losuj5_clicked()
{
ui->pytajnik5->setStyleSheet("background-color:#040f1e;");
int losowanie5;
srand (time(NULL));
losowanie5 = rand() % 6 + 1;
if (losowanie5 == 1)
{
QPixmap k1(":/pliki_korpus/img/losowanie_img/korpus_img/korpus1_wynik.png");
ui->pytajnik5->setPixmap(k1);
}
if (losowanie5 == 2)
{
QPixmap k2(":/pliki_korpus/img/losowanie_img/korpus_img/korpus2_wynik.png");
ui->pytajnik5->setPixmap(k2);
}
if (losowanie5 == 3)
{
QPixmap k3(":/pliki_korpus/img/losowanie_img/korpus_img/korpus3_wynik.png");
ui->pytajnik5->setPixmap(k3);
}
if (losowanie5 == 4)
{
QPixmap k4(":/pliki_korpus/img/losowanie_img/korpus_img/korpus4_wynik.png");
ui->pytajnik5->setPixmap(k4);
}
if (losowanie5 == 5)
{
QPixmap k5(":/pliki_korpus/img/losowanie_img/korpus_img/korpus5_wynik.png");
ui->pytajnik5->setPixmap(k5);
}
if (losowanie5 == 6)
{
QPixmap k6(":/pliki_korpus/img/losowanie_img/korpus_img/korpus6_wynik.png");
ui->pytajnik5->setPixmap(k6);
}
}
void MainWindow::on_losuj4_clicked()
{
ui->pytajnik4->setStyleSheet("background-color:#040f1e;");
int losowanie4;
srand (time(NULL));
losowanie4 = rand() % 6 + 1;
if (losowanie4 == 1)
{
QPixmap w1(":/pliki_wlosy/img/losowanie_img/wlosy_img/wlosy1_wynik.png");
ui->pytajnik4->setPixmap(w1);
}
if (losowanie4 == 2)
{
QPixmap w2(":/pliki_wlosy/img/losowanie_img/wlosy_img/wlosy2_wynik.png");
ui->pytajnik4->setPixmap(w2);
}
if (losowanie4 == 3)
{
QPixmap w3(":/pliki_wlosy/img/losowanie_img/wlosy_img/wlosy3_wynik.png");
ui->pytajnik4->setPixmap(w3);
}
if (losowanie4 == 4)
{
QPixmap w4(":/pliki_wlosy/img/losowanie_img/wlosy_img/wlosy4_wynik.png");
ui->pytajnik4->setPixmap(w4);
}
if (losowanie4 == 5)
{
QPixmap w5(":/pliki_wlosy/img/losowanie_img/wlosy_img/wlosy5_wynik.png");
ui->pytajnik4->setPixmap(w5);
}
if (losowanie4 == 6)
{
QPixmap w6(":/pliki_wlosy/img/losowanie_img/wlosy_img/wlosy6_wynik.png");
ui->pytajnik4->setPixmap(w6);
}
}
void MainWindow::on_losuj3_clicked()
{
ui->pytajnik3->setStyleSheet("background-color:#040f1e;");
int losowanie3;
srand (time(NULL));
losowanie3 = rand() % 6 + 1;
if (losowanie3 == 1)
{
QPixmap o1(":/pliki_oczy/img/losowanie_img/oczy_img/oczy1_wynik.png");
ui->pytajnik3->setPixmap(o1);
}
if (losowanie3 == 2)
{
QPixmap o2(":/pliki_oczy/img/losowanie_img/oczy_img/oczy2_wynik.png");
ui->pytajnik3->setPixmap(o2);
}
if (losowanie3 == 3)
{
QPixmap o3(":/pliki_oczy/img/losowanie_img/oczy_img/oczy3_wynik.png");
ui->pytajnik3->setPixmap(o3);
}
if (losowanie3 == 4)
{
QPixmap o4(":/pliki_oczy/img/losowanie_img/oczy_img/oczy4_wynik.png");
ui->pytajnik3->setPixmap(o4);
}
if (losowanie3 == 5)
{
QPixmap o5(":/pliki_oczy/img/losowanie_img/oczy_img/oczy5_wynik.png");
ui->pytajnik3->setPixmap(o5);
}
if (losowanie3 == 6)
{
QPixmap o6(":/pliki_oczy/img/losowanie_img/oczy_img/oczy6_wynik.png");
ui->pytajnik3->setPixmap(o6);
}
}
void MainWindow::on_losuj2_clicked()
{
ui->pytajnik2->setStyleSheet("background-color:#040f1e;");
int losowanie2;
srand (time(NULL));
losowanie2 = rand() % 6 + 1;
if (losowanie2 == 1)
{
QPixmap u1(":/pliki_usta/img/losowanie_img/usta_img/usta1_wynik.png");
ui->pytajnik2->setPixmap(u1);
}
if (losowanie2 == 2)
{
QPixmap u2(":/pliki_usta/img/losowanie_img/usta_img/usta2_wynik.png");
ui->pytajnik2->setPixmap(u2);
}
if (losowanie2 == 3)
{
QPixmap u3(":/pliki_usta/img/losowanie_img/usta_img/usta3_wynik.png");
ui->pytajnik2->setPixmap(u3);
}
if (losowanie2 == 4)
{
QPixmap u4(":/pliki_usta/img/losowanie_img/usta_img/usta4_wynik.png");
ui->pytajnik2->setPixmap(u4);
}
if (losowanie2 == 5)
{
QPixmap u5(":/pliki_usta/img/losowanie_img/usta_img/usta5_wynik.png");
ui->pytajnik2->setPixmap(u5);
}
if (losowanie2 == 6)
{
QPixmap u6(":/pliki_usta/img/losowanie_img/usta_img/usta6_wynik.png");
ui->pytajnik2->setPixmap(u6);
}
}
void MainWindow::on_losuj1_clicked()
{
ui->pytajnik1->setStyleSheet("background-color:#040f1e;");
int losowanie1;
srand (time(NULL));
losowanie1 = rand() % 6 + 1;
if (losowanie1 == 1)
{
QPixmap a1(":/pliki_akcesoria/img/losowanie_img/akcesoria_img/akcesoria1_wynik.png");
ui->pytajnik1->setPixmap(a1);
}
if (losowanie1 == 2)
{
QPixmap a2(":/pliki_akcesoria/img/losowanie_img/akcesoria_img/akcesoria2_wynik.png");
ui->pytajnik1->setPixmap(a2);
}
if (losowanie1 == 3)
{
QPixmap a3(":/pliki_akcesoria/img/losowanie_img/akcesoria_img/akcesoria3_wynik.png");
ui->pytajnik1->setPixmap(a3);
}
if (losowanie1 == 4)
{
QPixmap a4(":/pliki_akcesoria/img/losowanie_img/akcesoria_img/akcesoria4_wynik.png");
ui->pytajnik1->setPixmap(a4);
}
if (losowanie1 == 5)
{
QPixmap a5(":/pliki_akcesoria/img/losowanie_img/akcesoria_img/akcesoria5_wynik.png");
ui->pytajnik1->setPixmap(a5);
}
if (losowanie1 == 6)
{
QPixmap a6(":/pliki_akcesoria/img/losowanie_img/akcesoria_img/akcesoria6_wynik.png");
ui->pytajnik1->setPixmap(a6);
}
}
void MainWindow::on_wybierz7_clicked()
{
Buty buty;
buty.setModal(true);
buty.exec();
}
buty.h
#ifndef BUTY_H
#define BUTY_H
#include <QDialog>
#include "mainwindow.h"
#include "QObject"
namespace Ui {
class Buty;
}
class Buty : public QDialog
{
Q_OBJECT
public:
explicit Buty(QWidget *parent = 0);
~Buty();
private slots:
void on_wroc_do_gry_clicked();
public slots:
void on_buty1_clicked();
private:
Ui::Buty* ui;
};
#endif // BUTY_H
buty.cpp
#include "buty.h"
#include "ui_buty.h"
#include "mainwindow.h"
#include "QObject"
Buty::Buty(QWidget *parent) :
QDialog(parent),
ui(new Ui::Buty)
{
ui->setupUi(this);
//QDialog::connect(ui->buty1, SIGNAL(clicked()), QMainWindow, SLOT(pytajnik7()));
connect(ui->buty1, SIGNAL(clicked()), this, SLOT(pytajnik7()));
}
Buty::~Buty()
{
delete ui;
}
void Buty::on_wroc_do_gry_clicked()
{
close();
}
void Buty::on_buty1_clicked()
{
QPixmap b1(":/pliki_buty/img/losowanie_img/buty_img/buty1_wynik.png");
ui->pytajnik7->setPixmap(b1);
}
I interpret the question like:
How can I update the main window widget from other widget code in my
app?
Well, you need the pointer to QMainWindow which is usually the only main window in the widget-based app. You can either create a global pointer variable to QMainWindow or try to find it like that:
// TODO: make it template to resolve specific type?
QMainWindow* findMainWindow()
{
for(QWidget* pWidget : QApplication::topLevelWidgets())
{
QMainWindow pMainWnd = qobject_cast<QMainWindow*>(pWidget);
if (pMainWnd)
return pMainWnd;
}
return nullptr;
}
// UI receives an event that needs to pass the data to main window
void MyWidget::onItemsSelected(const QList<Item>& goods)
{
MyMainWindow* pMainWindow = qobject_cast<MyMainWindow*>(findMainWindow());
if (!pMainWindow)
{
qWarning() << "Cannot find this app main window!";
return;
}
// make it specific to your data
pMainWindow->updateGoodsView( goods );
}
To answer on the title
The reference to the main window in QT
in your code you need to pass you mainwindow to your child window in constructor and then use it via parent() or parentWidget().
So in your code:
void MainWindow::on_wybierz7_clicked()
{
Buty buty(this); //pay attention to this
buty.setModal(true);
buty.exec();
}
...
Buty::Buty(QWidget *parent) :
QDialog(parent),
ui(new Ui::Buty)
{
ui->setupUi(this);
connect(ui->buty1, SIGNAL(clicked()), parent(), SLOT(pytajnik7()));
}
But usually it is bad idea when child dialog "know" about parent slot. Better practice is to make connection in mainwindow code.
For this declare signal in child dialog, e.g. mySignal(). Then connect clicked() signal of the button to your new signal and then make final connection in mainwindow:
void MainWindow::on_wybierz7_clicked()
{
Buty buty(this); //pay attention to this
buty.setModal(true);
connect(&buty, SIGNAL(mySignal()), this, SLOT(pytajnik7()));
buty.exec();
}
...
class Buty : public QDialog
{
Q_OBJECT
...
signals:
void mySignal();
...
};
...
Buty::Buty(QWidget *parent) :
QDialog(parent),
ui(new Ui::Buty)
{
ui->setupUi(this);
connect(ui->buty1, SIGNAL(clicked()), this, SIGNAL(mySignal()));
}
Hope i understood your question correct.

QT Event transparency only for part of the widget

The software shown 3 widget:
Main window
Content widget, that cover most of the main window
custom widget, that cover part of both, the main window and the content widget.
The custom widget has a part (defined as a QRect) that need to be Event-opaque, while the surrounding zone has to be Event-transparent.
I tried with:
setAttribute(Qt::WA_TransparentForMouseEvents);
But all sub-widgets of custom become transparent also.
I also tried with setMask, but then the custom widget is unable to draw on the surrounding area.
How to achieve this partial event-transparency?
Example (it does not explain the full problem, just add a base on which to test solutions):
main.cpp
#include "transparentwidget.hpp"
#include "normalwidget.hpp"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Main Window
NormalWidget window;
window.resize(500,500);
window.setObjectName("window");
window.setStyleSheet("background-color: rgba(0,0,128,128); ");
// Content window
NormalWidget content(&window);
content.setObjectName("content");
content.resize(400, 400);
content.move(0,0);
content.setStyleSheet("background-color: rgba(128,0,0,128);");
TransparentWidget custom(&window);
custom.setObjectName("custom");
custom.resize(500, 200);
custom.setStyleSheet("background-color:rgba(0,128,0,128);");
window.show();
return a.exec();
}
transparentwidget.hpp
#ifndef TRANSPARENTWIDGET_H
#define TRANSPARENTWIDGET_H
#include <QWidget>
#include <QStyleOption>
#include <QPainter>
#include <QDebug>
#include <QEvent>
// This widget shall be transparent in some parts
class TransparentWidget : public QWidget
{
Q_OBJECT
public:
explicit TransparentWidget(QWidget *parent = 0): QWidget(parent)
{
// Start of solution with WA_TransparentForMouseEvents (not working)
setAttribute(Qt::WA_TransparentForMouseEvents);
// end solution with WA_TransparentForMouseEvents
}
~TransparentWidget(){}
protected:
QRect opaqueRect = QRect(0,0,400,100);
void paintEvent(QPaintEvent *)
{
// Solution with setMask, not working
QRegion reg(opaqueRect);
setMask(reg);
// end of setMask solution
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
bool event(QEvent *event)
{
// Starting of solution with event propagation (not working)
if (event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::MouseButtonRelease)
{
QMouseEvent* e = static_cast<QMouseEvent*>(event);
if (e && !opaqueRect.contains(e->pos()) return false;
}
// end solution with event propagation.
if (event->type() == QEvent::MouseButtonPress) qDebug() << "Press: " << objectName();
else if(event->type() == QEvent::MouseButtonRelease) qDebug() << "Release: " << objectName();
return QWidget::event(event);
}
};
#endif
normalwidget.hpp
#ifndef NORMALWIDGET_H
#define NORMALWIDGET_H
#include <QWidget>
#include <QStyleOption>
#include <QPainter>
#include <QDebug>
#include <QEvent>
// Widgets that are not event-transparent
class NormalWidget : public QWidget
{
Q_OBJECT
public:
explicit NormalWidget(QWidget *parent = 0): QWidget(parent){}
~NormalWidget(){}
protected:
void paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
bool event(QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress) qDebug() << "Press: " << objectName();
else if(event->type() == QEvent::MouseButtonRelease) qDebug() << "Release: " << objectName();
}
};
#endif // NORMALWIDGET_H
Like the docs say:
When enabled, this attribute disables the delivery of mouse events to
the widget and its children.
The solution is to ignore all the mouse events inside TransparentWidget::event(). If you do a mouse event over a child of TransparentWidget, the event will be consumed by the child, otherwise it will be delivered to the parent of TransparentWidget:
bool TransparentWidget::event(QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::MouseButtonRelease ||
event->type() == QEvent::MouseButtonRelease)
return false;
else
return QWidget::event(event);
}