RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1454138
Accepted
Djony Cooper
Djony Cooper
Asked:2022-10-05 02:25:41 +0000 UTC2022-10-05 02:25:41 +0000 UTC 2022-10-05 02:25:41 +0000 UTC

动态创建 QPushButton 并随后保存到 ini 文件

  • 772

动态创建按钮的问题。我正在写一个应用程序,我需要:

  1. 动态创建本质上是外部程序快捷方式的按钮。
  2. 如有必要,请移除所需按钮,以便其余按钮根据布局移动。
  3. 将配置保存到 ini 文件,以便在重新启动后保存所有创建的按钮。

现在是什么:

  1. 按钮是根据 Grid 布局动态创建的,可以运行附加到它们的 exe 文件,但只能运行最后附加的那个。
  2. 删除仅适用于最后创建的按钮,方法是用鼠标右键单击它。
  3. 事实证明,将按钮配置保存到 settings.ini 文件 - 但程序启动时我无法提取数据。

如果有人有任何想法,我将不胜感激。我附上了一个最小的工作示例。

main.py 文件:

from PyQt5.QtWidgets import QWidget, QApplication, QGridLayout, QGroupBox, QPushButton, QMessageBox, QMenu
from PyQt5.QtCore import QEvent, QSettings, Qt
from PyQt5.QtGui import QIcon

class Main(QWidget):

    settings = QSettings("settings.ini", QSettings.IniFormat)

    def __init__(self):
        super(Main, self).__init__()
        self.setWindowTitle('Образец')
        self.resize(500, 300)

        grid = QGridLayout()
        grid.addWidget(self.prog_group_box(), 0, 0, 1, 1)
        grid.addWidget(self.b_new_prog(), 1, 0, Qt.AlignRight)

        self.setLayout(grid)

    def prog_group_box(self):
        groupBox1 = QGroupBox(self)
        self.grid_prog = QGridLayout()
        groupBox1.setLayout(self.grid_prog)

        return groupBox1

    def saved_conf(self):
        # Сохранение созданной кнопки в ini файл
        self.settings.setValue('button', self.new_but)
        self.settings.setValue('label', self.click_newprog._leProgLabel.text())
        self.settings.setValue('source', self.click_newprog._leReview.text())
        self.settings.sync()

    # def restore_settings(self):
    # Функция восстановления сохраненного конфига из ini файла
        # test = self.settings.setValue('button')

        # print(f'RESTORE: {test}')

    def delete_setting(self):
        # Функция удаления данных из ini файла с сохраненной конфигурацией
        self.settings = QSettings("settings.ini", QSettings.IniFormat)
        self.settings.remove('button')

    def b_new_prog(self):
        self.b_new_prog = QPushButton(self)
        self.b_new_prog.setText("Добавить")
        self.b_new_prog.setMinimumSize(129, 43)
        self.b_new_prog.clicked.connect(self.click_newprog)

        return self.b_new_prog

    def click_newprog(self):
        from second import Second
        self.click_newprog = Second(self)
        self.click_newprog.show()

    def create_new_button(self):
        self.new_but = QPushButton()
        self.new_but.setFixedSize(70, 70)
        self.new_but.clicked.connect(self.btnClicked)
        self.new_but.setText(self.click_newprog._leProgLabel.text())
        self.grid_prog.addWidget(self.new_but, 0, 0)
        i = self.grid_prog.count() - 1
        self.grid_prog.addWidget(self.new_but, 1 + i // 8, i % 8)
        self.new_but.installEventFilter(self)

    def btnClicked(self):
        import os
        os.startfile(self.click_newprog._leReview.text())

    # Контекстное меню
    def eventFilter(self, source, event):
        if event.type() == QEvent.ContextMenu and source is self.new_but:
            menu = QMenu()
            menu.addAction('Удалить')

            if menu.exec_(event.globalPos()):
                reply = QMessageBox.question(
                    self,
                    'Message', "Вы действительно хотите удалить?",
                    QMessageBox.Yes | QMessageBox.No,
                    QMessageBox.No
                    )
                if reply == QMessageBox.Yes:
                    self.new_but.hide()
                    self.delete_setting()
                else:
                    pass

        return super().eventFilter(source, event)

if __name__ == ('__main__'):
    import sys
    app = QApplication(sys.argv)
    w = Main()
    w.show()
    sys.exit(app.exec_())

第二个.py 文件:

from PyQt5.QtWidgets import (QLabel, QVBoxLayout, QLineEdit, QPushButton,
                             QHBoxLayout, QFileDialog, QMessageBox, QDialog)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont


class Second(QDialog):
    def __init__(self, Main):
        super().__init__()
        self.main = Main
        self.setMinimumSize(300, 160)
        self.setWindowFlags(Qt.Dialog)

        vbox = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addWidget(self._lProgLabel())
        hbox.addWidget(self._leProgLabel())
        vbox.addLayout(hbox)
        vbox.addWidget(self._lReview())
        hbox2 = QHBoxLayout()
        hbox2.addWidget(self._leReview())
        hbox2.addWidget(self._bReview())
        vbox.addLayout(hbox2)
        hbox3 = QHBoxLayout()
        hbox3.addWidget(self.b_create())
        hbox3.addWidget(self.b_close())
        vbox.addLayout(hbox3)
        self.setLayout(vbox)

    def _lProgLabel(self):
        _lProgLabel = QLabel(self)
        _lProgLabel.setText('<center style=font-size:10pt><FONT FACE="Century Gothic">Название кнопки:</center>')

        return _lProgLabel

    def _leProgLabel(self):
        self._leProgLabel = QLineEdit(self)
        self._leProgLabel.setFont(QFont('Century Gothic', 10))

        return self._leProgLabel

    def _lReview(self):
        _lreview = QLabel(self)
        _lreview.setText(
            '<center style=font-size:10pt><FONT FACE="Century Gothic">Укажите путь к программе или нажмите "Обзор":</center>')

        return _lreview

    def _leReview(self):
        self._leReview = QLineEdit(self)
        self._leReview.setFixedSize(250, 30)
        self._leReview.setFont(QFont('Century Gothic', 10))

        return self._leReview

    def _bReview(self):
        _breview = QPushButton()
        _breview.setFixedSize(90, 30)
        _breview.setText("Обзор")
        _breview.clicked.connect(self.browseFiles)

        return _breview

    def browseFiles(self):
        fname = QFileDialog.getOpenFileName(self, 'Open file', 'C:\Program Files', 'exe files (*.exe)')
        self._leReview.setText(fname[0])

    def b_create(self):

        b_create = QPushButton(self)
        b_create.setText("Добавить")
        b_create.setMinimumSize(10, 40)

        b_create.clicked.connect(self.create_button)

        return b_create

    def b_close(self):
        b_close = QPushButton(self)
        b_close.setText("Отмена")
        b_close.setMinimumSize(10, 40)
        b_close.clicked.connect(self._cancel)

        return b_close

    def _cancel(self):
        self.close()

    def showMessageBox(self, title, message):
        msgBox = QMessageBox()
        msgBox.setWindowTitle(title)
        msgBox.setText(message)
        msgBox.setStyleSheet("font: 12px;"
                             "font-family: Century Gothic;")
        msgBox.setStandardButtons(QMessageBox.Ok)
        msgBox.exec_()

    # Проверка ввода данных
    def create_button(self):
        if len(self._leReview.text()) == 0:
            self.showMessageBox('Внимание!',
                                '<center><br/><u style=font-size:10pt><FONT FACE="Arial"><b>Вы не заполнили поля</b></u></center></FONT>')
        else:
            self.main.create_new_button()
            self.main.saved_conf()
            self.close()


if __name__ == ('__main__'):
    w = Second()
    w.show()
pyqt5
  • 2 2 个回答
  • 21 Views

2 个回答

  • Voted
  1. Sergey Tatarincev
    2022-10-07T15:59:25Z2022-10-07T15:59:25Z

    你的问题是你每次都重新分配self.new_but,所以只有最后一个添加的对你有用。

    self.new_but在您的任务中,在插槽中使用而不是信号源(谁调用它)就足够了-self.sender() 这里至少有一个示例:

    from PyQt5.QtWidgets import QWidget, QApplication, QGridLayout, QGroupBox, QPushButton, QMessageBox, QMenu, QFileDialog
    from PyQt5.QtCore import QEvent, Qt, QFileInfo
    
    class Main(QWidget):
    
        def __init__(self):
            super(Main, self).__init__()
            self.setWindowTitle('Образец')
            self.resize(500, 300)
            grid = QGridLayout()
            grid.addWidget(self.prog_group_box(), 0, 0, 1, 1)
            grid.addWidget(self.b_new_prog(), 1, 0, Qt.AlignRight)
            self.setLayout(grid)
    
        def prog_group_box(self):
            groupBox1 = QGroupBox(self)
            self.grid_prog = QGridLayout()
            groupBox1.setLayout(self.grid_prog)
            return groupBox1
    
        def b_new_prog(self):
            self.b_new_prog = QPushButton(self)
            self.b_new_prog.setText("Добавить")
            self.b_new_prog.setMinimumSize(129, 43)
            self.b_new_prog.clicked.connect(self.click_newprog)
    
            return self.b_new_prog
    
        def click_newprog(self):
            fname = QFileDialog.getOpenFileName(self, 'Open file', '', '')
            new_but = QPushButton()
            new_but.setFixedSize(70, 70)
            new_but.clicked.connect(self.btnClicked)
            fi = QFileInfo(fname[0])
            new_but.setText(fi.baseName())
            new_but.setProperty("filename",fname[0])
            self.grid_prog.addWidget(new_but, 0, 0)
            i = self.grid_prog.count() - 1
            self.grid_prog.addWidget(new_but, 1 + i // 8, i % 8)
            new_but.installEventFilter(self)
    
        def btnClicked(self):
            QMessageBox.information(self.sender(), "", self.sender().property("filename"))
    
    
        # Контекстное меню
        def eventFilter(self, source, event):
    
            if event.type() == QEvent.ContextMenu and source.metaObject().className()=='QPushButton':
                menu = QMenu()
                menu.addAction('Удалить')
    
                if menu.exec_(event.globalPos()):
                    reply = QMessageBox.question(
                        self,
                        'Message', "Вы действительно хотите удалить?",
                        QMessageBox.Yes | QMessageBox.No,
                        QMessageBox.No
                        )
                    if reply == QMessageBox.Yes:
                        source.hide()
    
                    else:
                        pass
    
            return super().eventFilter(source, event)
    
    if __name__ == ('__main__'):
        import sys
        app = QApplication(sys.argv)
        w = Main()
        w.show()
        sys.exit(app.exec_())
    
    • 0
  2. Best Answer
    Djony Cooper
    2022-10-07T17:35:52Z2022-10-07T17:35:52Z

    如果有人有同样的问题,这里是解决方案:

    更改将仅影响文件:main.py:

    from PyQt5.QtWidgets import QWidget, QApplication, QGridLayout, QGroupBox, QPushButton, QMessageBox, QMenu
    from PyQt5.QtCore import QEvent, QSettings, Qt
    from PyQt5.QtGui import QIcon
     
    class Main(QWidget):
     
        
     
        def __init__(self):
            super(Main, self).__init__()
            self.setWindowTitle('Образец')
            self.resize(500, 300)
     
            grid = QGridLayout()
            grid.addWidget(self.prog_group_box(), 0, 0, 1, 1)
            grid.addWidget(self.b_new_prog(), 1, 0, Qt.AlignRight)
     
            self.setLayout(grid)
            
            self.settings = QSettings("settings.ini", QSettings.IniFormat)
            self.dictButtons = {}
        
        def prog_group_box(self):
            groupBox1 = QGroupBox(self)
            self.grid_prog = QGridLayout()
            groupBox1.setLayout(self.grid_prog)
     
            return groupBox1
     
        def saved_conf(self):
            # Сохранение созданной кнопки в ini файл
            self.settings.beginGroup(self.new_but.text())
            self.settings.setValue('exe', self.dictButtons[self.new_but.text()])
            self.settings.endGroup()
            self.settings.sync()
        
        
        def restore_settings(self):
        # Функция восстановления сохраненного конфига из ini файла
            for i in self.settings.allKeys():
                self.restore_buttons(i.split('/')[0], self.settings.value(i))
                
        def restore_buttons(self, name, exe):
            self.new_but = QPushButton()
            self.new_but.setFixedSize(70, 70)
            self.new_but.clicked.connect(self.btnClicked)
            self.new_but.setText(name)
            self.grid_prog.addWidget(self.new_but, 0, 0)
            i = self.grid_prog.count() - 1
            self.grid_prog.addWidget(self.new_but, 1 + i // 8, i % 8)
            self.new_but.installEventFilter(self)
     
            self.dictButtons[name] = exe  
            
     
        def delete_setting(self, button):
            # Функция удаления данных из ini файла с сохраненной конфигурацией
            del self.dictButtons[button.text()]
            self.settings.remove(button.text())
     
        def b_new_prog(self):
            self.b_new_prog = QPushButton(self)
            self.b_new_prog.setText("Добавить")
            self.b_new_prog.setMinimumSize(129, 43)
            self.b_new_prog.clicked.connect(self.click_newprog)
     
            return self.b_new_prog
     
        def click_newprog(self):
            from second import Second
            self.click_newprog = Second(self)
            self.click_newprog.show()
     
        def create_new_button(self):
            self.new_but = QPushButton()
            self.new_but.setFixedSize(70, 70)
            self.new_but.clicked.connect(self.btnClicked)
            self.new_but.setText(self.click_newprog._leProgLabel.text())
            self.grid_prog.addWidget(self.new_but, 0, 0)
            i = self.grid_prog.count() - 1
            self.grid_prog.addWidget(self.new_but, 1 + i // 8, i % 8)
            self.new_but.installEventFilter(self)
     
            self.dictButtons[self.new_but.text()] = self.click_newprog._leReview.text()
     
        def btnClicked(self):
            import os
            button = self.sender()
            os.startfile(self.dictButtons[button.text()])
        
        # Контекстное меню
        def eventFilter(self, source, event):
            button = source
            if event.type() == QEvent.ContextMenu:
                menu = QMenu()
                menu.addAction('Удалить')
     
                if menu.exec_(event.globalPos()):
                    reply = QMessageBox.question(
                        self,
                        'Message', "Вы действительно хотите удалить?",
                        QMessageBox.Yes | QMessageBox.No,
                        QMessageBox.No
                        )
                    if reply == QMessageBox.Yes:
                        
                        button.hide()
                        self.delete_setting(button)
                    else:
                        pass
     
            return super().eventFilter(source, event)
     
    if __name__ == ('__main__'):
        import sys
        app = QApplication(sys.argv)
        w = Main()
        w.show()
        w.restore_settings()
        sys.exit(app.exec_())
    
    • 0

相关问题

  • PyQt5:带延迟的线路输出

  • 如何制作工具提示

  • 在 PyQt5 中读取字符串

  • 如何更改 QLabel 的背景?

  • python,PyQt5 库中的错误:ImportError: cannot import name 'QtWebKitWidgets'

  • PyQt5,选择图像时出现“无法读取内存”错误

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5