pyqt中的切换按钮 [英] Switch button in pyqt

查看:74
本文介绍了pyqt中的切换按钮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以用pyqt5创建一个开关按钮吗?

Is it possible to create a switch button with pyqt5?

我正在使用 pyqt5 在 python 中设计一个过滤工具.用户应该能够对某些数据应用过滤器或其补充,甚至组合过滤器.

I'm designing a filtering tool in python using pyqt5. The user is supposed to be able to apply a filter or its complement on some data and even combine filters.

我在 qtablewidget 中显示可能的过滤器,用户可以在其中使用复选框选择要应用的过滤器.在每一行中,复选框都是独占的,即用户不能同时选择过滤器及其补充.

I display possible filters in qtablewidget where the user can choose filters to apply using checkboxes. In each row, checkboxes are exclusives i.e. the user can not select a filter and its complement at the same time.

但问题是,一旦我们选中了一行中的复选框,我们就无法取消选中它,除非我们选中它的反面.事实上,当过滤器刚加载时,所有的框都没有被选中(它们在某种程度上是空的)所以我可以选择要应用的过滤器但是当我想选择另一个过滤器时,先例过滤器的一个框仍然选中(选中框过滤器或框补充),我无法将其关闭.

But the problem is that once we select a checkbox in a row, we cannot deselect it unless we select its opposite. In fact, when the filters are just loaded , all the boxes are unchecked (they are empty in a way) so I can choose which filter to apply but when I want to choose an other filter, one of the boxes of the precedent filter still checked (either box Filter or box Complement is checked) and I can not switch it off.

这就是为什么我想在每一行添加一个开关按钮来禁用过滤器.通过这样做,我将能够考虑或不考虑 checked 属性.

That's why I thought about adding a switch button in each row to disable a filter. By doing this I will be able to take in consideration or not the checked attribute.

这是我想要的一个例子:

Here is an example of what I want :

下面是一个可复制的例子

Below an reproductible example

from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(550, 350)
        MainWindow.setMinimumSize(QtCore.QSize(550, 350))
        MainWindow.setMaximumSize(QtCore.QSize(550, 350))
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(20, 20, 500, 200))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(3)
        self.tableWidget.setRowCount(0)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(2, item)
        self.pushButton_Save = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_Save.setGeometry(QtCore.QRect(120, 250, 100, 50))
        self.pushButton_Save.setMinimumSize(QtCore.QSize(100, 50))
        self.pushButton_Save.setMaximumSize(QtCore.QSize(100, 50))
        self.pushButton_Save.setObjectName("pushButton_Save")

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 550, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("MainWindow", "Name"))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(_translate("MainWindow", "Filter"))
        item = self.tableWidget.horizontalHeaderItem(2)
        item.setText(_translate("MainWindow", "complement"))
        self.pushButton_Save.setText(_translate("MainWindow", "Save"))
        self.pushButton_Save.clicked.connect(self.bindSave)

    def bindSave(self):
        numRows = self.tableWidget.rowCount()
        self.tableWidget.insertRow(numRows)

        groupButton = QtWidgets.QButtonGroup(self.tableWidget)
        groupButton.setExclusive(True)
        it1 = QtWidgets.QTableWidgetItem("filter "+str(numRows))
        self.tableWidget.setItem(numRows, 0, it1)
        ch_bx1 = QtWidgets.QCheckBox()
        groupButton.addButton(ch_bx1)
        self.tableWidget.setCellWidget(numRows, 1, ch_bx1)
        ch_bx2 = QtWidgets.QCheckBox()
        groupButton.addButton(ch_bx2)
        self.tableWidget.setCellWidget(numRows, 2, ch_bx2)



if __name__ == "__main__":
    if not QtWidgets.QApplication.instance():
        app = QtWidgets.QApplication(sys.argv)
    else:
        app = QtWidgets.QApplication.instance()
    MainWindow = QtWidgets.QMainWindow()
    ui        = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()

推荐答案

就像其他人建议的那样,您可以通过向表中添加第三列并将此列中的每个项目小部件设置为您所做的那样来启用/禁用过滤器ch_box1ch_box2.您可以使用插槽和信号来操作复选按钮(例如,根据开关的状态启用/禁用它们).

Like others have suggested, you could enable/disable filters by adding a third column to the table and setting each item widget in this column to a like you did for ch_box1 and ch_box2. You can use slots and signals to manipulate the check buttons (for example enable/disable them depending on the state of the switch).

要像 OP 中的图片一样创建自定义开关,您可以将 QPushButton 子类化并覆盖 paintEvent,例如(请注意,我省略了与原始帖子中可重现示例中的代码相同的代码)

To create custom switches like in the picture in the OP, you could sub-class QPushButton and overriding paintEvent, e.g. (note that I've omitted the code that was the same as the code in the reproducable example in the original post)

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QRect
import sys

class MySwitch(QtWidgets.QPushButton):
    def __init__(self, parent = None):
        super().__init__(parent)
        print('init')
        self.setCheckable(True)
        self.setMinimumWidth(66)
        self.setMinimumHeight(22)

    def paintEvent(self, event):
        label = "ON" if self.isChecked() else "OFF"
        bg_color = Qt.green if self.isChecked() else Qt.red

        radius = 10
        width = 32
        center = self.rect().center()

        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.translate(center)
        painter.setBrush(QtGui.QColor(0,0,0))

        pen = QtGui.QPen(Qt.black)
        pen.setWidth(2)
        painter.setPen(pen)

        painter.drawRoundedRect(QRect(-width, -radius, 2*width, 2*radius), radius, radius)
        painter.setBrush(QtGui.QBrush(bg_color))
        sw_rect = QRect(-radius, -radius, width + radius, 2*radius)
        if not self.isChecked():
            sw_rect.moveLeft(-width)
        painter.drawRoundedRect(sw_rect, radius, radius)
        painter.drawText(sw_rect, Qt.AlignCenter, label)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        ....
        self.tableWidget.setColumnCount(4)
        ....
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(3, item)
        ...

    def retranslateUi(self, MainWindow):
        ...
        item = self.tableWidget.horizontalHeaderItem(3)
        item.setText(_translate("MainWindow", "status"))

    def bindSave(self):
        ...
        ch_bx3 = MySwitch()
        ch_bx3.setChecked(True)
        ch_bx3.clicked.connect(ch_bx1.setEnabled)
        ch_bx3.clicked.connect(ch_bx2.setEnabled)
        self.tableWidget.setCellWidget(numRows, 3, ch_bx3)


if __name__ == "__main__":
    if not QtWidgets.QApplication.instance():
        app = QtWidgets.QApplication(sys.argv)
    else:
        app = QtWidgets.QApplication.instance()
    MainWindow = QtWidgets.QMainWindow()
    ui        = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    app.exec()

截图:

这篇关于pyqt中的切换按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆