PyQt:将Qdockwidget限制在一个象限,而不是左/右/上/下

时间:2018-07-02 22:48:41

标签: python pyqt4 qdockwidget

我有一个主窗口的三个主要部分,其中左侧(关键数据)应占据整个窗口的高度,而右侧数据应在顶部和底部之间划分。右下角的数据是相关的,但并不重要-这就是为什么我希望它不可对接/可关闭。

Qt documentation显示了C ++中的一个示例,但是由于我没有C ++经验,所以我不知道如何将其转换为python代码。

Qt Designer应用程序将用户限制为“左” /“右” /“上” /“下”,并且限制小部件的最大宽度不允许我占用未使用的空间(即不允许列表小部件位于左移以占据主窗口的整个高度)

编辑:长话短说,要使Qdockwidget进入右下角,您必须在其上方放置另一个停靠小部件(仍然限于Right / Left / Top / Bottom DockWidgetArea)。看完下面的eyllanesc答案后,我将发布两个解决方案。首先是他的代码的简化版本,然后是我最初发布的代码的修改版本。

上面提到的C ++示例中的Eyllanesc翻译:

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 个答案:

答案 0 :(得分:0)

我的回答是示例的翻译:http://doc.qt.io/qt-5/qtwidgets-mainwindows-dockwidgets-example.html,以便将来的读者可以使用它来将C ++代码转换为python。

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_())

完整的示例可以在下面的link中找到。 _rc.py是针对python2编译的,对于python3,您必须重新编译.qrc