PYQT如何编辑主窗口中标签化的QDockWidget的标题?

2024-10-03 17:17:28 发布

您现在位置:Python中文网/ 问答频道 /正文

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')的标题。有这个问题的样本或类吗?在


Tags: importselfinitwindowfirstqtguiqwidgetqtcore
2条回答

以下是@josephirland的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()

这是一个相当复杂的工作,但是当你需要替换默认的qt部件时,你会得到这样的结果。只需在某个地方添加一个按钮/菜单项来启动一个对话框并调用QDockWidget::setWindowTitle();您还可以在QDockWidget上安装一个事件过滤器,并捕获双击QMouseEvent来启动对话框。在

不管怎样,如果有点牵连的话,这是完全可行的。在

摘要

您可以为dock小部件创建一个新的标题栏小部件(请参见http://doc.qt.io/qt-4.8/qdockwidget.html#setTitleBarWidget)。在

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

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

您还必须重新实现close/dock按钮,这可能是一个痛苦的问题,但是可行的。您需要q_object_castparentWidget()QDockWidget并检查QDockWidget::features()以确定要显示哪些按钮,并将它们连接到构造时的正确插槽,并且父项已更改。您可以使用带有QStyle::StandardPixmap图标的工具按钮

祝你好运

编辑:在我午休的时候把这事搞砸了。它的行为与原始标题栏类似,只是双击会将标题标签替换为QLineEdit。在

< H2> 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;
};

相关问题 更多 >