自定義實現 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_())

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM