Remove QGraphicsEffect from child widget [duplicate] - c++

This question already has answers here:
Blur effect over a QWidget in Qt
(3 answers)
Closed 6 years ago.
I'm making a game whith QGraphics framework.
When the game finish I want to blur the whole graphicsview and show a widget with some text on top of it.
My simplified code is :
In view :
void GraphicsTraxView::showGameResultWidget(bool res)
{
blurEffect_->setEnabled(true);
WigglyWidget *wigglyWidget = new WigglyWidget(this);
if(res)
wigglyWidget->setText("you win");
else
wigglyWidget->setText("you loose");
wigglyWidget->resize(150,150);
wigglyWidget->move(QPoint(
getScreenSize().width() / 2 -75, getScreenSize().height() / 2-75));
wigglyWidget->show();
}
In text widget :
void WigglyWidget::paintEvent(QPaintEvent * /* event */)
{
QColor backgroundColor = palette().light().color();
backgroundColor.setAlpha(220);
QPainter customPainter(this);
customPainter.fillRect(rect(), backgroundColor);
//...
But as you can see in image bellow text become blur and unreadable with view too.
How can I remove graphicsEffect from child widget and still keep background color of my widget semi transparent ?

You can embed your WigglyWidget in a dialog, or make itself a dialog.
You can then make it transparent by setting the window opacity with setWindowOpacity.
If you embedded your WigglyWidget into a dialog, you have to set the Qt::WA_TranslucentBackground attribute to the dialog to make the background transparent.
Then you have to set the Qt::FramelessWindowHint | Qt::Dialog flags to it to get rid off the title bar.
Heres an example:
QDialog *pop_up = new QDialog(this);
pop_up->resize(200, 200);
pop_up->setAttribute(Qt::WA_TranslucentBackground);
pop_up->setWindowOpacity(0.5);
pop_up->setStyleSheet("QDialog{background-color: transparent;}");
pop_up->setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
pop_up->setLayout(new QVBoxLayout);
QLabel *transparentLabel = new QLabel("TRANSPARENT");
transparentLabel->setAlignment(Qt::AlignCenter);
transparentLabel->setStyleSheet("QLabel{color: red; font: 20pt bold; background-color: #00baff;}");
pop_up->layout()->addWidget(transparentLabel);
pop_up->show();

Related

QTreeWidget with non-native scroll bar when background changed

I need a QTreeWidget with transparent background so it has the same color as the native light-gray window background. This works fine by setting the background to transparent.
The problem is that if I do this, the scroll becomes non-native looking. The default background of QTreeWidget is "white" and if I don't change it, the scroll bar does look native. However, if I change the background to "transparent", the scrollbar looses its native appearance.
To demonstrate this, I put two QTreeWidgets next to each other, one with the default white background showing the native scroll bar and one with the background changed to transparent, showing a non-native scroll bar: screenshot
Here is the code:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QHBoxLayout* layout = new QHBoxLayout(this);
ui->centralWidget->setLayout(layout);
QTreeWidget* tree1 = new QTreeWidget();
QTreeWidget* tree2 = new QTreeWidget();
layout->addWidget(tree1);
layout->addWidget(tree2);
// add ten items to each tree widget
for(int i=0; i<10; i++){
QString item_text = "item " + QString::number(i);
QTreeWidgetItem* item1 = new QTreeWidgetItem();
item1->setText(0, item_text);
tree1->addTopLevelItem(item1);
QTreeWidgetItem* item2 = new QTreeWidgetItem();
item2->setText(0, item_text);
tree2->addTopLevelItem(item2);
}
// change the background color of tree2 to the window color
// this leads to a non native scroll bar for tree2
tree2->setStyleSheet("background-color: transparent;");
}
How can I have the transparent background an still keep the native scroll bar?
I finally found the solution. I need to restrict the definition of the background-color to the QTreeWidget:
tree2->setStyleSheet("QTreeWidget {background-color: transparent;}");

Can't set style sheet for a derived class from QWidget in qt [duplicate]

This question already has answers here:
Qt Stylesheet for custom widget
(6 answers)
Closed 4 years ago.
I have a derived class from QWidget, let's call it DerivedWidget. And I set the DerivedWidget in MainWindow class as central widget. I want to change the background color for the DerivedWidget, I tried many ways, it just will not work.
DerivedWidget::DerivedWidget(QWidget *parent) : QWidget(parent)
{
mBtn = new QPushButton(this); //if I have some other widgets on this, like a QPushButton
mBtn->setStyleSheet("QPushButton { background-color: red; }"); //it works for the QPushButton on this widget
//tried three ways below to set the widget bgcolor, none of them works
//first
this->setStyleSheet("QWidget { background-color: yellow; }"); //it is not working
//second
this->setObjectName("#DerivedWidget");
this->setStyleSheet("QWidget#DerivedWidget { background-color: yellow; }"); //still not working
//third
this->setStyleSheet("DerivedWidget { background-color: yellow; }"); //not working either
}
So as you can see, I can change the style sheet for the widgets on the DerivedWidget, but just can not change its background color.
I've also tried to change the DerivedWidget bgcolor in MainWindow class. Of course, I tried more than those three ways I provied, but the results are still the same. None of those methods worked. If I just create a QWidget and set it as central widget in MainWindow class, I can easily set bgcolor for that. But why can't I set bgcolor for the derived class?
Why would this happen and how can I solve this problem?
Ok, I solved this problem by re-implementing the paintEvent(QPaintEvent *) function` like:
void CustomWidget::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
More details are here: Qt Doc and a helpful answer.

Qt window bugs with OpenGL

I have created a Qt interface to visualise a 3D model (point cloud) and an image. The issue is that when I switch to full screen, (using keystroke F1 for example), I do get my fullscreen mode as expected. But When I switch to normal mode, the 3D model disappears in the widget as shown in the bottom figure.
QGLWidget is inserted like this in QMainWindow:
QMainWindow : setCentralWidget(viewerWidget);
Our 3D Engine Class,OpenGLViewer inherits QGLWidget
the function for toggle full window goes like this:
void OpenGLViewer::toggleFullWindow()
{
if (isFullScreen()) {
setWindowFlags(Qt::Widget);
showNormal();
}
else {
setWindowFlags(Qt::Window);
showFullScreen();
}
}
My ui widget goes like this
QLabel* App::createViewerBox()
{
viewerWidget = dynamic_cast<QWidget*>(viewer);
QHBoxLayout *layoutHor = new QHBoxLayout();
QLabel *frame = new QLabel();
layoutHor->addWidget(viewerWidget,Qt::AlignJustify);
frame->setLayout(layoutHor);
return frame;
}

How to create a resizable Qt thumbnail preview?

I'm working on a basic image viewer/tagger that will need a thumbnail view to select an image. So far, I've used a QDockWidget enclosing a QScrollArea with a QHBoxLayout to contain a series of QLabels, each of which has its QPixMap set.
This seems very inelegant, and it only gets uglier to consider how I might implement auto-scaling of the thumbnails when the QDockWidget is resized. It's further complicated by the additional need to resize the thumbnails when the scroll bar appears and disappears.
There must be a better way to do this?
I've ran into a similar problem when trying to animate resizing a qlabel with a qpixmap. The method I found that worked best was to use a QWidget instead and re-implement the paintEvent function. Then your QWidget image will automatically be scaled if it's resized. Here is an example:
In my case I had the private variables in a private object called private_:
bool image_set_;
QImage image_;
QBrush paintbrush_;
void MyClass::paintEvent( QPaintEvent* event )
{
// if the QWidget has an image set, then we use our custom painting.
if( this->private_->image_set_ )
{
//I've made it so that my QWidget has a 1px white border
this->private_->paintbrush_.setTextureImage( this->private_->image_.scaled(QSize( this->width() - 2, this->height() - 2 ) ) );
QPainter painter( this );
QRect temp_rect = QRect( 1, 1, this->width()-2, this->height() - 2 );
painter.fillRect( this->rect(), Qt::white );
painter.fillRect( temp_rect, this->private_->paintbrush_ );
}
else
{
QWidget::paintEvent( event );
}
}

Qt - QPushButton text formatting

I have a QPushButton and on that I have a text and and icon. I want to make the text on the button to be bold and red. Looked at other forums, googled and lost my hope. Seems there is no way to do that if the button has an icon (of course if you don't create a new icon which is text+former icon). Is that the only way? Anyone has a better idea?
You really don't need to subclass to change the formatting of your button, rather use stylesheets e.g.
QPushButton {
font-size: 18pt;
font-weight: bold;
color: #ff0000;
}
Applying this to the button that you want to change will make the buttons text 18pt, bold and red. You can apply via widget->setStyleSheet()
Applying this to a widget in the hierarchy above will style all the buttons underneath, the QT stylesheet mechanism is very flexible and fairly well documented.
You can set stylesheets in the designer too, this will style the widget that you are editing immediately
you make the subclass of "QPushbutton", then override the paint event,
there you modify the text to your wish.
here it is,
class button : public QPushButton
{
Q_OBJECT
public:
button(QWidget *parent = 0)
{
}
~button()
{
}
void paintEvent(QPaintEvent *p2)
{
QPushButton::paintEvent(p2);
QPainter paint(this);
paint.save();
QFont sub(QApplication::font());
sub.setPointSize(sub.pointSize() + 7);
paint.setFont(sub);
paint.drawText(QPoint(300,300),"Hi");
paint.restore();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
button b1;
b1.showMaximized();
return a.exec();
}
Note:My answer is inspired by the idea from #Петър Петров and the comment from #mjwach.
You can subclass QPushButton and give it two private fields:
self.__lbl: A QLabel() instance to hold the rich text. Its background is made transparent and it doesn't catch mouse events.
self.__lyt: A QHBoxLayout() to hold the label. The layout margins are set to zero, such that the label's borders touch the button's borders. In other words: we ensure that the label has the exact same size as the button, and is positioned right on top of it.
Finally you have to override the setText() method, such that the text ends up in the label instead of the button.
class RichTextPushButton(QPushButton):
def __init__(self, parent=None, text=None):
if parent is not None:
super().__init__(parent)
else:
super().__init__()
self.__lbl = QLabel(self)
if text is not None:
self.__lbl.setText(text)
self.__lyt = QHBoxLayout()
self.__lyt.setContentsMargins(0, 0, 0, 0)
self.__lyt.setSpacing(0)
self.setLayout(self.__lyt)
self.__lbl.setAttribute(Qt.WA_TranslucentBackground)
self.__lbl.setAttribute(Qt.WA_TransparentForMouseEvents)
self.__lbl.setSizePolicy(
QSizePolicy.Expanding,
QSizePolicy.Expanding,
)
self.__lbl.setTextFormat(Qt.RichText)
self.__lyt.addWidget(self.__lbl)
return
def setText(self, text):
self.__lbl.setText(text)
self.updateGeometry()
return
def sizeHint(self):
s = QPushButton.sizeHint(self)
w = self.__lbl.sizeHint()
s.setWidth(w.width())
s.setHeight(w.height())
return s
You can subclass a QLabel and completely throw away all of its mouse events (so they reach the parent).
Then crate a QPushButton, set a layout on it and in this layout insert a QLabel with formatted text. You get a button that contains QLabel and is clickable. (Any Qt Widget can have layout set, including ones that you never ever expected they can.)