Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting a QDialog to be an alien

Tags:

c++

qt

In a standalone GUI application where I don't have a windowmanager nor a composite manager I want to display a QDialog to the user to ask for values.

The dialog is quite big, so I want to make it translucent so that the user can look through it to see what happens in the application while the dialog is shown.

The problem is that for translucency of X native windows, there needs to be a composite manager. Qt internal widgets can be painted translucent because they don't correspond to native X windows (aliens) and are completely only known to Qt.

Is there a way to make the background of a QDialog translucent without having a composite manager running? Perhaps making it a normal child widget/alien of the application's main window? Is there a better alternative to this?

like image 723
Johannes Schaub - litb Avatar asked Nov 05 '22 15:11

Johannes Schaub - litb


1 Answers

I don't know of any way of turning a QDialog into a normal child widget. Looking at the Qt for X11 code, I can't figure out a way of not setting the Qt::WindowFlags passed to the QWidget (parent) constructor so that it would be a plain widget and not a window of its own (but I could be wrong, didn't spend a lot of time on that).

A simple alternative is to use a plain QWidget as your container, instead of a QDialog. Here's a sample "PopupWidget" that paints a half-transparent-red background.

#include <QtGui>

class PopupWidget: public QWidget
{
 Q_OBJECT

 public:
  PopupWidget(QWidget *parent): QWidget(parent)
  {
   QVBoxLayout *vl = new QVBoxLayout;
   QPushButton *pb = new QPushButton("on top!", this);
   vl->addWidget(pb);
   connect(pb, SIGNAL(clicked()), this, SLOT(hide()));
  }

 public slots:
  void popup() {
   setGeometry(0, 0, parentWidget()->width(), parentWidget()->height());
   raise();
   show();
  }

 protected:
  void paintEvent(QPaintEvent *)
  {
   QPainter p(this);
   QBrush b(QColor(255,0,0,128));
   p.fillRect(0, 0, width(), height(), b);
  }
};

To show it, call it's popup() slot which will raise it to the top of the widget stack, make it as large as its parent, and show it. This will mask all the widgets behind it (you can't interact with them with the mouse). It hides itself when you click on that button.

Caveats:

  • this doesn't prevent the user from using Tab to reach the widgets underneath. This could be fixed by toggling the enabled property on your "normal" widget container for example. (But don't disable the PopupWidget's parent: that would disable the popup widget itself.)
  • this doesn't allow for a blocking call like QDialog::exec
  • the widgets in that popup won't be transparent, you'd have to create custom transparent-background versions for all the widget types you need AFAIK.

But that's probably less of a hassel than integarting a compositing manager in your environment.

like image 93
Mat Avatar answered Nov 12 '22 17:11

Mat