Пользовательский множественный выбор для QListWidget
У меня есть приложение Qt с представлением на основе сплиттера: слева находится QListWidget, содержащий файлы, которые можно выбрать; Содержимое выбранного файла отображается в соответствующем формате с правой стороны разделителя. Эта часть отлично работает.
Теперь мне нужно добавить функцию сравнения: если в QListWidget выбран один элемент, его содержимое отображается справа; если выбран другой элемент, я бы вместо этого хотел отобразить результат сравнения. (Все немного сложнее, чем то, потому что не все предметы могут быть отражены.)
То, что я хотел бы сделать, это иметь единственную возможность выбора без изменений, а затем включить только CTRL + щелчок мышью для второго выбора. Я пытался использовать QAbstractItemView::ExtendedSelection, а затем отфильтровывать Shift и перетаскивание мышью, но мне не повезло с таким подходом: хотя я мог захватить клавишу Shift с помощью keyPressEvent(), я не смог предотвратить выбор (я надеялся, что достаточно просто отбросить событие); Что касается перетаскивания, я использовал mouseMoveEvent(), надеясь сбросить событие, когда состояние изменится на DragSelectingState, но это тоже не сработало.
Затем я подумал о том, чтобы придерживаться одиночного выбора, но при открытии контекстного меню правой кнопкой мыши по второму элементу - хотя щелчок правой кнопкой не вызывает сигнал itemSelectionChanged(), я еще не понял, что с этим делать, так как не знаю, какой элемент был нажат правой кнопкой мыши.
Открыты для любых других творческих предложений, которые не включают в себя добавление дополнительных элементов пользовательского интерфейса - у меня не может быть никаких дополнительных кнопок, полей со списком и т. Д.
1 ответ
До сих пор не понял, как ограничить выборки в QListWidget только одним или двумя, но получил контекстное меню при щелчке правой кнопкой мыши по второму рабочему элементу.
Просто установите режим выделения на QAbstractItemView::SingleSelection, затем переопределите mousePressEvent() и contextMenuEvent().
class MyListView : public QListWidget
{
Q_OBJECT
public:
ListView();
virtual ~ListView() {}
/** Add item to the list.
@param itemName Item's display name.
@param itemHandle Value to return if item selected.
*/
void AddItem(const QString itemName, const quint32 itemHandle);
private slots:
void slot_ItemSelectionChanged(void);
void slot_Option1(void);
void slot_Option1(void);
signals:
void signal_ItemSelectionChanged(const qint32 itemHandle);
private:
void mousePressEvent(QMouseEvent* mousePressEvent);
void contextMenuEvent(QContextMenuEvent* menuEvent);
QListWidgetItem *m_selectedItem; ///< Pointer to the currently selected item.
QListWidgetItem *m_rightClickedItem; ///< Pointer to right-clicked item in the list.
QAction* m_menuOption1; ///< Menu option 1.
QAction* m_menuOption2; ///< Menu option 2.
QMenu* m_myListContextMenu; ///< Menu with all List View menu actions.
};
MyListView::MyListView()
{
setSelectionMode(QAbstractItemView::SingleSelection);
// create my context menu with 2 options
m_menuOption1 = new QAction(tr("option 1"), this);
m_menuOption1 ->setEnabled(true);
m_menuOption2 = new QAction(tr("option 2"), this);
m_menuOption2 ->setEnabled(true);
m_myListContextMenu = new QMenu(this);
m_myListContextMenu ->addAction(m_menuOption1);
m_myListContextMenu ->addAction(m_menuOption2);
bool allConnected = true;
// process primary selection
allConnected &= connect(this, SIGNAL(itemSelectionChanged(void)), this, SLOT(slot_ItemSelectionChanged(void)));
// process menu option 1
allConnected &= connect(m_menuOption1, SIGNAL(triggered()), this, SLOT(slot_Option1()));
// process menu option 2
allConnected &= connect(m_menuOption2, SIGNAL(triggered()), this, SLOT(slot_Option2()));
if (!allConnected )
{
assert(0);
}
}
void ListView::slot_ItemSelectionChanged(void)
{
if (currentItem() != m_selectedItem)
{
m_selectedItem = currentItem();
emit signal_ItemSelectionChanged(m_selectedItem->type());
}
} // end of method slot_ItemSelectionChanged()
void MyListView::contextMenuEvent(QContextMenuEvent* menuEvent)
{
m_rightClickedItem = itemAt(menuEvent->pos());
// do my prep stuff here specific to right-clicked item
// in case one of menu options gets selected
m_listMenu->exec(menuEvent->globalPos());
} // end of method contextMenuEvent()
void MyListView::mousePressEvent(QMouseEvent* mousePressEvent)
{
// drop right mouse button event as it would otherwise cause a change of selection
if (!(mousePressEvent->buttons() & Qt::RightButton))
{
QListWidget::mousePressEvent(mousePressEvent);
}
} // end of method mousePressEvent()