Qt Прозрачный фон заставляет дочерний виджет «впечатываться» в родителя

У меня есть родительский контейнер (MyCartParentWidget) с полупрозрачным фоном, внутри которого я должен нарисовать дочерний виджет (MyCart) с фоновым изображением (это изображение в портрете, это изображение в пейзаже), также рисуется с полупрозрачным фоном, и оба QLabels, Есть кнопка, по которой дочерний виджет переключает свои размеры (resetCartStyle), то есть он переходит из портретного в ландшафтный режим и наоборот. Проблема в том, что при переключении исходный отпечаток остается прежним, то есть это оригинальная картинка, где он находится в режиме «портрет»:

введите описание изображения здесь

Затем, когда я переключаюсь в «альбомный» режим, он смещается, но оригинальный «портретный» режим остается прежним:

введите описание изображения здесь

Это мой код:

main.cpp:

#include <QApplication>
#include "MyCartParentWidget.hpp"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyCartParentWidget p;
p.move(370,10);
p.show();
return a.exec();
}

MyCart.cpp:

 #include "MyCart.hpp"#include <QPainter>

MyCart::MyCart(QWidget *parent): QLabel(parent)
{
setAttribute(Qt::WA_TranslucentBackground);
fPixMap.load("/Users/attitude/Desktop/RnSghvV.png");
setStyleSheet("background-color: rgba(0,0,0,255);");
setFixedSize(325,400);

}

void MyCart::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.setRenderHint(QPainter::SmoothPixmapTransform);
p.drawPixmap(0,0,width(),height(),fPixMap);
}

void MyCart::resetCartStyle(QString url, int w, int h)
{
setFixedSize(w,h);
fPixMap.load(url);
this->update();
}

MyCart.hpp:

#pragma once

#include <QLabel>
#include <QPaintEvent>
#include <QPixmap>class MyCart: public QLabel
{
public:
MyCart(QWidget*);
virtual void paintEvent(QPaintEvent *);
QPixmap fPixMap;
void resetCartStyle(QString, int w, int h);
};

MyCartParentWidget.cpp:

#include "MyCartParentWidget.hpp"#include <QPushButton>

MyCartParentWidget::MyCartParentWidget()
{

setFixedSize(800,700);
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
setStyleSheet("background-color: none;");

fLayout = new QHBoxLayout();
setLayout(fLayout);
fLayout->setContentsMargins(0,0,0,0);
fLayout->setSpacing(0);
fLayout->setMargin(0);
fLayout->setAlignment(Qt::AlignLeft | Qt:: AlignTop);
i = 0;

fCart = new MyCart(this);
fLayout->addWidget(fCart);

QPushButton* p = new QPushButton(this);
p->setText("Toggle");
p->move(0,650);
connect(p,SIGNAL(clicked(bool)),this,SLOT(clickedSlot()));
}

void MyCartParentWidget::clickedSlot()
{
if (i == 0)
{
//enter landscape mode
i = 1;
fCart->resetCartStyle("/Users/attitude/Desktop/foo.png",400,325);
}
else
{
//enter portrait mode
i = 0;
fCart->resetCartStyle("/Users/attitude/Desktop/RnSghvV.png",325,400);
}
}

MyCartParentWidget.hpp:

#pragma once

#include <QLabel>
#include <QHBoxLayout>
#include "MyCart.hpp"

class MyCartParentWidget: public QLabel
{
Q_OBJECT
public:
MyCartParentWidget();

QHBoxLayout* fLayout;
MyCart *fCart;
int i;

private slots:
void clickedSlot();
};

Эта проблема не возникает, когда я устанавливаю фон родительского виджета на что-то вроде green и закомментировать setAttribute(Qt::WA_TranslucentBackground); частично, это происходит только с setAttribute(Qt::WA_TranslucentBackground); часть.

Как это исправить?

Платформа — OS X Yosemite, Qt 5.3.1, 32 бит.

Приведенное ниже решение Ильи прекрасно работает на Windows, но проблема сохраняется на Mac.

2

Решение

Вместо рисования / обновления вручную, просто вызовите setPixmap метод, QLabel должен управлять собой. Код работает нормально, кроме как на Mac OS X:

MyCart.cpp:

#include "MyCart.hpp"
MyCart::MyCart(QWidget *parent): QLabel(parent)
{
resetCartStyle("C:/dev/cart/portrait.png");
}

void MyCart::resetCartStyle(QString url)
{
fPixMap.load(url);
setPixmap(fPixMap);
}

MyCart.hpp:

#pragma once

#include <QLabel>
#include <QPaintEvent>
#include <QPixmap>class MyCart: public QLabel
{
public:
MyCart(QWidget*);
QPixmap fPixMap;
void resetCartStyle(QString);
};

MyCartParentWidget.cpp:

#include "MyCartParentWidget.hpp"#include <QPushButton>

MyCartParentWidget::MyCartParentWidget()
{

setFixedSize(800,700);
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);

fLayout = new QHBoxLayout();
setLayout(fLayout);
fLayout->setContentsMargins(0,0,0,0);
fLayout->setSpacing(0);
fLayout->setMargin(0);
fLayout->setAlignment(Qt::AlignLeft | Qt:: AlignTop);
i = 0;

fCart = new MyCart(this);
fLayout->addWidget(fCart);

QPushButton* p = new QPushButton(this);
p->setText("Toggle");
p->move(0,650);
connect(p,SIGNAL(clicked(bool)),this,SLOT(clickedSlot()));
}

void MyCartParentWidget::clickedSlot()
{
if (i == 0)
{
//enter landscape mode
i = 1;
fCart->resetCartStyle("C:/dev/cart/landscape.png");
}
else
{
//enter portrait mode
i = 0;
fCart->resetCartStyle("C:/dev/cart/portrait.png");
}
}

Так что насчет Mac OS? Результат немного лучше с Qt 5.5.1, чем с 5.3.1, вот скриншот (Mac OS 10.11):

введите описание изображения здесь

Итак, призрак изображения остался. Чтобы получить полностью правильный дисплей,
Самый простой и эффективный способ — скрыть / показать родительский виджет до / после переключения:

void MyCartParentWidget::clickedSlot()
{
hide();
if (i == 0)
{
//enter landscape mode
i = 1;
fCart->resetCartStyle("C:/dev/cart/landscape.png");
}
else
{
//enter portrait mode
i = 0;
fCart->resetCartStyle("C:/dev/cart/portrait.png");
}
show();
}

Для полноты ниже приведены два других трюка, найденных при поиске исправления, которые исправили код примера MCV, но не производственное приложение.

Первый трюк:

MyCart.cpp

MyCart::MyCart(QWidget *parent): QLabel(parent)
{
// do nothing in the constructor
}

MyCartParentWidget.cpp

MyCartParentWidget::MyCartParentWidget()
{
...previous code

// add this line...
QTimer::singleShot( 0, this, SLOT(onclicked() ); // ...to show the widget
}

Этот код по-прежнему не работает с Qt 5.3.1, версией OP.
Для этой версии Qt необходимо другое исправление (снято с этот сообщение об ошибке). NB это исправить не подавить призрачное изображение для Qt 5.5.1.

void MyCartParentWidget::paintEvent(QPaintEvent *)
{
QPainter p( this );
p.setCompositionMode( QPainter::CompositionMode_Clear );
p.fillRect( this->rect(), Qt::transparent );
}

Так что для рабочего кода (для примера) в Mac OS с обеими версиями Qt (5.3.1 и 5.5.1) вы должны использовать оба трюка.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]