python-3.x PyQt5用户点击订购按钮

im9ewurl  于 2023-08-08  发布在  Python
关注(0)|答案(1)|浏览(106)

下面的代码有点长,在pip安装PyQt5后运行:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QLabel
from PyQt5.QtCore import pyqtSignal

class MyPushButton(QPushButton):
    self_emit_toggle_signal = pyqtSignal(list)
    def __init__(self, text):
        super().__init__(text)
        self.emit_self_toggle = False
        self.toggled.connect(self.when_toggled)
    
    def when_toggled(self, checked):
        if self.emit_self_toggle:
            self.self_emit_toggle_signal.emit([self, checked])

class ButtonWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.buttons = []
        self.checked_buttons = []
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("Widget with 10 Push Buttons")
        
        # Create 10 push buttons
        for i in range(0, 10):
            button = MyPushButton(f"Button {i}")
            self.buttons.append(button)
        
        # Add buttons to the layout
        layout = QVBoxLayout()
        self.label = QLabel("Game not started.")
        layout.addWidget(self.label)
        self.start_button = QPushButton("Start")
        layout.addWidget(self.start_button)
        self.clear_button = QPushButton("Clear")
        layout.addWidget(self.clear_button)

        for button in self.buttons:
            layout.addWidget(button)
        
        self.setLayout(layout)

        #Callbacks:
        self.start_button.clicked.connect(self.start_game)
        self.clear_button.clicked.connect(self.clear_game)
        self.show()
    
    def start_game(self):
        self.label.setText("Game started.")
        for button in self.buttons:
            button.setCheckable(True)
            button.emit_self_toggle = True
            button.self_emit_toggle_signal.connect(self.upon_toggle)
    
    def upon_toggle(self, list_button_checked):
        button, checked = list_button_checked[0], list_button_checked[1]
        if checked:
            self.checked_buttons.append(button)
        else:
            self.checked_buttons.remove(button)
        self.update_label()
    
    def update_label(self):
        for button in self.buttons:
            if button in self.checked_buttons:
                index = self.buttons.index(button)
                checked_index = self.checked_buttons.index(button)
                button.setText(str(checked_index + 1) + " :" + f"Button {index}")    #line (1)
            else:
                index = self.buttons.index(button)
                button.setText(f"Button {index}")
    
    def clear_game(self):
        self.label.setText("Game not started.")
        self.checked_buttons.clear()
        for button in self.buttons:
            button.emit_self_toggle = False
            button.setCheckable(False)
            button.setChecked(False)
            button.self_emit_toggle_signal.disconnect(self.upon_toggle)
        
        self.update_label()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = ButtonWidget()
    sys.exit(app.exec_())

字符串
它给出了以下内容:


的数据
上面的代码做了什么,用文字来说,如下所示:在用户点击“开始”之后,用户将能够点击按钮。用户点击的顺序将直接反映在按钮的标签上。如果一个按钮被点击,用户再次点击它,那么点击被取消,程序将该按钮视为以前从未点击过。单击“清除”将初始化程序。从程序上讲,代码保存选中按钮的列表,在用户单击时更新列表,并相应地重写每个按钮上的文本。
例如:如果用户点击“开始”,然后按顺序按钮1,2,3,4,5,1,它将显示以下内容:



问题:
1.现在,我通过直接更改按钮上的文本来反映用户点击的顺序(参见第(1)行)。有没有可能修改上面的代码,使顺序仍然被反映出来,按钮上的文本完全不变?最优选的结果将是一些彩色数字“浮动”在按钮的左手侧。
1.(可选)是否有办法完全避免使用检查状态?如果没有,我至少可以隐藏检查状态吗?
下面是一个演示,当1和2都达到时,我的意思是什么,点击与上面的例子完全相同:



注意事项:
所提供的代码旨在作为演示。您可以随意以任何方式更改所提供的代码,包括完全重写它。没有必要担心性能。在我的实际项目中,按钮的数量肯定会小于15。

hc8w905p

hc8w905p1#

由于您只想知道按钮被点击的顺序,因此使用按钮的选中状态实际上是没有意义的,特别是因为您不希望事件显示它。只需连接到标准clicked信号即可。
事实上,逻辑很简单;单击按钮时,则:

  • 如果不在列表中,只需追加;
  • 如果它在列表中,则删除它;

如果您想在按钮之外显示数字,那么为每个按钮使用“兄弟”标签。
在下面的代码修改中,我为标签和按钮使用了内部网格布局,它们将被添加到它们各自的列表中。
然后,要获取被单击并触发connected函数的按钮,只需使用所有QObjects的sender()函数,该函数返回发出信号的对象。

class ButtonWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Widget with 10 Push Buttons")
        
        # Add buttons to the layout
        layout = QVBoxLayout(self)
        self.label = QLabel("Game not started.")
        layout.addWidget(self.label)
        self.start_button = QPushButton("Start")
        layout.addWidget(self.start_button)
        self.clear_button = QPushButton("Clear")
        layout.addWidget(self.clear_button)

        self.buttons = []
        self.labels = []
        self.checked_buttons = []

        buttonGrid = QGridLayout()
        layout.addLayout(buttonGrid)

        for i in range(0, 10):
            label = QLabel()
            label.setMinimumWidth(20)
            buttonGrid.addWidget(label, i, 0)
            self.labels.append(label)

            button = QPushButton("Button {}".format(i))
            button.setEnabled(False)
            buttonGrid.addWidget(button, i, 1)
            self.buttons.append(button)
            button.clicked.connect(self.update_list)

        self.start_button.clicked.connect(self.start_game)
        self.clear_button.clicked.connect(self.clear_game)
    
    def start_game(self):
        self.label.setText("Game started.")
        for button in self.buttons:
            button.setEnabled(True)
    
    def clear_game(self):
        self.label.setText("Game not started.")
        for button in self.buttons:
            button.setEnabled(False)
        self.checked_buttons.clear()
        self.update_labels()

    def update_list(self):
        button = self.sender()
        if button in self.checked_buttons:
            self.checked_buttons.remove(button)
            self.update_labels()
        else:
            self.checked_buttons.append(button)
            index = self.buttons.index(button)
            # no need to update all labels, we can get its "sibling" label
            # and just use the length of the checked_buttons, since this
            # is obviously the last clicked button
            self.labels[index].setText(
                str(len(self.checked_buttons)))

    def update_labels(self):
        for label, button in zip(self.labels, self.buttons):
            if button in self.checked_buttons:
                index = self.checked_buttons.index(button)
                label.setText(str(index + 1))
            else:
                label.clear()

字符串

相关问题