该提问者设计了一个简单的GUI应用程序,使用了PyQt4框架来实现界面的可扩展性。用户可以在应用程序中输入一些基本信息并将其发送到n个队列中(队列实现为等待列表)。每个队列都是一个QTableview控件,且具有弹出、删除和重新顺序排列队列的功能。这些控件连同其他控件(例如标签)组成一个“模块”。目前,该应用程序默认包含4个队列模块,因此有诸如btn_table1_pop、btn_table2_pop等元素,这些元素是每个模块控件的四个副本。如果总是假定应用程序总是需要四个队列,则这种设计显然不是一个好的用户界面设计。提问者希望能够轻松地修改程序,以便8个人可以使用它,或者3个人可以毫不浪费屏幕空间地使用它。
通过为每个模块的按钮编写设置索引并调用实现通用逻辑的函数的方法来解决该问题,但这种方法仍然高度依赖于4个队列,因为分支逻辑和调用函数仍然需要考虑到元素的名称。如果有一方法“向量化”元素的名称,就可以编写btn_table[index]_pop.setEnabled(False)这样的代码,这就可以消除分支逻辑,并显著精简代码。但是提问者是PyQt的新手,对是否可以通过这种方式实现自己的目标或如何实现不了解。
2、解决方案
要解决这个问题,可以创建一个列表来存储所有队列模块的名称,并使用该列表来动态生成元素的名称。这将允许在运行时添加或删除队列模块。以下是实现该解决方案的步骤:
- 创建一个包含所有队列模块名称的列表。
- 对于每个队列模块,创建一个相应的QTableview控件并将其添加到布局中。
- 为每个队列模块的按钮创建相应的点击事件处理程序。
- 在点击事件处理程序中,获取当前队列模块的索引并使用该索引从列表中获取队列模块的名称。
- 使用队列模块的名称来生成元素的名称。
- 使用生成的元素名称来访问相应的元素并执行相应的操作。
以下是一个示例代码:
import sys
from PyQt4 import QtCore, QtGui
class QueueModule(QtGui.QWidget):
def __init__(self, index):
super().__init__()
self.index = index
self.tableview = QtGui.QTableview()
self.btn_pop = QtGui.QPushButton("Pop")
self.btn_delete = QtGui.QPushButton("Delete")
self.btn_rearrange = QtGui.QPushButton("Rearrange")
self.layout = QtGui.QHBoxLayout()
self.layout.addWidget(self.tableview)
self.layout.addWidget(self.btn_pop)
self.layout.addWidget(self.btn_delete)
self.layout.addWidget(self.btn_rearrange)
self.setLayout(self.layout)
self.btn_pop.clicked.connect(self.on_btn_pop_clicked)
self.btn_delete.clicked.connect(self.on_btn_delete_clicked)
self.btn_rearrange.clicked.connect(self.on_btn_rearrange_clicked)
def on_btn_pop_clicked(self):
# Get the current queue module's name.
queue_module_name = "queue_module_" + str(self.index)
# Generate the element's name.
btn_pop_name = queue_module_name + "_btn_pop"
# Get the element using the generated name.
btn_pop = self.findChild(QtGui.QPushButton, btn_pop_name)
# Disable the button.
btn_pop.setEnabled(False)
def on_btn_delete_clicked(self):
# Get the current queue module's name.
queue_module_name = "queue_module_" + str(self.index)
# Generate the element's name.
btn_delete_name = queue_module_name + "_btn_delete"
# Get the element using the generated name.
btn_delete = self.findChild(QtGui.QPushButton, btn_delete_name)
# Disable the button.
btn_delete.setEnabled(False)
def on_btn_rearrange_clicked(self):
# Get the current queue module's name.
queue_module_name = "queue_module_" + str(self.index)
# Generate the element's name.
btn_rearrange_name = queue_module_name + "_btn_rearrange"
# Get the element using the generated name.
btn_rearrange = self.findChild(QtGui.QPushButton, btn_rearrange_name)
# Disable the button.
btn_rearrange.setEnabled(False)
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super().__init__()
self.queue_modules = []
self.main_widget = QtGui.QWidget()
self.layout = QtGui.QVBoxLayout()
self.main_widget.setLayout(self.layout)
self.btn_add_queue_module = QtGui.QPushButton("Add Queue Module")
self.btn_remove_queue_module = QtGui.QPushButton("Remove Queue Module")
self.layout.addWidget(self.btn_add_queue_module)
self.layout.addWidget(self.btn_remove_queue_module)
self.setCentralWidget(self.main_widget)
self.btn_add_queue_module.clicked.connect(self.on_btn_add_queue_module_clicked)
self.btn_remove_queue_module.clicked.connect(self.on_btn_remove_queue_module_clicked)
def on_btn_add_queue_module_clicked(self):
# Create a new queue module.
queue_module = QueueModule(len(self.queue_modules))
# Add the queue module to the list of queue modules.
self.queue_modules.append(queue_module)
# Add the queue module to the main layout.
self.layout.addWidget(queue_module)
def on_btn_remove_queue_module_clicked(self):
# Get the last queue module.
queue_module = self.queue_modules[-1]
# Remove the queue module from the list of queue modules.
self.queue_modules.remove(queue_module)
# Remove the queue module from the main layout.
self.layout.removeWidget(queue_module)
# Destroy the queue module.
queue_module.deleteLater()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
这种方法使得应用程序可以轻松地添加或删除队列模块,而无需修改代码,提高了应用程序的可扩展性。