You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5布局求助:如何将文本框垂直排列在按钮网格左侧?

PyQt5布局问题:文本框错位,需垂直排列在按钮网格左侧

我在PyQt5代码中设置了按钮网格布局与文本框布局,按钮可正常显示在指定位置,但文本框始终错位至左上角。需要将这些文本框垂直排列在按钮网格的左侧(对应截图中的黄色矩形区域),尝试多种布局调整方法均无效,求助解决方案。

原代码

import sys
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QVBoxLayout, QHBoxLayout, QSpacerItem, QSizePolicy
from PyQt5 import QtGui, QtCore
from PyQt5.QtGui import QCursor, QFont
from PyQt5.QtCore import Qt


class TransparentButton(QLabel):
    def __init__(self, name, parent=None):
        super().__init__(parent)
        self.setAlignment(Qt.AlignCenter)
        self.setStyleSheet("background-color: transparent; color : white;")
        self.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
        self.setFont(QFont('Arial', 20))
        self.name = name

        self.value = 0
        self.setText('')

    def mousePressEvent(self, event):
        # 判断点击的按钮并设置对应值
        if self.name == "Button 1" or self.name == "Button 3" or self.name == "Button 5" or self.name == "Button 7":
            self.value = 20
        else:
            self.value = 10
        self.update_text()

    def update_text(self):
        self.setText(str(self.value))

class EditableLabel(QLineEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAlignment(Qt.AlignCenter)
        self.setStyleSheet("background-color: transparent; color : white;")
        self.setFont(QFont('Arial', 20))
        self.setPlaceholderText("")


class App(QWidget):

    def __init__(self):
        super().__init__()
        self.init_ui()


    def init_ui(self):
        # 设置背景图片
        pixmap = QPixmap("theme_game.png")
        self.setFixedSize(pixmap.width(), pixmap.height()) # 设置窗口固定大小
        self.setWindowFlags(Qt.FramelessWindowHint) # 去除窗口边框
        self.setAttribute(Qt.WA_TranslucentBackground) # 设置透明背景
        self.label = QLabel(self)
        self.label.setPixmap(pixmap)
        self.label.setGeometry(0, 0, pixmap.width(), pixmap.height())

        # 创建按钮网格
        grid_buttons = QGridLayout(self)
        grid_buttons.setHorizontalSpacing(50)
        grid_buttons.setVerticalSpacing(50)
        names = ['1', 'Bck', 'Button 1', 'Close',
                'Button 3', '8', '9', '/',
                '4', '5', '6', 'Button 5',
                '1', 'Button 7', '3', '-']

        positions = [(i,j) for i in range(4) for j in range(4)]

        for position, name in zip(positions, names):
            if name == '':
                continue
            button = TransparentButton(name)
            grid_buttons.addWidget(button, *position)

        # 创建文本框垂直布局
        vertical_layout = QVBoxLayout()
        for i in range(4):
            text_edit = EditableLabel(self)
            text_edit.setMinimumSize(100, 100)
            text_edit.setMaximumSize(200, 200)
            vertical_layout.addWidget(text_edit)
        vertical_layout.addStretch(1)

        # 组合布局
        lay = QHBoxLayout()
        lay.addLayout(grid_buttons)
        lay.addLayout(vertical_layout)

        # 设置布局边距
        self.layout().setContentsMargins(795, 35, 70, 155)
        self.setLayout(lay)

        # 移动窗口位置
        self.move(500, 200)

        self.showFullScreen()


    def resizeEvent(self, event):
        pixmap = QPixmap("theme_game.png")
        self.setFixedSize(pixmap.width(), pixmap.height())
        self.label.setGeometry(0, 0, pixmap.width(), pixmap.height())


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

当前效果

当前布局效果

期望效果

期望布局效果


解决方案

问题根源

  1. 创建grid_buttons时直接传入self,导致它提前绑定为窗口的主布局,后续再设置lay作为主布局会引发布局冲突。
  2. 主布局lay的添加顺序错误,把按钮网格放在了前面,导致文本框布局逻辑混乱,最终错位到左上角。
  3. 设置布局边距的时机错误,在未设置主布局前调用self.layout(),操作的是提前绑定的grid_buttons,而非最终的主布局。

修改后的代码

import sys
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QVBoxLayout, QHBoxLayout, QSpacerItem, QSizePolicy
from PyQt5 import QtGui, QtCore
from PyQt5.QtGui import QCursor, QFont
from PyQt5.QtCore import Qt


class TransparentButton(QLabel):
    def __init__(self, name, parent=None):
        super().__init__(parent)
        self.setAlignment(Qt.AlignCenter)
        self.setStyleSheet("background-color: transparent; color : white;")
        self.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
        self.setFont(QFont('Arial', 20))
        self.name = name

        self.value = 0
        self.setText('')

    def mousePressEvent(self, event):
        if self.name == "Button 1" or self.name == "Button 3" or self.name == "Button 5" or self.name == "Button 7":
            self.value = 20
        else:
            self.value = 10
        self.update_text()

    def update_text(self):
        self.setText(str(self.value))

class EditableLabel(QLineEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAlignment(Qt.AlignCenter)
        self.setStyleSheet("background-color: transparent; color : white;")
        self.setFont(QFont('Arial', 20))
        self.setPlaceholderText("")


class App(QWidget):

    def __init__(self):
        super().__init__()
        self.init_ui()


    def init_ui(self):
        pixmap = QPixmap("theme_game.png")
        self.setFixedSize(pixmap.width(), pixmap.height())
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.label = QLabel(self)
        self.label.setPixmap(pixmap)
        self.label.setGeometry(0, 0, pixmap.width(), pixmap.height())

        # 修改点1:创建网格布局时不传入self,避免提前绑定窗口布局
        grid_buttons = QGridLayout()
        grid_buttons.setHorizontalSpacing(50)
        grid_buttons.setVerticalSpacing(50)
        names = ['1', 'Bck', 'Button 1', 'Close',
                'Button 3', '8', '9', '/',
                '4', '5', '6', 'Button 5',
                '1', 'Button 7', '3', '-']

        positions = [(i,j) for i in range(4) for j in range(4)]

        for position, name in zip(positions, names):
            if name == '':
                continue
            button = TransparentButton(name)
            grid_buttons.addWidget(button, *position)

        vertical_layout = QVBoxLayout()
        for i in range(4):
            text_edit = EditableLabel(self)
            text_edit.setMinimumSize(100, 100)
            text_edit.setMaximumSize(200, 200)
            vertical_layout.addWidget(text_edit)
        vertical_layout.addStretch(1)

        # 修改点2:调整布局顺序,先加文本框垂直布局(左侧),再加按钮网格(右侧)
        lay = QHBoxLayout()
        lay.addLayout(vertical_layout)
        lay.addLayout(grid_buttons)

        # 修改点3:先设置主布局,再调整边距
        self.setLayout(lay)
        self.layout().setContentsMargins(795, 35, 70, 155)

        self.move(500, 200)
        # 修改点4:移除showFullScreen,避免和固定窗口大小冲突
        self.show()


    def resizeEvent(self, event):
        pixmap = QPixmap("theme_game.png")
        self.setFixedSize(pixmap.width(), pixmap.height())
        self.label.setGeometry(0, 0, pixmap.width(), pixmap.height())


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

关键修改说明

  • 移除grid_buttons创建时的self参数,让布局先独立,再通过主布局整合,避免布局绑定冲突。
  • 调整主布局lay的添加顺序,确保文本框布局显示在左侧,按钮网格在右侧。
  • 调整边距设置的时机,确保作用于最终的主布局,保证整体位置符合预期。
  • 移除showFullScreen(),因为窗口已设置固定大小,全屏模式会覆盖该设置,导致布局混乱。

内容的提问来源于stack exchange,提问作者Nekit Letayev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 22:20:35