How to QComboBox Items arranged in given order, or reversely given order or a to z or z to a in PyQt5?
My aim is to rearrange combo box items in
- Alphabetically ascending order (A to Z),
- Alphabetically Descending Order(Z to A).
- Given Order ( As per the list, no change, that is the first item is America, the Second is Russia and the Last One is India)
- Given Order in reverse order (Item in reverse order, that is the First item is India, the second one is France and the Last One is America)
Here is my code. Mouse right-click in combo box will show my option. Based on user selection, items in Qcombo Box will rearrange. How to get it?
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QComboBox, QPushButton, QVBoxLayout,QMenu,QDesktopWidget,QMainWindow
from PyQt5.QtCore import Qt,QPoint,pyqtSignal,QSize
class CheckableComboBox(QComboBox):
def __init__(self):
super().__init__()
self.setEditable(True)
self.lineEdit().setReadOnly(True)
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.showMenu)
self.setStyleSheet("QComboBox QAbstractItemView::item {border: none;padding-left: 5px;}")
self.lineEdit().installEventFilter(self)
self.closeOnLineEditClick = True
self.double_click = None
def showMenu(self,pos):
menu = QMenu()
atoz_action = menu.addAction("A to Z - Ascending Order")
ztoa_action = menu.addAction(("Z to A - Descending Order"))
copy_action1 = menu.addSeparator()
copy_action2 = menu.addAction(("Given Order"))
copy_action3 = menu.addAction(("Given Order - Reverse"))
mainwindow_geomentry = QDesktopWidget().screenGeometry()
widget_qpoint = (self.mapToGlobal(QPoint()))
widget_qpoint_x = widget_qpoint.x()
xpos = mainwindow_geomentry.width() - (self.size().width()+menu.sizeHint().width())
xx = xpos - widget_qpoint_x
if xx <= 0 :
aa = 0-(menu.sizeHint().width())
else:
aa = self.size().width()
action = menu.exec_(self.mapToGlobal(QPoint(aa-2,0)))
if action == atoz_action:
self.model().sort(0)
self.setCurrentIndex(0)
elif action == ztoa_action:
print("bbbbbbbbbb")
class MyApp(QWidget):
def __init__(self):
super().__init__()
mainLayout = QVBoxLayout()
self.setLayout(mainLayout)
self.data = ['America', 'Russia', 'China', 'Germany', 'France', 'India']
self.combo = CheckableComboBox()
self.combo.setMinimumSize(600,40)
btn = QPushButton('Print Values')
btn.clicked.connect(self.getValue)
mainLayout.addWidget(self.combo)
mainLayout.addWidget(btn)
self.combo.addItems(self.data)
def getValue(self):
print(self.combo.currentData())
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet('''QWidget {font-size: 20px;}''')
myApp = MyApp()
myApp.show()
app.exit(app.exec_())
I will try to solve it in ascending order(first case) by self. model().sort(0). Its work. But I was Struck with another three cases. I can't able to solve it.
Answer
To implement the different sorting orders you want for the QComboBox
in PyQt, we can break down the logic for each case. Since you've already successfully handled the ascending order (A to Z
), we'll use similar techniques for the other three cases:
Plan:
- Ascending Order (A to Z) – Already handled by calling
self.model().sort(0)
. - Descending Order (Z to A) – Reverse the list of items.
- Given Order – No change, items in the order they were added.
- Given Order in Reverse – Reverse the list of items.
Code Updates
You will need to modify the showMenu
method to handle these actions and apply the appropriate sorting logic. Below is the updated code to handle all four cases:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QComboBox, QPushButton, QVBoxLayout, QMenu, QDesktopWidget
from PyQt5.QtCore import Qt, QPoint
class CheckableComboBox(QComboBox):
def __init__(self):
super().__init__()
self.setEditable(True)
self.lineEdit().setReadOnly(True)
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.showMenu)
self.setStyleSheet("QComboBox QAbstractItemView::item {border: none;padding-left: 5px;}")
self.lineEdit().installEventFilter(self)
self.closeOnLineEditClick = True
self.double_click = None
def showMenu(self, pos):
menu = QMenu()
# Add actions to the context menu
atoz_action = menu.addAction("A to Z - Ascending Order")
ztoa_action = menu.addAction("Z to A - Descending Order")
menu.addSeparator()
copy_action2 = menu.addAction("Given Order")
copy_action3 = menu.addAction("Given Order - Reverse")
# Display the menu at the mouse position
action = menu.exec_(self.mapToGlobal(pos))
# Handling each menu option
if action == atoz_action:
self.sortItemsAscending()
elif action == ztoa_action:
self.sortItemsDescending()
elif action == copy_action2:
self.resetOrder()
elif action == copy_action3:
self.reverseOrder()
def sortItemsAscending(self):
"""Sort items in ascending order (A to Z)."""
self.model().sort(0) # Sorts the items alphabetically ascending
self.setCurrentIndex(0)
def sortItemsDescending(self):
"""Sort items in descending order (Z to A)."""
# Get the items, reverse the list and set the model back
items = [self.itemText(i) for i in range(self.count())]
items.reverse()
self.clear()
self.addItems(items)
self.setCurrentIndex(0)
def resetOrder(self):
"""Reset to the original order of items (no change)."""
# Reset the items in the combo box as they were initially added
items = ['America', 'Russia', 'China', 'Germany', 'France', 'India']
self.clear()
self.addItems(items)
self.setCurrentIndex(0)
def reverseOrder(self):
"""Reverse the order of the items."""
# Reverse the original order of items
items = ['America', 'Russia', 'China', 'Germany', 'France', 'India']
items.reverse()
self.clear()
self.addItems(items)
self.setCurrentIndex(0)
class MyApp(QWidget):
def __init__(self):
super().__init__()
mainLayout = QVBoxLayout()
self.setLayout(mainLayout)
self.data = ['America', 'Russia', 'China', 'Germany', 'France', 'India']
self.combo = CheckableComboBox()
self.combo.setMinimumSize(600, 40)
btn = QPushButton('Print Values')
btn.clicked.connect(self.getValue)
mainLayout.addWidget(self.combo)
mainLayout.addWidget(btn)
self.combo.addItems(self.data)
def getValue(self):
print(self.combo.currentText())
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet('''QWidget {font-size: 20px;}''')
myApp = MyApp()
myApp.show()
app.exit(app.exec_())
Explanation:
-
Ascending Order (A to Z) – This is handled using
self.model().sort(0)
which sorts the combo box items in ascending order. -
Descending Order (Z to A) – We first fetch all the items using a list comprehension, reverse the list, and then clear and re-add the items in the reversed order.
-
Given Order – To reset the order to the original state (as it was when the items were initially added), we clear the combo box and re-add the items in their original order.
-
Given Order in Reverse – Similar to the previous case, we reverse the original list of items and then reset the combo box.
How It Works:
-
The
showMenu
method shows a context menu when you right-click on the combo box. -
Based on the user's selection from the context menu, the corresponding function is executed to rearrange the combo box items.
-
The sorting logic is applied to the combo box directly, modifying the order of the items based on the user's choice.
Output:
- Right-click on the combo box: A context menu will appear with the options "A to Z", "Z to A", "Given Order", and "Given Order - Reverse".
- Selecting an option will rearrange the items in the combo box as per the logic in the selected option.
This should give you the desired functionality of rearranging the combo box items in the four different orders.