在QDockWidget上绘制/绘画顶部的小部件

5

我在Qt中有一个继承自QDockWidget的类,并且该类包含另一个小部件。 是否有可能在我的QDockWidget继承类中定义一个函数,以在包含的小部件顶部绘制东西?就像绘画独立于包含的小部件,但与继承类链接一样。

谢谢

3个回答

10
当然可以。实际上这很简单。您需要放置一个子部件,它位于QDockWidget中的所有其他部件之上。为此,它必须是您添加到dockwidget的最后一个子部件。该部件不能绘制其背景,因此可以在dockwidget的任何子代上方绘制。该部件的大小必须跟踪父部件的大小。
下面是一个自包含的示例。 示例的屏幕截图
// https://github.com/KubaO/stackoverflown/tree/master/questions/overlay-line-11034838
#include <QtGui>
#if QT_VERSION > QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif

class Line : public QWidget {
protected:
   void paintEvent(QPaintEvent *) override {
        QPainter p(this);
        p.setRenderHint(QPainter::Antialiasing);
        p.drawLine(rect().topLeft(), rect().bottomRight());
    }
public:
    explicit Line(QWidget *parent = nullptr) : QWidget(parent) {
       setAttribute(Qt::WA_TransparentForMouseEvents);
    }
};

class Window : public QWidget {
    QHBoxLayout layout{this};
    QPushButton left{"Left"};
    QLabel right{"Right"};
    Line line{this};
protected:
    void resizeEvent(QResizeEvent *) override {
        line.resize(size());
    }
public:
    explicit Window(QWidget *parent = nullptr) : QWidget(parent) {
        layout.addWidget(&left);
        right.setFrameStyle(QFrame::Box | QFrame::Raised);
        layout.addWidget(&right);
        line.raise();
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    Window w;
    w.show();
    return app.exec();
}

0

据我所知:不。

小部件按深度顺序绘制,因此您的QDockWidget派生类绘制的任何内容,在包含的小部件更新时都会被其覆盖(毫无疑问,因为绘画更新会传播到子小部件)。


深度排序绘图正是让你能够使用额外放置在下层窗口小部件上方的小部件画出覆盖在底层窗口小部件上方的内容。这很简单,就算是新的窗口小部件渲染模型也能够胜任(据我所知,这是在Qt 4.1中引入的)。 - Kuba hasn't forgotten Monica
@KubaOber,您说得完全正确,但这不是OP所问的。 OP问的是容器小部件是否可以覆盖子小部件-答案是否定的。 您的解决方案是一种可能的解决方法,但它并不涉及QDockWidget派生类绘制包含小部件,因此它不能回答OP的问题。 - cmannett85
1
它确实提供了一个解决方案。容器小部件可以自由地向自身添加子小部件。当然,绘画代码不会进入容器的 paintEvent,但谁在乎呢。 - Kuba hasn't forgotten Monica

0

被接受答案的Python版本:

# Created by BaiJiFeiLong@gmail.com at 2022/1/15 10:22

from PySide2 import QtWidgets, QtGui, QtCore

app = QtWidgets.QApplication()
widget = QtWidgets.QWidget()

line = QtWidgets.QFrame(widget)
line.paintEvent = lambda _: QtGui.QPainter(line).drawLine(line.rect().topLeft(), line.rect().bottomRight())
line.setAttribute(QtCore.Qt.WidgetAttribute.WA_TransparentForMouseEvents)

widget.setLayout(QtWidgets.QGridLayout(widget))
widget.layout().addWidget(QtWidgets.QPushButton("CLICK ME", widget))
widget.resizeEvent = lambda event: line.resize(event.size())

line.raise_()
widget.show()
app.exec_()

请注意,这种方法不适用于 QSplitter,在这种情况下,您应该使用 QMainWindow 作为父窗口小部件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接