【问题标题】:Initiating a custom QWidget within another QWidget class' function在另一个 QWidget 类的函数中启动自定义 QWidget
【发布时间】:2020-12-26 23:54:19
【问题描述】:

我是 python 和 pyqt 的新手。我正在尝试创建一个 QToolButtons 矩阵,在按下按钮时,会弹出一个 QDialog 供用户输入(多个字段)。

我有一个用于按钮矩阵对象的类和一个用于对话框的类,但似乎无法在按钮矩阵类中获得一个函数来启动对话框类/小部件的实例。

谁能告诉我我做错了什么?

我提供了以下代码:

from PyQt4 import QtGui
from PyQt4.QtGui import QApplication, QWidget, QFormLayout, QInputDialog, QPushButton, QToolButton, QLabel, QVBoxLayout, QHBoxLayout, QLineEdit

class Pixel(object):
    def __init__(self, pixel_number, r_value, g_value, b_value):
        self.pixel = pixel_number
        self.red_value = r_value
        self.green_value = g_value
        self.blue_value = b_value
        
class inputdialogdemo(QWidget):
    
    def __init__(self, parent = None):
        QWidget.__init__(self, parent)
        #super(inputdialogdemo, self).__init__(parent)
        
        layout = QFormLayout()
        self.btn1 = QPushButton("Enter red value")
        self.le1 = QLineEdit()
        self.btn1.clicked.connect(self.getRed)
        layout.addRow(self.btn1,self.le1)
    
        self.btn2= QPushButton("Enter green value")
        self.le2 = QLineEdit()
        self.btn2.clicked.connect(self.getGreen)
        layout.addRow(self.btn1,self.le2)
      
        self.btn3 = QPushButton("Enter blue value")
        self.le3 = QLineEdit()
        self.btn3.clicked.connect(self.getBlue)
        layout.addRow(self.btn3,self.le3)
      
        self.setLayout(layout)
        self.setWindowTitle("RGB input dialog ")
        
    def getRed(self):
        num, ok = QInputDialog.getText(self, 'Red Input Dialog', 'Enter your name:')
        
        if ok:
            self.le1.setText(str(num))
            
    def getGreen(self):
        num,ok = QInputDialog.getInt(self,"Green input dualog","enter a number")
        
        if ok:
            self.le2.setText(str(num))  
    
    def getBlue(self):
        num,ok = QInputDialog.getInt(self,"Blue input dualog","enter a number")
        
        if ok:
            self.le3.setText(str(num))    


class ClusterArray(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        #self.button_layout = QHBoxLayout()
        self.button_layout = QtGui.QGridLayout()
        self.widget_layout = QtGui.QGridLayout()
        for cluster_number in range(1, 15):
            for pixel_number in range(1, 5):
                    button = QToolButton()
                    button.setText(str(cluster_number) + str(pixel_number))
                    button.setObjectName(f"Cluster{cluster_number},Pixel{pixel_number}")
                    button.released.connect(self.button_released)
                    self.button_layout.addWidget(button, cluster_number, pixel_number)

        self.status_label = QLabel('No button clicked')

        self.widget_layout.addItem(self.button_layout)
        self.widget_layout.addWidget(self.status_label)
        self.setLayout(self.widget_layout)
        ex = inputdialogdemo()
        
    def button_released(self):
        sending_button = self.sender()
        self.status_label.setText('%s Clicked!' % str(sending_button.objectName()))
        ex = inputdialogdemo()
        ex.show()
        #i, okPressed = QInputDialog.getInt(self, "Get integer","Percentage:", 28, 0, 100, 1)
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = ClusterArray() 
    widget.show()
#   ex = inputdialogdemo()
#   ex.show()
    sys.exit(app.exec_()

目前我刚刚尝试让我的类的函数从一个名为“inputdialogdemo”的类中的一些演示代码创建一个对象

另外,我想以某种方式保留与矩阵上相应按钮关联的输入值。我认为这些值应该存储在每个按钮代表的另一个对象中。我的对象是包含红色、绿色和蓝色值的“像素”。我还没有编写这个功能。这种方法听起来可行吗?

【问题讨论】:

    标签: python pyqt pyqt4


    【解决方案1】:

    inputdialogdemo 实例在__init__button_released 中都正确创建,问题是一旦这些函数返回,ex 实例就会收集垃圾:由于没有持久引用(ex 只是一个本地变量),python 会自动删除它以避免不必要的内存消耗。

    由于您需要一个对话框,最好的解决方案是从QDialog 继承而不是QWidget;这有两个重要的好处:它保持对话框modal(它停留在其他窗口之上并避免与它们交互)并提供exec_() 方法,该方法在对话框关闭之前不会返回;然后您可以为标准的确定/取消按钮添加一个 QDialogBu​​ttonBox,并将其 acceptedrejected 连接到对话框的 accept()reject() 插槽。

    from PyQt4.QtGui import (QApplication, QWidget, QFormLayout, QInputDialog, QPushButton, QToolButton, 
        QLabel, QVBoxLayout, QHBoxLayout, QLineEdit, QDialog, QDialogButtonBox)
    
    class inputdialogdemo(QDialog):
        def __init__(self, parent = None):
            # ...
            buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
            layout.addRow(buttonBox)
            buttonBox.accepted.connect(self.accept)
            buttonBox.rejected.connect(self.reject)
    
    class ClusterArray(QWidget):
        # ...
        def button_released(self):
            sending_button = self.sender()
            self.status_label.setText('%s Clicked!' % str(sending_button.objectName()))
            ex = inputdialogdemo()
            if ex.exec_():
                red = ex.le1.text()
                green = ex.le2.text()
                blue = ex.le2.text()
    

    一些建议:

    • 如果需要数值,不要使用QLineEdit,而是使用QSpinBox;
    • 要向另一个布局添加布局,请使用setLayout(),而不是addItem()
    • 要连接到按钮点击,请使用clicked 信号,而不是released
    • 虽然特殊字符并没有严格禁止用于对象名称,但通常最好避免使用它们;此外,实际对象名称使用对象名称,而不是用于跟踪某些属性
    • 您可以使用dynamic properties 跟踪任何 QObject 的自定义属性:
        button.setProperty('cluster', cluster_number)
        button.setProperty('pixel', pixel_number)
    
    • 除非您有强制性的系统要求,否则您应该真正考虑切换到 PyQt5,因为自 2015 年以来,PyQt4 被认为已过时且已弃用/不受支持;
    • 总是首选大写的类名称,因为小写名称通常仅用于变量和属性;阅读更多关于 Style Guide for Python Code;

    【讨论】:

    • 非常感谢 Musicamante。这对我帮助很大。很抱歉回复晚了,因为我一直非常忙,而且我才刚刚抽出时间花在我的项目上。
    猜你喜欢
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多