PyQt5 QMainWindow,QDockWidget,适合使用screenize自动调整大小

Pav*_*l.D 6 python qdockwidget python-3.x qmainwindow pyqt5

QMainWindow用菜单栏和4 创建了一个dockable widgets.第一个dockwidget内容multipletabs,第二个是Qpainter widget,第三个是Matlabplot第四个pdf report.

当我运行代码时,如下所示.

在此输入图像描述

我希望如下.

在此输入图像描述

我想在任何屏幕上运行时自动将屏幕划分为四个小部件,并且我希望有标签来调整其内容的大小.

或者你有更好的想法有这样的小部件,欢迎你来.

更新代码

Qdockwidget的大小调整带来了这篇文章.似乎Qt Qdockwidget调整大小已经成为很久以前的问题了.我觉得用Qdockwidget编写我的Qmainwindow非常困难,它可以根据其内容适合并调整大小,换句话说就是子小部件.根据Qt文档,Qdockwidget调整并尊重子窗口小部件的大小.直接问题,我的主窗口有4个qdockwidgets,我想根据内容调整它们.

到目前为止我尝试过和使用过的东西.我使用了以下尺寸功能.

self.sizeHint, self.minimumSize(), self.maximumSize() and self.setFixedSize(self.sizeHint()). 
Run Code Online (Sandbox Code Playgroud)

我可以使用以下代码修复第一个Qdockwidget中的内容大小.

self.setFixedSize(self.sizeHint())
Run Code Online (Sandbox Code Playgroud)

上面的代码是在子窗口小部件中编写的Class widgets 但是,尽管需要运行和生成以下代码,但这还不够.

    self.first.setMinimumSize(self.first.sizeHint())
    self.grid.setMinimumSize(self.grid.sizeHint())
    self.third.setMinimumSize(self.third.sizeHint())
    self.adjustSize()
    self.first.setMinimumSize(self.first.minimumSizeHint())
    self.grid.setMinimumSize(self.grid.minimumSizeHint())
    self.third.setMinimumSize(self.third.minimumSizeHint())
Run Code Online (Sandbox Code Playgroud)

注意到仍然我的dockwindow不会根据子窗口小部件调整大小.Dockwidget扩展和增加.有人可能会问,Qdockwidgets可以安排和控制resizeDocks().使用并尝试了此代码行,但仍未获得所需的行为.

我一直在环顾四周,可以找到一些相关的问题.

C++以编程方式调整停靠的Qt QDockWidget的大小?

在调整大小时强制QDockWidget的行为类似于中央小部件

创建一个调整其内容大小的QDockWidget

那些问题并没有解决我的问题.

可视化我的代码启动

1-代码运行并在屏幕上显示.

在此输入图像描述

2-首次运行软件需要和想要显示.

在此输入图像描述

3-当tabwidgets之间的用户选项卡想要调整其内容时,如下图所示.

在此输入图像描述

4-代码如下.

import sys, os
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget, 
QDesktopWidget, QApplication, QAction, QFileDialog,QColorDialog
from PyQt5.QtWidgets import QPushButton, QMessageBox, QDockWidget, 
QTabWidget, QVBoxLayout, QGroupBox, QHBoxLayout, QFrame, QSplitter
from PyQt5.QtWidgets import QTableWidget, QRadioButton, QListWidget, 
QCheckBox, QTextEdit, QDialog, QSizePolicy
from PyQt5.QtCore import QSize, Qt, QFileInfo, QFile
from PyQt5.QtGui import QIcon, QKeySequence, QPainter, QPalette, QPen, 
QBrush, QTextCursor, QFont

import matplotlib.pyplot as plt
#plt.style.use('ggplot')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import seaborn as sns


iconroot = os.path.dirname(__file__)

class mywindow(QMainWindow):
    def __init__(self):
        super(mywindow, self).__init__()

        self.setMinimumSize(QSize(1200,800))
        self.setWindowTitle('My Graphic Window')

        centralWidget = QWidget(self)
        self.setCentralWidget(centralWidget)

        gridLayout = QGridLayout(self)
        centralWidget.setLayout(gridLayout)

        qtRectangle = self.frameGeometry()
        centerPoint = QDesktopWidget().availableGeometry().center()
        qtRectangle.moveCenter(centerPoint)
        self.move(qtRectangle.topLeft())


        imageroot = QFileInfo(__file__).absolutePath()

        # Greate new action
        newaction = QAction(QIcon(imageroot +'/images/new.png'), '&New', self)
        newaction.setShortcut('Ctrl+N')
        newaction.setStatusTip('New document')
        newaction.triggered.connect(self.newCall) 


        # Greate menu bar and add action
        menubar = self.menuBar()
        filemenu = menubar.addMenu('&Test')
        filemenu.addAction(newaction)


        # Get current screen geometry
        self.Screen = QtWidgets.QDesktopWidget().screenGeometry()
        print(self.Screen, self.Screen.height(), self.Screen.width())


#    def createToolbar(self):
        self.filetoolbar = self.addToolBar('File')
        self.filetoolbar.addAction(newaction)


        self.topleftdockwindow()
        self.toprightdockwindow()



    def newCall(self):
        print('New')


    # Greate dockable subwindow. 

    def topleftdockwindow(self):
        topleftwindow = QDockWidget ('Info',self)
        # Stick window to left or right
        topleftwindow.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.addDockWidget(Qt.TopDockWidgetArea, topleftwindow)

        topleftwindow.setWidget(createtabwidget())
        topleftwindow.resize( topleftwindow.minimumSize() )

        bottomleftwindow = QDockWidget("Matplot",self)
        bottomleftwindow.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.addDockWidget(Qt.BottomDockWidgetArea, bottomleftwindow)
        bottomleftwindow.setWidget(createplotwidget())
        self.setDockNestingEnabled(True)     
        topleftwindow.resize( topleftwindow.minimumSize() )

        self.splitDockWidget(topleftwindow, bottomleftwindow , Qt.Vertical)
        #self.resizeDocks((topleftwindow, bottomleftwindow), (40,20), 
#Qt.Horizontal)


        # Greate topright dockwindow. 

    def toprightdockwindow(self):
        toprightdock = QDockWidget ('Plot',self)
        toprightdock = QDockWidget ('Plot',self)
        toprightdock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.addDockWidget(Qt.TopDockWidgetArea, toprightdock)
        #self.setDockOptions(self.AnimatedDocks | self.AllowNestedDocks)
        toprightdock.setWidget(createpaintwidget())
        toprightdock.setFloating( True )
        bottomrightdock = QDockWidget("Technical report",self)
        bottomrightdock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.addDockWidget(Qt.BottomDockWidgetArea, bottomrightdock)  
        bottomrightdock.setWidget(QtWidgets.QListWidget())
        self.splitDockWidget(toprightdock, bottomrightdock, Qt.Vertical)




class createpaintwidget(QWidget):
    def __init__(self):
        super().__init__()      
        self.setBackgroundRole(QPalette.Base)       
        self.setAutoFillBackground(True)
        self.sizeHint()
        self.adjustSize()

    def paintEvent(self, event):
        self.pen = QPen()
        self.brush = QBrush(Qt.gray,Qt.Dense7Pattern)
        painter = QPainter(self)
        painter.setPen(self.pen)
        painter.setBrush(self.brush)
        painter.drawRect(100,100,250,250)
        painter.setBrush(QBrush())
        painter.drawEllipse(400,100,200,200)


class createplotwidget(QWidget):
    def __init__(self):
        super().__init__()

        self.initializewidget()
        self.plot1()
        self.setMaximumSize(self.sizeHint())
        self.adjustSize()    

    def initializewidget(self):
        self.setWindowTitle("Plotting M&N")
        gridlayout = QGridLayout()
        self.setLayout(gridlayout)

        self.figure = plt.figure(figsize=(15,5))
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas,self)
        gridlayout.addWidget(self.canvas,1,0,1,2)
        gridlayout.addWidget(self.toolbar,0,0,1,2)


    def plot1(self):
 #        sns.set()
        ax = self.figure.add_subplot(111)
        x = [i for i in range(100)]
        y = [i**2 for i in x]
        ax.plot(x,y, 'b.-')
        ax.set_title('Quadratic Plot')
        self.canvas.draw()



class createtextdocument(QWidget):
    def __init__(self):
        super().__init__()

        self.textedit()

    def textedit(self):        
        self.textedit = QTextEdit()
        self.cursor = self.textedit.textCursor()


class createtabwidget(QDialog):
    def __init__(self):
        super().__init__()

        # Greate tabs in dockable window        
        tab = QTabWidget()

        scroll = QScrollArea()
        ncroll = QScrollArea()
        mcroll = QScrollArea()
        self.first = firsttabgeometry()
        self.grid = Grid()
        self.third = thirdtabloads()

        scroll.setWidget(self.first)
        ncroll.setWidget(self.grid)
        mcroll.setWidget(self.third)
        scroll.setWidgetResizable(True)

        self.first.setMinimumSize(self.first.sizeHint())
        self.grid.setMinimumSize(self.grid.sizeHint())
        self.third.setMinimumSize(self.third.sizeHint())
        self.adjustSize()
        self.first.setMinimumSize(self.first.minimumSizeHint())
        self.grid.setMinimumSize(self.grid.minimumSizeHint())
        self.third.setMinimumSize(self.third.minimumSizeHint())

        # Adding multiple tabslides         
        tab.addTab(self.first,'One')
        tab.addTab(self.grid,'Two')
        tab.addTab(self.third,'Three')
        tab.setFont(QFont("Georgia",10,QFont.Normal))

        vboxlayout = QVBoxLayout()
        vboxlayout.addWidget(tab)
        self.setLayout(vboxlayout)


class firsttabgeometry(QWidget):
    def __init__(self):
        super().__init__()
        self.setFixedSize(self.sizeHint())

        iconroot = QFileInfo(__file__).absolutePath()
        font = QFont("Georgia",10,QFont.Normal)

        # Add widget and buttons to tabs
        sectiontypegroupbox = QGroupBox('&One',self)
        sectiontypegroupbox.setFont(QFont("Georgia",10,QFont.Normal))

        tab1button = QPushButton('')
        tab1button.setIcon(QIcon(iconroot +'/images/circularcolumn'))
        tab1button.setIconSize(QSize(60,60))
        tab1button.clicked.connect(self.One)


        squarebutton = QPushButton('')
        squarebutton.setIcon(QIcon(iconroot +'/images/squarecolumn'))
        squarebutton.setIconSize(QSize(60,60))
        squarebutton.clicked.connect(self.Two)

        wallbutton = QPushButton("")
        wallbutton.setIcon(QIcon(iconroot +'/images/wall'))
        wallbutton.setIconSize(QSize(60,60))
        wallbutton.clicked.connect(self.Three)


        circularlabel = QLabel("    One",self)




    circularlabel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
        circularlabel.setFont(font)
        sclabel = QLabel("    Two",self)
        sclabel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
        sclabel.setFont(font)

        walllabel = QLabel("    Three",self)
        walllabel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
        walllabel.setFont(font)


        bottomgroupbox = QGroupBox("Group 2")
        vboxlayout = QHBoxLayout()
        vboxlayout.addStretch()
        radiobutton2 = QRadioButton("Radio Button")
        radiobutton3 = QRadioButton("Radio Button")
        testbutton2 = QPushButton('Test Button 2')
        vboxlayout.addWidget(radiobutton2)
        vboxlayout.addWidget(radiobutton3)
        vboxlayout.addWidget(testbutton2)


        bottomgroupbox.setLayout(vboxlayout)      

        mainlayout = QGridLayout()

        mainlayout.addWidget(tab1button,0,0)
        mainlayout.addWidget(circularlabel,0,1)
        mainlayout.addWidget(squarebutton,1,0)
        mainlayout.addWidget(sclabel,1,1)
        mainlayout.addWidget(wallbutton,2,0)
        mainlayout.addWidget(walllabel,2,1)
        mainlayout.setContentsMargins(200,50,50,50)
        sectiontypegroupbox.setLayout(mainlayout)

        gridlayout = QGridLayout()
        gridlayout.addWidget(sectiontypegroupbox,1,0)
        gridlayout.setContentsMargins(25,25,25,25)
        self.setLayout(gridlayout)


    def One(self):
        print('One')

    def Two(self):
        print('Two')

    def Three(self):
        print('Three')


class FooWidget(QtWidgets.QWidget):
    def __init__(self, path_icon, text, checked=False, parent=None):
        super(FooWidget, self).__init__(parent)
        lay = QtWidgets.QVBoxLayout(self)

        pixmap = QtGui.QPixmap(os.path.join(iconroot, path_icon))
        pixmap_label = QtWidgets.QLabel()
        pixmap_label.resize(150, 150)
        pixmap_label.setPixmap(pixmap.scaled(pixmap_label.size(), QtCore.Qt.KeepAspectRatio))

        text_label = QtWidgets.QLabel(text)
        checkbox = QtWidgets.QCheckBox(checked=checked)

        lay.addWidget(pixmap_label)
        lay.addWidget(text_label)
        lay.addWidget(checkbox)


class Grid(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Grid, self).__init__(parent)
        self.setFixedSize(self.sizeHint())
        font = QFont("Georgia",8,QFont.Normal)
        lay = QtWidgets.QHBoxLayout(self)

        icons = ["images/fixed-fixed.png", 
                 "images/pinned-pinned.png",
                 "images/fixed-free.png",
                 "images/fixed-pinned.png"]

        texts = ["Ley = 1.0 L\nLec = 1.0 L",
             "Ley = 0.699 L\nLec = 0.699 L",
             "Ley = 2.0 L\nLec = 2.0 L",
             "Ley = 0.5 L\nLec = 0.5 L"]

        for path_icon, text in zip(icons, texts):
            w = FooWidget(os.path.join(iconroot, path_icon), text)
            lay.addWidget(w)



class thirdtabloads(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(thirdtabloads, self).__init__(parent)     
        self.adjustSize()
        table = loadtable()


        add_button = QtWidgets.QPushButton("Add")
        add_button.clicked.connect(table._addrow)

        delete_button = QtWidgets.QPushButton("Delete")
        delete_button.clicked.connect(table._removerow)

        copy_button = QtWidgets.QPushButton("Copy")
        copy_button.clicked.connect(table._copyrow)

        button_layout = QtWidgets.QVBoxLayout()
        button_layout.addWidget(add_button, alignment=QtCore.Qt.AlignBottom)
        button_layout.addWidget(delete_button, alignment=QtCore.Qt.AlignTop)
        button_layout.addWidget(copy_button, alignment=QtCore.Qt.AlignTop )

        tablehbox = QtWidgets.QHBoxLayout()
        tablehbox.setContentsMargins(10,10,10,10)
        tablehbox.addWidget(table)

        grid = QtWidgets.QGridLayout(self)
        grid.addLayout(button_layout, 0, 1)
        grid.addLayout(tablehbox, 0, 0) 


def copy_widget(w):
    if isinstance(w, QtWidgets.QWidget):
        new_w = type(w)()
        if isinstance(w, QtWidgets.QComboBox):
            vals = [w.itemText(ix) for ix in range(w.count())]
            new_w.addItems(vals)
        return new_w


class loadtable(QtWidgets.QTableWidget):
    def __init__(self, parent=None):
        super(loadtable, self).__init__(1, 5, parent)

        self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))   
        headertitle = ("Load Name","N [kN]","My [kNm]","Mz [kNm]","Load Type")
        self.setHorizontalHeaderLabels(headertitle)

        self.verticalHeader().hide()
        self.horizontalHeader().setHighlightSections(False)



   self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed)
        self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
        self.setColumnWidth(0, 130)

        combox_lay = QtWidgets.QComboBox(self)
        combox_lay.addItems(["ULS","SLS"])
        self.setCellWidget(0, 4, combox_lay)


        self.cellChanged.connect(self._cellclicked)


    @QtCore.pyqtSlot(int, int)
    def _cellclicked(self, r, c):
        it = self.item(r, c)
        it.setTextAlignment(QtCore.Qt.AlignCenter) 

    @QtCore.pyqtSlot()
    def _addrow(self):
        rowcount = self.rowCount()
        self.insertRow(rowcount)
        combox_add = QtWidgets.QComboBox(self)
        combox_add.addItems(["ULS","SLS"])
        self.setCellWidget(rowcount, 4, combox_add)

    @QtCore.pyqtSlot()
    def _removerow(self):
        if self.rowCount() > 0:
            self.removeRow(self.rowCount()-1)


    @QtCore.pyqtSlot()
    def _copyrow(self):
        r = self.currentRow()
        if 0 <= r < self.rowCount():
            cells = {"items": [], "widgets": []}
            for i in range(self.columnCount()):
                it = self.item(r, i)
                if it:
                    cells["items"].append((i, it.clone()))
                w = self.cellWidget(r, i)
                if w:
                    cells["widgets"].append((i, copy_widget(w)))
            self.copy(cells, r+1)

    def copy(self, cells, r):
        self.insertRow(r)
        for i, it in cells["items"]:
            self.setItem(r, i, it)
        for i, w in cells["widgets"]:
            self.setCellWidget(r, i, w)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    app.setStyle("Fusion")
    mainWin = mywindow()
    mainWin.show()
    mainWin.showMaximized()  
    sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)

我很感激你的帮助.

Gre*_*ell 2

如果浮动窗口对您的工具来说不是必需的,那么您可以尝试删除QDockWidget并使用一系列窗口QSplitter。这样,您就可以拥有漂亮的框布局,同时使用选项卡来水平和垂直调整大小,并且当工具整体调整大小时仍然可以正确调整大小。

我的示例在 中PySide2,但您可能需要进行非常小的调整PyQt5(可能只是导入名称):

from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets


class SubWindow(QtWidgets.QWidget):

    def __init__(self, label, parent=None):
        super(SubWindow, self).__init__(parent)

        self.label = QtWidgets.QLabel(label, parent=self)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setStyleSheet("QLabel {font-size:40px;}")

        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addWidget(self.label)
        self.setLayout(self.main_layout)


class MainWindow(QtWidgets.QWidget):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.sub_win_1 = SubWindow("1", parent=self)
        self.sub_win_2 = SubWindow("2", parent=self)
        self.sub_win_3 = SubWindow("3", parent=self)
        self.sub_win_4 = SubWindow("4", parent=self)

        self.sub_splitter_1 = QtWidgets.QSplitter(QtCore.Qt.Horizontal, parent=self)
        self.sub_splitter_1.addWidget(self.sub_win_1)
        self.sub_splitter_1.addWidget(self.sub_win_2)

        self.sub_splitter_2 = QtWidgets.QSplitter(QtCore.Qt.Horizontal, parent=self)
        self.sub_splitter_2.addWidget(self.sub_win_3)
        self.sub_splitter_2.addWidget(self.sub_win_4)

        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical, parent=self)
        self.splitter.addWidget(self.sub_splitter_1)
        self.splitter.addWidget(self.sub_splitter_2)

        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addWidget(self.splitter)
        self.setLayout(self.main_layout)

        self.setWindowTitle("Layout example")
        self.resize(500, 500)


inst = MainWindow()
inst.show()
Run Code Online (Sandbox Code Playgroud)

这会给你这样的东西:

在此输入图像描述

现在,顶部/底部水平拆分器单独运行,但您可以轻松地将它们与事件绑定在一起。

希望有帮助!