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')。这个问题是否有任何样本或类别?
答案 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)。
对于标题,请在布局中使用相邻的QLabel
和QLineEdit
,并在双击/ QLineEdit::editingFinished
时切换可见性,以便一次只能看到一个。
将QLineEdit::editingFinished
连接到设置窗口标题的新插槽,将QDockWidget::windowTitleChanged
连接到设置QLabel
和QLineEdit
文本的插槽。
您还需要在构造和changeEvent(QEvent :: ParentChanged)上将它们初始化为父窗口标题。
您还必须重新实现关闭/停靠按钮,这可能是一种痛苦,但是可行。您需要q_object_cast
parentWidget()
到QDockWidget
并检查QDockWidget::features()
要显示的按钮,并在构造时将它们连接到正确的插槽,并更改父级。您可以使用带有QStyle::StandardPixmap
编辑:设法在我的午休时间打破这个。它的作用就像原始标题栏一样,除非双击用QLineEdit替换标题标签。
#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;
};