Issue
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.
Solution
QComboBox uses a Qt model for its items (the default is a QStandardItemModel), so you can use sort()
to change the sorting depending on your needs.
Since you also need to reverse the original order, a possible solution is to add a custom data field (using setItemData()
) that simply stores the source index.
Then it's just a matter of choosing the sortRole
and order.
class CheckableComboBox(QComboBox):
def __init__(self):
super().__init__()
self.setEditable(True)
self.lineEdit().setReadOnly(True)
self.setStyleSheet("""
QComboBox QAbstractItemView::item {
border: none;
padding-left: 5px;
}
""")
def contextMenuEvent(self, event):
model = self.model()
for i in range(model.rowCount()):
if self.itemData(i) is None:
self.setItemData(i, i)
menu = QMenu()
atoz_action = menu.addAction("A to Z - Ascending Order")
ztoa_action = menu.addAction(("Z to A - Descending Order"))
copy_action1 = menu.addSeparator()
originalAction = menu.addAction(("Given Order"))
reverseAction = menu.addAction(("Given Order - Reverse"))
action = menu.exec_(event.globalPos())
if action in (atoz_action, ztoa_action):
model.setSortRole(Qt.DisplayRole)
else:
model.setSortRole(Qt.UserRole)
if action in (atoz_action, originalAction):
order = Qt.AscendingOrder
else:
order = Qt.DescendingOrder
model.sort(self.modelColumn(), order)
Note that I replaced the showMenu
function with a more appropriate override of customContextMenu
, and I also removed the repositioning because it used an unreliable computation (and an obsolete class, QDesktopWidget) which placed the menu in odd and confusing places.
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.