自定义实现 PyQt5 下拉复选框 ComboCheckBox

一、前言

  由于最近的项目需要具有复选功能,但过多的复选框会影响界面布局和美观,因而想到把 PyQt5 的下拉列表和复选框结合起来,但在 PyQt5 中并没有这样的组件供我们使用,所以想要自己实现一个下拉复选框,主要就是继承 QComboBox 类,然后将复选框 QCheckBox 加入其中,并实现相应的功能。

  最终实现的下拉复选框效果如下:

  

 

二、代码实现

1.主要方法

  在 PyQt5 中,有几个主要的方法需要了解一下,方法名称和对应的含义如下:

  • QtWidgets.QComboBox.setView(itemView):设置组合框弹出窗口中使用的视图组合框获取视图的所有权。
  • QtWidgets.QcomboBox.setLineEdit(QLineEdit)设置组合框使用的行,而不是当前行编辑窗口小部件。
  • QtWidgets.QListWidget.setItemWidget(item, widget)设置要在给定的 item 中的 widget 组件

2.具体代码

  实现下拉复选框的思路为用 setView() 方法将 QComboBox 下拉列表的视图改为 QListWidget 组件,然后将 QCheckBox 复选框用在 QListWiget 中,具体代码如下:

 1 class ComboCheckBox(QComboBox):
 2     def __init__(self, items: list):
 3         """
 4         initial function
 5         :param items: the items of the list
 6         """
 7         super(ComboCheckBox, self).__init__()
 8         self.items = items  # items list
 9         self.box_list = []  # selected items
10         self.text = QLineEdit()  # use to selected items
11         self.text.setReadOnly(True)
12 
13         q = QListWidget()
14         for i in range(len(self.items)):
15             self.box_list.append(QCheckBox())
16             self.box_list[i].setText(self.items[i])
17             item = QListWidgetItem(q)
18             q.setItemWidget(item, self.box_list[i])
19             self.box_list[i].stateChanged.connect(self.show_selected)
20 
21         self.setLineEdit(self.text)
22         self.setModel(q.model())
23         self.setView(q)
24 
25     def get_selected(self) -> list:
26         """
27         get selected items
28         :return:
29         """
30         ret = []
31         for i in range(len(self.items)):
32             if self.box_list[i].isChecked():
33                 ret.append(self.box_list[i].text())
34         return ret
35 
36     def show_selected(self):
37         """
38         show selected items
39         :return:
40         """
41         self.text.clear()
42         ret = '; '.join(self.get_selected())
43         self.text.setText(ret)

   其中 show_selected() 用于显示被选中的内容,get_selected() 则用于获取所有被选中的内容并返回。

3.增加全选

  要增加全选功能,首先是要在最前面加一个全选的选择框,然后为这个全选的选择框绑定相应的方法,用于实现全选功能和取消全选功能,具体代码如下:

 1 def all_selected(self):
 2     """
 3     decide whether to check all
 4     :return:
 5     """
 6     # change state
 7     if self.state == 0:
 8         self.state = 1
 9         for i in range(1, len(self.items)):
10             self.box_list[i].setChecked(True)
11     else:
12         self.state = 0
13         for i in range(1, len(self.items)):
14             self.box_list[i].setChecked(False)
15     self.show_selected()

4.修改样式

  由于默认的样式并不美观,所以我们可以对控件的样式进行自定义,例如字体大小、字体粗细等等,例如:

q.setStyleSheet("font-size: 20px; font-weight: bold; height: 40px; margin-left: 5px")
self.setStyleSheet("width: 300px; height: 50px; font-size: 21px; font-weight: bold")

 

三、完整程序

  完善后的下拉复选框的运行程序代码如下:

 1 from PyQt5.QtWidgets import QComboBox, QLineEdit, QListWidgetItem, QListWidget, QCheckBox, \
 2     QApplication, QVBoxLayout, QWidget
 3 import sys
 4 
 5 
 6 class ComboCheckBox(QComboBox):
 7     def __init__(self, items: list):
 8         """
 9         initial function
10         :param items: the items of the list
11         """
12         super(ComboCheckBox, self).__init__()
13         self.items = ["全选"] + items  # items list
14         self.box_list = []  # selected items
15         self.text = QLineEdit()  # use to selected items
16         self.state = 0  # use to record state
17 
18         q = QListWidget()
19         for i in range(len(self.items)):
20             self.box_list.append(QCheckBox())
21             self.box_list[i].setText(self.items[i])
22             item = QListWidgetItem(q)
23             q.setItemWidget(item, self.box_list[i])
24             if i == 0:
25                 self.box_list[i].stateChanged.connect(self.all_selected)
26             else:
27                 self.box_list[i].stateChanged.connect(self.show_selected)
28 
29         q.setStyleSheet("font-size: 20px; font-weight: bold; height: 40px; margin-left: 5px")
30         self.setStyleSheet("width: 300px; height: 50px; font-size: 21px; font-weight: bold")
31         self.text.setReadOnly(True)
32         self.setLineEdit(self.text)
33         self.setModel(q.model())
34         self.setView(q)
35 
36     def all_selected(self):
37         """
38         decide whether to check all
39         :return:
40         """
41         # change state
42         if self.state == 0:
43             self.state = 1
44             for i in range(1, len(self.items)):
45                 self.box_list[i].setChecked(True)
46         else:
47             self.state = 0
48             for i in range(1, len(self.items)):
49                 self.box_list[i].setChecked(False)
50         self.show_selected()
51 
52     def get_selected(self) -> list:
53         """
54         get selected items
55         :return:
56         """
57         ret = []
58         for i in range(1, len(self.items)):
59             if self.box_list[i].isChecked():
60                 ret.append(self.box_list[i].text())
61         return ret
62 
63     def show_selected(self):
64         """
65         show selected items
66         :return:
67         """
68         self.text.clear()
69         ret = '; '.join(self.get_selected())
70         self.text.setText(ret)
71 
72 
73 class UiMainWindow(QWidget):
74     def __init__(self):
75         super(UiMainWindow, self).__init__()
76         self.setWindowTitle('Test')
77         self.resize(600, 400)
78         combo = ComboCheckBox(["Python", "Java", "Go", "C++", "JavaScript", "PHP"])
79         layout = QVBoxLayout()
80         layout.addWidget(combo)
81         self.setLayout(layout)
82 
83 
84 if __name__ == "__main__":
85     app = QApplication(sys.argv)
86     ui = UiMainWindow()
87     ui.show()
88     sys.exit(app.exec_())

 

posted @ 2020-03-28 21:06  onionono  阅读(4972)  评论(1编辑  收藏  举报