首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在运行时在Qt5中替换一个小部件

在运行时在Qt5中替换一个小部件
EN

Stack Overflow用户
提问于 2020-03-13 15:45:28
回答 1查看 123关注 0票数 0

我有一个用python3(.8)制作的.8图形用户界面。它的左边有一个QButtonGroup。按下这些按钮中的一个应该会显示在右侧创建的相关设备QWidget类(此处未显示)。因此主布局中只有两个小部件。

这个代码运行。我知道这些功能在device_clicked中并没有真正的意义,但它只是为了演示一个小的工作代码片段。

代码语言:javascript
运行
复制
import logging
import sys

from PyQt5.QtWidgets import (QApplication, QButtonGroup, QHBoxLayout, QTabBar, QTabWidget,
                             QMainWindow, QPushButton, QVBoxLayout, QWidget, QLabel)

logging.basicConfig(
    format="%(asctime)s,%(msecs)d - %(name)s - %(levelname)s: %(message)s",
    datefmt="%H:%M:%S",
    level=logging.INFO,
)

DEVICES = [("DEV1", QLabel), ("2222", QLabel), ("HUPP", QLabel), ("FOOO", QLabel), ("BOOO", QLabel)]


class MainApp(QMainWindow):
    """Documentation for MainApp(QMainWindow)

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

        self.logger = logging.getLogger("MAIN")
        self.logger.info("Starting main program")

        self.title = "Title"
        self.left = 300
        self.top = 200
        self.width = 1100
        self.height = 600

        self.init_ui()

    def init_ui(self) -> None:
        """
        Initializs the UI
        """
        self.logger.info("Starting UI")

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

        self.main_widget = QWidget()
        self.setCentralWidget(self.main_widget)

        layout = QHBoxLayout()
        self.main_widget.setLayout(layout)

        dev_layout = QVBoxLayout()
        self.devices = QButtonGroup()
        for i, (t, w) in enumerate(DEVICES):
            btn = QPushButton(t)
            self.devices.addButton(btn, i)
            dev_layout.addWidget(btn)

        self.devices.buttonClicked[int].connect(self.device_clicked)

        layout.addLayout(dev_layout, 10)
        layout.addWidget(QLabel("test"), 90)
        self.prev_device_id = 0
        self.devices.button(0).setDown(True)

    def device_clicked(self, btn_id: int) -> None:
        self.logger.info(f"BTN {btn_id} clicked")
        self.devices.button(self.prev_device_id).setDown(False)
        self.devices.button(btn_id).setDown(True)

        # replace gives my an AttributeError: 'QHBoxLayout' object has no attribute 'replace'
        # self.main_widget.layout().replace(DEVICES[self.prev_device_id][1], DEVICES[btn_id][1])

        self.main_widget.layout().takeAt(1)
        self.main_widget.layout().addWidget(DEVICES[btn_id][1](DEVICES[btn_id][0]), 90)
        self.main_widget.layout().update()

        self.prev_device_id = btn_id

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = MainApp()
    main.show()
    app.exec_()

我现在遇到的问题是,旧小部件没有被删除,新小部件被放置在上面,同时显示它们。

是因为MainApp是一个QMainWindow并且有一个self.main_widget = QWidget() centralWidget吗?建议使用setCentralWidget()吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-13 16:56:05

takeAt()只从布局中删除布局项,而不删除其小部件。请注意,我指定了布局项,因为布局使用QLayoutItems,这是布局用于管理其内容的抽象项:布局项可以包含布局本身或小部件。

在任何情况下,在删除小部件(通过删除布局项或通过使用removeWidget()删除小部件本身)之后,您还必须调用deleteLater()

这是必要的,因为即使从布局中删除了一个小部件,小部件仍然有一个父集(设置布局的小部件)。

代码语言:javascript
运行
复制
    layoutItem = self.main_widget.layout().itemAt(1)
    if layoutItem.widget():
        layoutItem.widget().deleteLater()

或者,如果您已经有了对小部件的引用:

代码语言:javascript
运行
复制
    self.someWidget.deleteLater()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60673451

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档