Placing a widget in QMainWindow, how to position i

2020-04-18 03:47发布

问题:

I'm using QGridLayout, and by using the setCentralWidget function, the row and column (0,0) start in the center of the window which leaves a lot of empty space.

How can I get it centered but beginning from the top of the window and not in the middle?

I'm pretty new to Qt, and was wondering if I'm handling it all wrong? Should I instead make a new class for QWidget?

class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'Data visualizing'
        self.left = 50
        self.top = 50
        self.width = 300
        self.height = 100
        self.initUI()

    def initUI(self):
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)

        # Create textbox
        self.textbox = QLineEdit(self)
        self.textbox.setReadOnly(True)

        # Create textbox 2
        self.textbox2 = QLineEdit(self)
        self.textbox2.setReadOnly(True)

        # Create button
        self.button = QPushButton('Load file 1', self)
        self.button.setToolTip('Click here to browse for the first data file')
        self.button.clicked.connect(self.on_click)

        # Create button 2
        self.button2 = QPushButton('Load file 2', self)
        self.button2.setToolTip('Click here to browse for the first data file')
        self.button2.clicked.connect(self.on_click)

        grid = QGridLayout()

        grid.addWidget(self.textbox, 0, 0, 0, 3)
        grid.addWidget(self.textbox2, 0, 3, 0, 3)
        grid.addWidget(self.button, 1, 1, 1, 1)
        grid.addWidget(self.button2, 1, 4, 1, 1)

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.centralWidget().setLayout(grid)
        self.show()

    def openFileNameDialog(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getOpenFileName(self, "QFileDialog.getOpenFileName()", "",
                                                  "All Files (*);;Comma seperated files (*.csv)", options=options)
        if fileName:
            self.textbox.setText(fileName)
            print(fileName)

    @pyqtSlot()
    def on_click(self):
        self.openFileNameDialog()
        print('PyQt5 button click')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

回答1:

You have to establish a Stretch in row 2, but before that you must correct the rowSpan in:

grid.addWidget(self.textbox, 0, 0, 0, 3)
grid.addWidget(self.textbox2, 0, 3, 0, 3)

To understand, let's review the docs:

void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = ...)

This is an overloaded function.

This version adds the given widget to the cell grid, spanning multiple rows/columns. The cell will start at fromRow, fromColumn spanning rowSpan rows and columnSpan columns. The widget will have the given alignment.

If rowSpan and/or columnSpan is -1, then the widget will extend to the bottom and/or right edge, respectively.

That is, the rowSpan indicates how many rows the widget will occupy, but you are indicating it to 0 so the size will no longer be handled by the layout but only the position, you must change it to 1.

import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class App(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'Data visualizing'
        self.left, self.top, self.width, self.height = 50, 50, 300, 100
        self.initUI()

    def initUI(self):
        self.central_widget = QtWidgets.QWidget()
        self.setCentralWidget(self.central_widget)

        # Create textboxs
        self.textbox = QtWidgets.QLineEdit(readOnly=True)
        self.textbox2 = QtWidgets.QLineEdit(readOnly=True)

        # Create buttons
        self.button = QtWidgets.QPushButton('Load file 1', 
            toolTip = 'Click here to browse for the first data file')
        self.button.clicked.connect(self.on_click)
        self.button2 = QtWidgets.QPushButton('Load file 2',
            toolTip = 'Click here to browse for the first data file')
        self.button2.clicked.connect(self.on_click)

        grid = QtWidgets.QGridLayout(self.centralWidget())

        grid.addWidget(self.textbox, 0, 0, 1, 3)
        grid.addWidget(self.textbox2, 0, 3, 1, 3)
        grid.addWidget(self.button, 1, 1, 1, 1)
        grid.addWidget(self.button2, 1, 4, 1, 1)
        grid.setRowStretch(2, 1)

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.show()

    def openFileNameDialog(self):
        options = QtWidgets.QFileDialog.Options()
        options |= QtWidgets.QFileDialog.DontUseNativeDialog
        fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self, "QFileDialog.getOpenFileName()", "",
                                                  "All Files (*);;Comma seperated files (*.csv)", options=options)
        if fileName:
            self.textbox.setText(fileName)
            print(fileName)

    @QtCore.pyqtSlot()
    def on_click(self):
        self.openFileNameDialog()
        print('PyQt5 button click')

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()