2012-05-10 75 views
1

我有Qt應用程序與基於分割器的視圖:在左側是QListWidget包含可以選擇的文件;選定文件的內容將以適當的格式顯示在分離器的右側。這部分工作正常。QListWidget的自定義選擇

我現在需要添加比較功能:如果在QListWidget中選擇了一個項目,則其內容顯示在右側;如果選擇另一個項目,而不是我想顯示比較結果。 (事情比這更復雜一些,因爲不是所有的項目可以diff'ed。)

我想什麼做的是有一個單一的選擇能力不變,但隨後也使只有 CTRL +鼠標點擊第二選擇。我嘗試使用QAbstractItemView :: ExtendedSelection,然後篩選出Shift和鼠標拖動,但沒有這種方法運氣:雖然我可以捕獲Shift鍵keyPressEvent()我無法阻止選擇(我希望只是放棄事件就足夠了);至於拖我用mouseMoveEvent()希望在狀態改變爲DragSelectingState時刪除事件,但也沒有工作。

然後,我認爲堅持單選,但打開右鍵單擊第二項上下文菜單 - 而右鍵單擊確實發出itemSelectionChanged()信號,我還沒有想出如何處理這個,因爲我不'不知道哪個項目被右鍵單擊。

打開任何其他創造性的建議不涉及添加額外的UI元素 - 我不能有任何多餘的按鍵,組合框等

回答

0

仍然沒有想出如何限制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()