PyQt: ограничить Qdockwidget квадрантом, а не влево / вправо / сверху / снизу
У меня есть три основных раздела главного окна, где левая сторона (критические данные) должна занимать всю высоту окна, а данные справа должны быть разделены между верхом и низом. Данные в правом нижнем углу связаны, но не критичны - вот почему я хотел бы, чтобы они были не стыкуемыми / закрываемыми.
Документация Qt показывает пример этого в C++, но я не знаю, как превратить это в код на Python, так как у меня нет опыта работы с C++.
Приложение Qt Designer ограничивает пользователя левым / правым / верхним / нижним, а ограничение максимальной ширины виджета не позволяет мне занимать неиспользуемое пространство (т.е. не позволяет виджету списка слева занимать на всю высоту главного окна)
Изменить: Короче говоря, чтобы получить Qdockwidget в правом нижнем углу, вы должны поместить над ним другой док-виджет (он по-прежнему ограничен Right/Left/Top/Bottom DockWidgetArea). Посмотрев на ответ от eyllanesc ниже, я опубликую два решения. Сначала это упрощенная версия его кода, а затем модифицированная версия кода, которую я первоначально разместил.
Перевод Eyllanesc из примера C++ из упомянутого выше:
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.resize(600, 600)
self.centralWidget = QtGui.QTextEdit()
self.setCentralWidget(self.centralWidget)
# Upper table widget
dock = QtGui.QDockWidget("Upper", self.centralWidget)
dock.setAllowedAreas(QtCore.Qt.RightDockWidgetArea)
self.tableWidget = QtGui.QTableWidget(dock)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(6)
self.tableWidget.setRowCount(7)
for i in range(7):
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(i, item)
self.tableWidget.verticalHeaderItem(i).setText("Item " + str(i + 1))
for i in range(6):
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(i, item)
dock.setWidget(self.tableWidget)
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
# Lower table widget
dock = QtGui.QDockWidget("Lower", self.centralWidget)
self.tableWidget_2 = QtGui.QTableWidget(dock)
self.tableWidget_2.setObjectName("tableWidget_2")
self.tableWidget_2.setColumnCount(6)
self.tableWidget_2.setRowCount(7)
for i in range(7):
item = QtGui.QTableWidgetItem()
self.tableWidget_2.setVerticalHeaderItem(i, item)
for i in range(6):
item = QtGui.QTableWidgetItem()
self.tableWidget_2.setHorizontalHeaderItem(i, item)
dock.setWidget(self.tableWidget_2);
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
self.listWidget = QtGui.QListWidget(self.centralWidget)
self.listWidget.setLayoutDirection(QtCore.Qt.RightToLeft)
self.listWidget.setObjectName("listWidget")
for i in range(10):
item = QtGui.QListWidgetItem()
self.listWidget.addItem(item)
item = self.listWidget.item(i)
item.setText("Item " + str(i + 1))
self.listWidget.setMinimumSize(QtCore.QSize(340, 600))
self.setWindowTitle("Dock Widgets")
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
И модифицированная версия кода, который я первоначально использовал:
from PyQt4 import QtCore, QtGui
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtGui.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.listWidget = QtGui.QListWidget(self.centralwidget)
self.listWidget.setObjectName("listWidget")
self.gridLayout.addWidget(self.listWidget, 0, 0, 1, 1)
self.listWidget.setLayoutDirection(QtCore.Qt.RightToLeft)
for i in range(10):
item = QtGui.QListWidgetItem()
self.listWidget.addItem(item)
item = self.listWidget.item(i)
item.setText("Item " + str(i + 1))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.dockWidget = QtGui.QDockWidget(MainWindow)
self.dockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable)
self.dockWidget.setObjectName("dockWidget")
self.dockWidgetContents = QtGui.QWidget()
self.dockWidgetContents.setObjectName("dockWidgetContents")
self.tableWidget = QtGui.QTableWidget(self.dockWidgetContents)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(6)
self.tableWidget.setRowCount(7)
for i in range(7):
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(i, item)
self.tableWidget.verticalHeaderItem(i).setText("Item " + str(i + 1))
for i in range(6):
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(i, item)
self.gridLayout_2 = QtGui.QGridLayout(self.dockWidgetContents)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout_2.addWidget(self.tableWidget, 0, 0, 1, 1)
self.dockWidget.setWidget(self.dockWidgetContents)
MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.dockWidget)
self.dockWidget_2 = QtGui.QDockWidget(MainWindow)
self.dockWidget_2.setFeatures(QtGui.QDockWidget.DockWidgetClosable|QtGui.QDockWidget.DockWidgetFloatable)
self.dockWidget_2.setObjectName("dockWidget_2")
self.dockWidgetContents_2 = QtGui.QWidget()
self.dockWidgetContents_2.setObjectName("dockWidgetContents_2")
self.gridLayout_3 = QtGui.QGridLayout(self.dockWidgetContents_2)
self.gridLayout_3.setObjectName("gridLayout_3")
self.tableWidget_2 = QtGui.QTableWidget(self.dockWidgetContents)
self.tableWidget_2.setObjectName("tableWidget_2")
self.tableWidget_2.setColumnCount(6)
self.tableWidget_2.setRowCount(7)
for i in range(7):
item = QtGui.QTableWidgetItem()
self.tableWidget_2.setVerticalHeaderItem(i, item)
for i in range(6):
item = QtGui.QTableWidgetItem()
self.tableWidget_2.setHorizontalHeaderItem(i, item)
self.gridLayout_3.addWidget(self.tableWidget_2, 0, 0, 1, 1)
self.dockWidget_2.setWidget(self.dockWidgetContents_2)
MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.dockWidget_2)
MainWindow.setWindowTitle("MainWindow")
QtCore.QMetaObject.connectSlotsByName(MainWindow)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())## Heading ##
1 ответ
Мой ответ - перевод примера: http://doc.qt.io/qt-5/qtwidgets-mainwindows-dockwidgets-example.html, поэтому будущие читатели могут использовать его для перевода кода C ++ в питон.
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.textEdit = QtGui.QTextEdit()
self.setCentralWidget(self.textEdit)
self.createActions()
self.createStatusBar()
self.createDockWindows()
self.setWindowTitle("Dock Widgets")
self.newLetter()
self.setUnifiedTitleAndToolBarOnMac(True)
def newLetter(self):
self.textEdit.clear()
cursor = QtGui.QTextCursor(self.textEdit.textCursor())
cursor.movePosition(QtGui.QTextCursor.Start)
topFrame = cursor.currentFrame()
topFrameFormat = topFrame.frameFormat()
topFrameFormat.setPadding(16)
topFrame.setFrameFormat(topFrameFormat)
textFormat = QtGui.QTextCharFormat()
boldFormat = QtGui.QTextCharFormat()
boldFormat.setFontWeight(QtGui.QFont.Bold)
italicFormat = QtGui.QTextCharFormat()
italicFormat.setFontItalic(True)
tableFormat = QtGui.QTextTableFormat()
tableFormat.setBorder(1)
tableFormat.setCellPadding(16)
tableFormat.setAlignment(QtCore.Qt.AlignRight)
cursor.insertTable(1, 1, tableFormat)
cursor.insertText("The Firm", boldFormat)
cursor.insertBlock()
cursor.insertText("321 City Street", textFormat)
cursor.insertBlock()
cursor.insertText("Industry Park")
cursor.insertBlock()
cursor.insertText("Some Country")
cursor.setPosition(topFrame.lastPosition())
cursor.insertText(QtCore.QDate.currentDate().toString("d MMMM yyyy"), textFormat)
cursor.insertBlock()
cursor.insertBlock()
cursor.insertText("Dear ", textFormat)
cursor.insertText("NAME", italicFormat)
cursor.insertText(",", textFormat)
for i in range(3):
cursor.insertBlock()
cursor.insertText("Yours sincerely,", textFormat)
for i in range(3):
cursor.insertBlock()
cursor.insertText("The Boss", textFormat)
cursor.insertBlock()
cursor.insertText("ADDRESS", italicFormat)
def print_(self):
document = self.textEdit.document()
printer = QtGui.QPrinter()
dlg = QtGui.QPrintDialog(printer, self)
if dlg.exec() != QtGui.QDialog.Accepted:
return
document.print_(printer)
self.statusBar().showMessage("Ready", 2000)
def save(self):
fileName = QtGui.QFileDialog.getSaveFileName(self,
"Choose a file name", ".", "HTML document (*.html *.htm)")
if not fileName:
return
file = QtCore.QFile(fileName)
if not file.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
QtGui.QMessageBox.warning(self, "Dock Widgets",
"Cannot write file {}:\n{}."
.format(QtCore.QDir.toNativeSeparators(fileName), file.errorString()))
return
out = QTextStream(file)
QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
out << textEdit.toHtml()
QtGui.QApplication.restoreOverrideCursor()
self.statusBar().showMessage("Saved '{}'".format(fileName), 2000)
def undo(self):
document = self.textEdit.document()
document.undo()
def insertCustomer(self, customer):
if not customer:
return
customerList = customer.split(", ")
document = self.textEdit.document()
cursor = document.find("NAME")
if not cursor.isNull():
cursor.beginEditBlock()
cursor.insertText(customerList[0])
oldcursor = cursor
cursor = document.find("ADDRESS")
if not cursor.isNull():
for c in customerList:
cursor.insertBlock()
cursor.insertText(c)
cursor.endEditBlock()
else:
oldcursor.endEditBlock()
def addParagraph(self, paragraph):
if not paragraph:
return
document = self.textEdit.document()
cursor = document.find("Yours sincerely,")
if cursor.isNull():
return
cursor.beginEditBlock()
cursor.movePosition(QtGui.QTextCursor.PreviousBlock, QtGui.QTextCursor.MoveAnchor, 2)
cursor.insertBlock()
cursor.insertText(paragraph)
cursor.insertBlock()
cursor.endEditBlock()
def about(self):
QtGui.QMessageBox.about(self, "About Dock Widgets",
"The <b>Dock Widgets</b> example demonstrates how to "
"use Qt's dock widgets. You can enter your own text, "
"click a customer to add a customer name and "
"address, and click standard paragraphs to add them.")
def createActions(self):
fileMenu = self.menuBar().addMenu("&File")
fileToolBar = self.addToolBar("File")
newIcon = QtGui.QIcon.fromTheme("document-new", QtGui.QIcon(":/images/new.png"))
newLetterAct = QtGui.QAction(newIcon, "&New Letter", self)
newLetterAct.setShortcuts(QtGui.QKeySequence.New)
newLetterAct.setStatusTip("Create a new form letter")
newLetterAct.triggered.connect(self.newLetter)
fileMenu.addAction(newLetterAct)
fileToolBar.addAction(newLetterAct)
saveIcon = QtGui.QIcon.fromTheme("document-save", QtGui.QIcon(":/images/save.png"))
saveAct = QtGui.QAction(saveIcon, "&Save...", self)
saveAct.setShortcuts(QtGui.QKeySequence.Save)
saveAct.setStatusTip("Save the current form letter")
saveAct.triggered.connect(self.save)
fileMenu.addAction(saveAct)
fileToolBar.addAction(saveAct)
printIcon = QtGui.QIcon.fromTheme("document-print", QtGui.QIcon(":/images/print.png"))
printAct = QtGui.QAction(printIcon,"&Print...", self)
printAct.setShortcuts(QtGui.QKeySequence.Print)
printAct.setStatusTip("Print the current form letter")
printAct.triggered.connect(self.print_)
fileMenu.addAction(printAct)
fileToolBar.addAction(printAct)
fileMenu.addSeparator()
quitAct = fileMenu.addAction("&Quit", self.close)
quitAct.setShortcuts(QtGui.QKeySequence.Quit)
quitAct.setStatusTip("Quit the application")
editMenu = self.menuBar().addMenu("&Edit")
editToolBar = self.addToolBar("Edit")
undoIcon = QtGui.QIcon.fromTheme("edit-undo", QtGui.QIcon(":/images/undo.png"))
undoAct = QtGui.QAction(undoIcon, "&Undo", self)
undoAct.setShortcuts(QtGui.QKeySequence.Undo)
undoAct.setStatusTip("Undo the last editing action")
undoAct.triggered.connect(self.undo)
editMenu.addAction(undoAct)
editToolBar.addAction(undoAct)
self.viewMenu = self.menuBar().addMenu("&View")
self.menuBar().addSeparator()
helpMenu = self.menuBar().addMenu("&Help")
aboutAct = helpMenu.addAction("&About", self.about)
aboutAct.setStatusTip("Show the application's About box")
aboutQtAct = helpMenu.addAction("About &Qt", QtGui.qApp.aboutQt)
aboutQtAct.setStatusTip("Show the Qt library's About box")
def createStatusBar(self):
self.statusBar().showMessage("Ready")
def createDockWindows(self):
dock = QtGui.QDockWidget("Customers", self)
dock.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
self.customerList = QtGui.QListWidget(dock)
self.customerList.addItems([
"John Doe, Harmony Enterprises, 12 Lakeside, Ambleton",
"Jane Doe, Memorabilia, 23 Watersedge, Beaton",
"Tammy Shea, Tiblanka, 38 Sea Views, Carlton",
"Tim Sheen, Caraba Gifts, 48 Ocean Way, Deal",
"Sol Harvey, Chicos Coffee, 53 New Springs, Eccleston",
"Sally Hobart, Tiroli Tea, 67 Long River, Fedula"])
dock.setWidget(self.customerList)
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
self.viewMenu.addAction(dock.toggleViewAction())
dock = QtGui.QDockWidget("Paragraphs", self)
self.paragraphsList = QtGui.QListWidget(dock)
self.paragraphsList.addItems([
"""Thank you for your payment which we have received today.""",
"""Your order has been dispatched and should be with you \
within 28 days.""",
"""We have dispatched those items that were in stock. The \
rest of your order will be dispatched once all the \
remaining items have arrived at our warehouse. No \
additional shipping charges will be made.""",
"""You made a small overpayment (less than $5) which we \
will keep on account for you, or return at your request.""",
"""You made a small underpayment (less than $1), but we have \
sent your order anyway. We'll add this underpayment to \
your next bill.""",
"""Unfortunately you did not send enough money. Please remit \
an additional $. Your order will be dispatched as soon as \
the complete amount has been received.""",
"""You made an overpayment (more than $5). Do you wish to \
buy more items, or should we return the excess to you?"""])
dock.setWidget(self.paragraphsList);
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
self.viewMenu.addAction(dock.toggleViewAction())
self.customerList.currentTextChanged.connect(self.insertCustomer)
self.paragraphsList.currentTextChanged.connect(self.addParagraph)
# import dockwidgets_rc
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Полный пример можно найти по следующей ссылке. _rc.py
компилируется для python2, для python3 вы должны перекомпилировать .qrc
,