简体   繁体   English

Pyqt5-网格布局行为异常

[英]Pyqt5 - grid layout misbehaving

So I'm trying to get a grip on Qt (more specifically, Pyqt), and I want to create a simple feedback form. 因此,我试图掌握Qt(更具体地说是Pyqt),并希望创建一个简单的反馈表。 It should have 应该有

  • a title 一个标题
  • a name ('author') 名称(“作者”)
  • a message 一个消息
  • a send and a cancel button 发送和取消按钮

Let's try without the buttons, first (the App class just provides a button to create a popup. the question concerns the Form class below it): 首先,让我们尝试不使用按钮( App类仅提供一个用于创建弹出窗口的按钮。问题涉及其下方的Form类):

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QDesktopWidget,\
    QHBoxLayout, QVBoxLayout, QGridLayout,\
    QPushButton, QLabel,QLineEdit, QTextEdit,\
    qApp
from PyQt5.QtGui import QIcon


class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 Layout Demo'
        self.popup = None

        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setWindowIcon(QIcon('imgs/python3.png'))

        formButton = QPushButton("show form")
        formButton.clicked.connect(self.showPopup)

        formBox = QHBoxLayout()
        formBox.addWidget(formButton)
        formBox.addStretch(1)

        vbox = QVBoxLayout()
        vbox.addLayout(formBox)
        vbox.addStretch(1)

        # self.setLayout(vbox)  # would work if this was a QWidget

        # instead, define new central widget
        window = QWidget()
        window.setLayout(vbox)
        self.setCentralWidget(window)

        self.center(self)
        self.show()

    @staticmethod
    def center(w: QWidget):
        qr = w.frameGeometry()  # get a rectangle for the entire window

        # center point = center of screen resolution
        cp = QDesktopWidget().availableGeometry().center()

        qr.moveCenter(cp)  # move center of rectangle to cp
        w.move(qr.topLeft())  # move top-left point of window to top-let point of rectangle

    def showPopup(self):
        if self.popup is None:
            self.popup = Form(self)
            self.popup.setGeometry(10, 10, 300, 400)
            self.center(self.popup)

        self.popup.show()


class Form(QWidget):
    def __init__(self, main):
        super().__init__()
        self.initUI()
        self.main = main

    def initUI(self):
        self.setWindowTitle('Feedback')
        self.setWindowIcon(QIcon('imgs/python3.png'))

        title = QLabel('Title')
        author = QLabel('Author')
        message = QLabel('Message')

        titleEdit = QLineEdit()
        authorEdit = QLineEdit()
        messageEdit = QTextEdit()

        grid = QGridLayout()
        grid.setSpacing(10)

        grid.addWidget(title, 1, 0)
        grid.addWidget(titleEdit,1, 1)

        grid.addWidget(author, 2, 0)
        grid.addWidget(authorEdit,2, 1)

        grid.addWidget(message, 3, 0)
        grid.addWidget(messageEdit, 4, 0, 6, 0)

        self.setLayout(grid)

    # probably should delegate to self.main, but bear with me
    def send(self):
        self.main.popup = None
        self.hide()

    def cancel(self):
        self.hide()

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

在此处输入图片说明

Ok, looks about right. 好吧,看起来不错。 There's a bit too much spacing in-between the line edits and the text edit, but since I want to add some buttons below it, that should be be a problem. 行编辑和文本编辑之间的间距太大,但是由于我想在其下方添加一些按钮,因此应该是一个问题。

So I add: 所以我添加:

    sendBtn = QPushButton("send")
    cancelBtn = QPushButton("cancel")

    sendBtn.clicked.connect(self.send)
    cancelBtn.clicked.connect(self.cancel)

    grid.addWidget(sendBtn, 7, 1)
    grid.addWidget(cancelBtn, 7, 2)

which yields 产生

在此处输入图片说明

Now obviously, I forgot to stretch the title and author line edits to the newly introduced column 2. Easy enough to fix but what really bothers me is the placement of the buttons. 现在显然,我忘记了将标题和作者行的编辑内容扩展到新引入的第2列。虽然很容易修复,但真正困扰我的是按钮的位置。

WHY do they show up in the middle of the text edit? 为什么它们显示在文本编辑的中间? I can see how Qt chooses the column size, and why that would lead to the buttons' being of different size, but since the tutorial doesn't actually add buttons to the form, I have no idea how to fix that. 我可以看到Qt如何选择列大小,以及为什么这会导致按钮的大小不同,但是由于本教程实际上并未在表单中添加按钮,因此我不知道如何解决该问题。

I could, of course, simply add boxes: 我当然可以简单地添加框:

sendBtn = QPushButton("send")
cancelBtn = QPushButton("cancel")

sendBtn.clicked.connect(self.send)
cancelBtn.clicked.connect(self.cancel)

btns = QHBoxLayout()
btns.addStretch(1)
btns.addWidget(sendBtn)
btns.addWidget(cancelBtn)

l = QVBoxLayout()
l.addLayout(grid)
l.addLayout(btns)

self.setLayout(l)

With which the popup then actually starts looking closer to something acceptable: 通过该弹出窗口,实际上实际上开始看起来更接近可接受的对象:

在此处输入图片说明

But is there a way to fix this within the grid layout, instead? 但是,有没有办法在网格布局中解决此问题呢?

You seem to have misunderstood the signature of addWidget . 您似乎误解了addWidget的签名。 The second and third arguments specify the row and column that the widget is placed in, whilst the third and fourth specify the row-span and column-span. 第二个和第三个参数指定放置小部件的行和列,而第三个和第四个参数指定行跨度和列跨度。

In your example, the problems start here: 在您的示例中,问题从这里开始:

    grid.addWidget(message, 3, 0)
    grid.addWidget(messageEdit, 4, 0, 6, 0)

where you make the text-edit span six rows and zero columns - which I doubt is what you intended. 您在其中进行文本编辑的范围为六行零列-我怀疑这是您的意图。 Instead, you probably want this: 相反,您可能想要这样:

    grid.addWidget(message, 3, 0, 1, 2)
    grid.addWidget(messageEdit, 4, 0, 1, 2)

which will make the message label and text-edit span the two columns created by the title and author fields above. 这将使消息标签和文本编辑跨越上方标题和作者字段创建的两列。

Now when you add the buttons, they must have a layout of their own, since the top two rows are already determining the width of the two columns. 现在,当您添加按钮时,它们必须具有自己的布局,因为最上面的两行已经确定了两列的宽度。 If you added the buttons directly to the grid, they would be forced to have the same widths as the widgets in the top two rows (or vice versa). 如果将按钮直接添加到网格,则它们将被迫具有与顶部两行中的小部件相同的宽度(反之亦然)。 So the buttons should be added like this: 所以应该这样添加按钮:

    hbox = QHBoxLayout()

    sendBtn = QPushButton("send")
    cancelBtn = QPushButton("cancel")

    sendBtn.clicked.connect(self.send)
    cancelBtn.clicked.connect(self.cancel)

    hbox.addStretch()
    hbox.addWidget(sendBtn)
    hbox.addWidget(cancelBtn)

    grid.addLayout(hbox, 5, 0, 1, 2)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM