PYQT如何编辑在MainWindow中标记的QDockWidget的标题?

时间:2016-11-28 08:27:05

标签: python python-3.x pyqt pyqt4

from PyQt4 import QtCore, QtGui

class Window(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)

        self.centralContent = QtGui.QMainWindow()

        self.setCentralWidget(self.centralContent)

        self.centralContent.firstTabWidget = QtGui.QWidget()
        self.centralContent.firstTabDock = QtGui.QDockWidget("first")
        self.centralContent.firstTabDock.setWidget(self.centralContent.firstTabWidget)
        self.centralContent.addDockWidget(QtCore.Qt.LeftDockWidgetArea,self.centralContent.firstTabDock)
        self.centralContent.secondTabWidget = QtGui.QWidget()
        self.centralContent.secondTabDock = QtGui.QDockWidget("second")
        self.centralContent.secondTabDock.setWidget(self.centralContent.secondTabWidget)
        self.centralContent.addDockWidget(QtCore.Qt.LeftDockWidgetArea,self.centralContent.secondTabDock)

        self.centralContent.tabifyDockWidget(self.centralContent.firstTabDock, self.centralContent.secondTabDock)


if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    app.exec_()

这是我的示例代码。我想用鼠标双击编辑DockWidget的标题('first','second')。这个问题是否有任何样本或类别?

2 个答案:

答案 0 :(得分:4)

这是@JosephIreland解决方案的PyQt4端口(有一些改进):

class DockTitleBar(QtGui.QWidget):
    def __init__(self, dockWidget):
        super(DockTitleBar, self).__init__(dockWidget)

        boxLayout = QtGui.QHBoxLayout(self)
        boxLayout.setSpacing(1)
        boxLayout.setMargin(1)

        self.titleLabel = QtGui.QLabel(self)
        self.titleEdit = QtGui.QLineEdit(self)
        self.titleEdit.hide()
        self.titleEdit.editingFinished.connect(self.finishEdit)

        iconSize = QtGui.QApplication.style().standardIcon(
            QtGui.QStyle.SP_TitleBarNormalButton).actualSize(
                QtCore.QSize(100, 100))
        buttonSize = iconSize + QtCore.QSize(4, 4)

        self.dockButton = QtGui.QToolButton(self)
        self.dockButton.setIcon(QtGui.QApplication.style().standardIcon(
            QtGui.QStyle.SP_TitleBarNormalButton))
        self.dockButton.setMaximumSize(buttonSize)
        self.dockButton.setAutoRaise(True)
        self.dockButton.clicked.connect(self.toggleFloating)

        self.closeButton = QtGui.QToolButton(self)
        self.closeButton.setMaximumSize(buttonSize)
        self.closeButton.setAutoRaise(True)
        self.closeButton.setIcon(QtGui.QApplication.style().standardIcon(
            QtGui.QStyle.SP_DockWidgetCloseButton))
        self.closeButton.clicked.connect(self.closeParent)

        boxLayout.addSpacing(2)
        boxLayout.addWidget(self.titleLabel)
        boxLayout.addWidget(self.titleEdit)
        boxLayout.addStretch()
        boxLayout.addSpacing(5)
        boxLayout.addWidget(self.dockButton)
        boxLayout.addWidget(self.closeButton)

        dockWidget.featuresChanged.connect(self.onFeaturesChanged)

        self.onFeaturesChanged(dockWidget.features())
        self.setTitle(dockWidget.windowTitle())

        dockWidget.installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.WindowTitleChange:
            self.setTitle(source.windowTitle())
        return super(DockTitleBar, self).eventFilter(source, event)

    def startEdit(self):
        self.titleLabel.hide()
        self.titleEdit.show()
        self.titleEdit.setFocus()

    def finishEdit(self):
        self.titleEdit.hide()
        self.titleLabel.show()
        self.parent().setWindowTitle(self.titleEdit.text())

    def onFeaturesChanged(self, features):
        if not features & QtGui.QDockWidget.DockWidgetVerticalTitleBar:
            self.closeButton.setVisible(
                features & QtGui.QDockWidget.DockWidgetClosable)
            self.dockButton.setVisible(
                features & QtGui.QDockWidget.DockWidgetFloatable)
        else:
            raise ValueError('vertical title bar not supported')

    def setTitle(self, title):
        self.titleLabel.setText(title)
        self.titleEdit.setText(title)

    def toggleFloating(self):
        self.parent().setFloating(not self.parent().isFloating())

    def closeParent(self):
        self.parent().toggleViewAction().setChecked(False)
        self.parent().hide()

    def mouseDoubleClickEvent(self, event):
        if event.pos().x() <= self.titleLabel.width():
            self.startEdit()
        else:
            # this keeps the normal double-click behaviour
            super(DockTitleBar, self).mouseDoubleClickEvent(event)

    def mouseReleaseEvent(self, event):
        event.ignore()

    def mousePressEvent(self, event):
        event.ignore()

    def mouseMoveEvent(self, event):
        event.ignore()

答案 1 :(得分:3)

这是一项相当复杂的工作,但这就是当你需要更换默认的qt部件时所得到的。在某个地方添加一个启动对话框的按钮/菜单项可能更容易,并调用QDockWidget::setWindowTitle();您还可以在QDockWidget上安装事件过滤器,然后双击QMouseEvent以启动对话框。

无论如何,如果有一点参与,它是完全可行的。

摘要

您可以为停靠窗口小部件创建新的标题栏窗口小部件(请参阅http://doc.qt.io/qt-4.8/qdockwidget.html#setTitleBarWidget)。

对于标题,请在布局中使用相邻的QLabelQLineEdit,并在双击/ QLineEdit::editingFinished时切换可见性,以便一次只能看到一个。

QLineEdit::editingFinished连接到设置窗口标题的新插槽,将QDockWidget::windowTitleChanged连接到设置QLabelQLineEdit文本的插槽。 您还需要在构造和changeEvent(QEvent :: ParentChanged)上将它们初始化为父窗口标题。

您还必须重新实现关闭/停靠按钮,这可能是一种痛苦,但是可行。您需要q_object_cast parentWidget()QDockWidget并检查QDockWidget::features()要显示的按钮,并在构造时将它们连接到正确的插槽,并更改父级。您可以使用带有QStyle::StandardPixmap

图标的工具按钮 祝你好运

编辑:设法在我的午休时间打破这个。它的作用就像原始标题栏一样,除非双击用QLineEdit替换标题标签。

C ++ Qt5中的示例(应该很容易移植)

#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QToolButton>
#include <QStyle>
#include <QDockWidget>
#include <QDebug>
#include <QBoxLayout>
#include <QMouseEvent>
#include <QApplication>
#include <QAction>


// usage: dockwidget->setTitleBarWidget(new EditableDockTitleBar(dockwidget));
class EditableDockTitleBar : public QWidget
{
    Q_OBJECT
public:
    explicit EditableDockTitleBar(QDockWidget *parent): QWidget(parent) {
        parentDockWidget = parent;

        auto boxLayout = new QHBoxLayout(this);
        boxLayout->setSpacing(1);
        boxLayout->setMargin(1);
        setLayout(boxLayout);

        titleLabel = new QLabel(this);
        titleEdit = new QLineEdit(this);
        titleEdit->hide();
        connect(titleEdit, &QLineEdit::editingFinished, this, &EditableDockTitleBar::finishEdit);

        QSize iconSize = QApplication::style()->standardIcon(QStyle::StandardPixmap::SP_TitleBarNormalButton).actualSize(QSize(100,100));
        QSize buttonSize = iconSize +  QSize(4,4);
        dockButton = new QToolButton(this);
        dockButton->setIcon(QApplication::style()->standardIcon(QStyle::StandardPixmap::SP_TitleBarNormalButton));
        dockButton->setMaximumSize(buttonSize);
        dockButton->setAutoRaise(true);
        connect (dockButton, &QToolButton::clicked, this, &EditableDockTitleBar::toggleFloating);
        closeButton = new QToolButton(this);
        closeButton->setMaximumSize(buttonSize);
        closeButton->setAutoRaise(true);
        closeButton->setIcon(QApplication::style()->standardIcon(QStyle::StandardPixmap::SP_DockWidgetCloseButton));
        connect (closeButton, &QToolButton::clicked, this, &EditableDockTitleBar::closeParent);

        boxLayout->addSpacing(2);
        boxLayout->addWidget(titleLabel);
        boxLayout->addWidget(titleEdit);
        boxLayout->addSpacing(5);
        boxLayout->addWidget(dockButton);
        boxLayout->addWidget(closeButton);

        auto* dockWidget = parentDockWidget;

        connect(dockWidget, &QDockWidget::featuresChanged, this, &EditableDockTitleBar::onFeaturesChanged);
        connect(dockWidget, &QDockWidget::windowTitleChanged, this, &EditableDockTitleBar::setTitle);

        onFeaturesChanged(dockWidget->features());
        setTitle(dockWidget->windowTitle());

    }

public slots:
    void startEdit() {
        titleLabel->hide();
        titleEdit->show();
        titleEdit->setFocus();
    }
    void finishEdit() {
        titleEdit->hide();
        titleLabel->show();

        parentDockWidget->setWindowTitle(titleEdit->text());

    }

    void onFeaturesChanged(QDockWidget::DockWidgetFeatures features) {
        closeButton->setVisible(features & QDockWidget::DockWidgetClosable);
        dockButton->setVisible(features & QDockWidget::DockWidgetFloatable);
        Q_ASSERT_X(! (features & QDockWidget::DockWidgetVerticalTitleBar), "DockTitleBar::onFeaturesChanged", "vertical title bar not supported");
    }

    void setTitle(const QString& title) {
        titleLabel->setText(title);
        titleEdit->setText(title);
    }

    void toggleFloating() {
        parentDockWidget->setFloating(!parentDockWidget->isFloating());
    }

    void closeParent() {
        parentDockWidget->toggleViewAction()->setChecked(false);
        parentDockWidget->hide();
    }

protected:
    void mouseDoubleClickEvent(QMouseEvent*  ) override{
        startEdit();
    }
    void mouseReleaseEvent(QMouseEvent* e) override {
        e->ignore();
    }
    void mousePressEvent(QMouseEvent* e) override {
        e->ignore();
    }
    void mouseMoveEvent(QMouseEvent* e) override {
        e->ignore();
    }

private:
    QLabel* titleLabel;
    QLineEdit* titleEdit;
    QToolButton* dockButton;
    QToolButton* closeButton;
    QDockWidget* parentDockWidget;
};