我想更改a的外观,包括物品和“ leandit-part”看起来不错/专业。
简单的部分:
组合框既可以用作搜索字段,又用于选择已经成功找到的符号。作为一个符号通常会提供几个结果,这些结果必须很容易被以组合框项目而彼此区分。
困难的部分/我失败的地方:
QCombobox
Combobox.LineEdit
.光学上相同。
当点击/具有焦点时:
Combobox-Item
我假设它必须/可以使用customqcombobox完成。但是,我所有的尝试都遭受了巨大的失败。
工作和代码段作为基础/实验:
Combobox.LineEdit
我想保持外观(LineEdit
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
import qdarkstyle
# from Custom_Widgets import CustomComboBox
class ComboBoxItemDelegate(QtWidgets.QStyledItemDelegate):
#This delegate will make the Combobox Items look nice
def paint(self, painter, option, index):
primary = index.data(QtCore.Qt.DisplayRole)
secondary = index.data(QtCore.Qt.UserRole)
if secondary is None:
secondary = ""
# Highlight Background if you mouseover
if option.state & QtWidgets.QStyle.State_Selected:
painter.fillRect(option.rect, option.palette.highlight())
else:
painter.fillRect(option.rect, option.palette.base())
# Make/Define the "Boxes" where primary and secondary will be written in
rect = option.rect.adjusted(5, 0, -5, 0)
primaryRect = QtCore.QRect(rect.left(), rect.top(), rect.width(), rect.height()//2)
secondaryRect = QtCore.QRect(rect.left(), rect.top() + rect.height()//2, rect.width(), rect.height()//2)
#Draw Primary
primaryFont = option.font
painter.setFont(primaryFont)
painter.setPen(option.palette.text().color())
painter.drawText(primaryRect, QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter, primary)
#Draw Secondary
secondaryFont = QtGui.QFont(option.font)
secondaryFont.setPointSize(option.font.pointSize() - 1)
painter.setFont(secondaryFont)
painter.setPen(QtGui.QColor("gray"))
painter.drawText(secondaryRect, QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter, secondary)
def sizeHint(self, option, index):
#Make it fit
size = super().sizeHint(option, index)
size.setHeight(int(size.height() * 1.6))
return size
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
items = [{'additional_info':'HELLO', 'Item':'SYMBOL'},
{'additional_info':'WORLD', 'Item':'G.I. JOE'},
{'additional_info':'NOVABRAIN', 'Item':'FLATEARTH'},
{'additional_info':'SUPERSTAR', 'Item':'BOB THE BUILDER'}]
for item in items:
self.initial_filling(item['Item'], item['additional_info'])
def initial_filling(self, primary, secondary):
self.searchComboBox.addItem(primary)
index = self.searchComboBox.model().index(self.searchComboBox.count()-1, 0)
self.searchComboBox.model().setData(index, secondary, role=QtCore.Qt.UserRole)
def initUI(self):
self.setWindowTitle("My best Widget")
self.resize(324, 500)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
layout = QtWidgets.QVBoxLayout(central_widget)
# Creating the Combobox
self.searchComboBox = QtWidgets.QComboBox()
self.searchComboBox.setEditable(True)
self.searchComboBox.setItemDelegate(ComboBoxItemDelegate(self.searchComboBox))
self.searchComboBox.setInsertPolicy(QtWidgets.QComboBox.NoInsert)
layout.addWidget(self.searchComboBox)
#Usually triggers API. Just think of it as "make menu" function
self.searchComboBox.lineEdit().returnPressed.connect(self.on_search_return)
#Updating LineEdit but ugly version
self.searchComboBox.currentIndexChanged.connect(self.updateComboBoxLineEdit)
# !(not relevant)! Dummy Table !(not relevant)!
self.table = QtWidgets.QTableWidget()
self.table.setColumnCount(3)
self.table.setHorizontalHeaderLabels(["Some", "Nice", "Table"])
self.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint)
self.table.verticalHeader().setVisible(False)
self.table.setShowGrid(False)
layout.addWidget(self.table)
def on_search_return(self):
#PREPARE INPUT FOR API CALL AND GETTING RESULT
symbol = self.searchComboBox.currentText().strip().upper()
if not symbol:
return
#.... RESULTS FROM API
results = [{'additional_info':'HELLO', 'Item':symbol},
{'additional_info':'WORLD', 'Item':symbol},
{'additional_info':'GALAXY', 'Item':symbol},
{'additional_info':'STAR', 'Item':symbol}]
self.show_lookup_menu(results)
def show_lookup_menu(self, results):
#Creating Menu based on results
menu = QtWidgets.QMenu(self)
for result in results:
text = f"{result['additional_info']} - {result['Item']}"
action = QtWidgets.QAction(text, menu)
action.setData(result)
menu.addAction(action)
menu.triggered.connect(self.on_menu_action_triggered)
pos = self.searchComboBox.mapToGlobal(QtCore.QPoint(0, self.searchComboBox.height()))
menu.exec_(pos)
def on_menu_action_triggered(self, action):
result = action.data()
if result:
print("You chose: ", result)
primary = result["Item"]
secondary = result["additional_info"]
if self.searchComboBox.findText(primary) == -1:
self.searchComboBox.addItem(primary)
index = self.searchComboBox.model().index(self.searchComboBox.count()-1, 0)
self.searchComboBox.model().setData(index, secondary, role=QtCore.Qt.UserRole)
def updateComboBoxLineEdit(self, index):
#Sadly LineEdit-Part of Combobox has no Delegate...
if index >= 0:
primary = self.searchComboBox.itemText(index)
secondary = self.searchComboBox.itemData(index, role=QtCore.Qt.UserRole)
if secondary:
combined = f"{primary} {secondary}"
else:
combined = primary
self.searchComboBox.lineEdit().setText(combined)
def main():
qt_app = QtWidgets.QApplication(sys.argv)
qt_app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
window = MainWindow()
window.show()
sys.exit(qt_app.exec_())
if __name__ == "__main__":
main()
和一个又一个又一个。 对我来说,次要是灰色,一个级别较小(以便很容易区分
primary/secondary
)才是很重要的
我通过嵌套两个customwidget。 首先,我创建了一个自定义QlineEdit,并覆盖了“小部件没有焦点”的油漆。NEXT,必须创建自定义的Qcombobox。在此中,每个组合的构建列被刚创建的CustomLineDIT覆盖。
最终,您应该覆盖CustomQcombobox的SizeHint方法,以便有足够的空间进行两行显示。
primary
ASDF