在 PyQt6 中触发动作时如何 add/remove 布局?如何更改布局的顺序?

How do I add/remove a layout when triggering action in PyQt6? How do I change the order of a layout?

我正在为一个项目制作一个计算器,我想要它,这样如果我在菜单栏中按下一个动作,它就会变成一个科学计算器,如果我取消选中它,它就会返回到一个基本的计算器。

到目前为止,我已经能够成功地为科学计算器添加按钮,但我希​​望它位于水平布局的左侧(所以基本按钮在右侧,高级按钮在左)但我不知道该怎么做。我也不知道如何在它成为科学计算器后将其恢复为基本计算器。同样出于某种原因,科学计算器的按钮操作似乎无法正常工作(如果我键入一个按钮,它应该向 QLineEdit 添加一个文本)。我很茫然,因为我不知道从这里去哪里。

下面我创建了一个简单的例子来说明我用我的计算器做了什么。

import sys, os
from PyQt6.QtCore import *
from PyQt6.QtWidgets import *
from PyQt6.QtGui import *

class MainWindow(QMainWindow):

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

        self.allbuttons = {}
        #self.setFixedSize(200, 200)
        self.setWindowTitle('Try')

        self.verlayout = QVBoxLayout()
        self.horlayout = QHBoxLayout()

        self.qline()
        self.wid1()


        self.verlayout.addLayout(self.horlayout)

        self.centralwidget = QWidget()
        self.setCentralWidget(self.centralwidget)
        self.centralwidget.setLayout(self.verlayout)

    def qline(self):

        self.line = QLineEdit()
        self.line.setFixedHeight(35)
        self.verlayout.addWidget(self.line)

    def wid1(self):

        buttons = QGridLayout()
        buttondict = {
        'A': (0, 0),
        'B': (0, 1),
        'C': (1, 0),
        'D': (1, 1)
        }

        for btn, pos in buttondict.items():

            self.allbuttons[btn] = QPushButton(btn)

            self.allbuttons[btn].setFixedSize(20, 20)
            buttons.addWidget(self.allbuttons[btn], pos[0], pos[1])

        self.horlayout.addLayout(buttons)

    def wid2(self):

        buttons = QGridLayout()
        buttondict = {
        'E': (0, 0),
        'F': (0, 1),
        'G': (1, 0),
        'H': (1, 1)
        }

        for btn, pos in buttondict.items():

            self.allbuttons[btn] = QPushButton(btn)

            self.allbuttons[btn].setFixedSize(20, 20)
            buttons.addWidget(self.allbuttons[btn], pos[0], pos[1])

        self.horlayout.addLayout(buttons)

class Menu:

    def __init__(self, MainWindow):

        super().__init__()

        self.view = MainWindow

        self.menuBar = QMenuBar()
        self.menuBar.setGeometry(QRect(0, 0, 277, 22))
        self.view.setMenuBar(self.menuBar)
        self.open = QMenu(self.menuBar)
        self.open.setTitle('Open')
        self.menuBar.addAction(self.open.menuAction())
        self.this = QAction(self.menuBar)
        self.this.setText('This')
        self.this.setCheckable(True)
        self.open.addAction(self.this)
        
        self.this.triggered.connect(self.show_new_window)

    def show_new_window(self, checked):
        
        if checked:

            self.view.wid2()
            #self.view.resize(300, 200)

        else:

            pass

app = QApplication(sys.argv)
w = MainWindow()
m = Menu(w)
w.show()
app.exec()

与其删除和添加布局,不如使用 QStackedWidget:

import sys
from functools import cached_property

from PyQt6.QtCore import QRect, Qt
from PyQt6.QtGui import QAction
from PyQt6.QtWidgets import (
    QApplication,
    QGridLayout,
    QLineEdit,
    QMainWindow,
    QMenu,
    QMenuBar,
    QPushButton,
    QStackedWidget,
    QVBoxLayout,
    QWidget,
)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Try")

        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        lay = QVBoxLayout(central_widget)
        lay.addWidget(self.lineedit)

        lay.addWidget(self.stacked_widget, alignment=Qt.AlignmentFlag.AlignCenter)

        maps = [
            {"A": (0, 0), "B": (0, 1), "C": (1, 0), "D": (1, 1)},  # first page
            {"E": (0, 0), "F": (0, 1), "G": (1, 0), "H": (1, 1)},  # second page
        ]

        for m in maps:
            page = self.create_page(m)
            self.stacked_widget.addWidget(page)

    @cached_property
    def stacked_widget(self):
        return QStackedWidget()

    @cached_property
    def lineedit(self):
        le = QLineEdit()
        le.setFixedHeight(35)
        return le

    def create_page(self, map_letters):
        page = QWidget()
        grid_layout = QGridLayout(page)
        for name, pos in map_letters.items():
            button = QPushButton(name)
            button.setFixedSize(20, 20)
            grid_layout.addWidget(button, *pos)
        return page


class Menu:
    def __init__(self, MainWindow):
        super().__init__()
        self.view = MainWindow
        self.menuBar = QMenuBar()
        self.menuBar.setGeometry(QRect(0, 0, 277, 22))
        self.view.setMenuBar(self.menuBar)
        self.open = QMenu(self.menuBar)
        self.open.setTitle("Open")
        self.menuBar.addAction(self.open.menuAction())
        self.this = QAction(self.menuBar)
        self.this.setText("This")
        self.this.setCheckable(True)
        self.open.addAction(self.this)

        self.this.triggered.connect(self.show_new_window)

    def show_new_window(self, checked):
        self.view.stacked_widget.setCurrentIndex(1 if checked else 0)


def main():
    app = QApplication(sys.argv)
    w = MainWindow()
    m = Menu(w)
    w.show()
    app.exec()


if __name__ == "__main__":
    main()