问题
I need to provide a reordering Dialog to let a user interactively order a list of strings. Does Qt already provide something fitting for this purpose?
I have searched the usual forums and examples but found nothing appropriate.
To clarify what I need:
Raw List:
- FileBaz
- FileFoo
- FileBar
User sorted list
- FileBar
- FileFoo
- FileBaz
So an arbitrary order as for example needed for merging formerly selected pdf files
回答1:
Qt already supports it, there's nothing for you to do: The standard views automatically support internal drag and drop, where items are moved around to change the order in which they are displayed.
Further quoting the documentation:
- To enable item dragging, set the view's
dragEnabledproperty to true. - To allow the user to drop both internal or external items within the view, set the view's viewport()'s
acceptDropsproperty to true. - To show the user where the item currently being dragged will be placed if dropped, set the view's
showDropIndicatorproperty. This provides the user with continuously updating information about item placement within the view. - To enable the user to move the items around within the view, we must set the list widget's dragDropMode to
QAbstractItemView::InternalMove.
Below is a sscce that you can run to see it in action.
#include <QApplication>
#include <QListWidget>
#include <QListWidgetItem>
int main(int argc, char ** argv)
{
QApplication a(argc, argv);
QListWidget w;
w.addItem("Rosalind");
w.addItem("Celia");
w.addItem("Adam");
w.addItem("Jaques");
w.setDragEnabled(true);
w.setDropIndicatorShown(true);
w.setDragDropMode(QAbstractItemView::InternalMove);
w.show();
return a.exec();
}
回答2:
Not that I know of. Something simple with a Move up button and a Move down button in coordination with a QListWidget may be useful, however. Up and Down would move around the list items in the respective direction, naturally.
Even easier, in my opinion, would be to use a QTreeWidget, as, if I recall correctly, there are some easy functions for swapping items around. A combination of something like
void insertTopLevelItem ( int index, QTreeWidgetItem * item )
QTreeWidgetItem *itemAbove ( const QTreeWidgetItem * item )
QTreeWidgetItem *itemBelow ( const QTreeWidgetItem * item )
QTreeWidgetItem *currentItem ()
int indexOfTopLevelItem ( QTreeWidgetItem * item )
may be useful. (Excerpts from http://qt-project.org/doc/qt-4.8/QTreeWidget.html)
Edit: I haven't used QListWidget much, but seems fairly similar to the QTreeWidget in terms of ease of swapping items around. Either one works.
回答3:
Just for completeness sake: Here is the solution I'm using in the end:
#include <QtGui>
class SortDialog:public QDialog{
Q_OBJECT
public:
SortDialog(QStringList* pList, QString const& title, QString const& middleButton);
int getSelectedItem() const;
private slots:
void slotAccept();
void slotItemUp();
void slotItemDown();
void slotSelectItem();
private:
QStringList* mpList;
QListWidget* mpListWidget;
int mSelectedItem;
};
SortDialog::SortDialog(QStringList* pList, QString const& title, QString const& middleButton):
QDialog(),
mpList(pList),
mpListWidget(new QListWidget()),
mSelectedItem(-1){
this->setWindowTitle(title);
QHBoxLayout* pMainLayout = new QHBoxLayout();
this->setLayout(pMainLayout);
QVBoxLayout* pListLayout = new QVBoxLayout();
pMainLayout->addLayout(pListLayout);
pListLayout->addWidget(mpListWidget);
mpListWidget->setDragEnabled(true);
mpListWidget->setDropIndicatorShown(true);
mpListWidget->setDragDropMode(QAbstractItemView::InternalMove);
boostForeach(QString const& string, *mpList) {
mpListWidget->addItem(string);
}
mpListWidget->setMinimumWidth(mpListWidget->sizeHintForColumn(0)+10);
mpListWidget->adjustSize();
mpList->clear();
QPushButton* confirm = new QPushButton(tr("Confirm"));
connect(confirm, SIGNAL(clicked()), this, SLOT(slotAccept()));
pListLayout->addWidget(confirm);
confirm->setDefault(true);
QVBoxLayout* pUpDownLayout = new QVBoxLayout();
pMainLayout->addLayout(pUpDownLayout);
QPushButton* up = new QPushButton(tr("Up"));
connect(up, SIGNAL(clicked()), this, SLOT(slotItemUp()));
pUpDownLayout->addWidget(up);
QPushButton* down = new QPushButton(tr("Down"));
connect(down, SIGNAL(clicked()), this, SLOT(slotItemDown()));
pUpDownLayout->addWidget(down);
QPushButton* ground = new QPushButton(middleButton);
connect(ground, SIGNAL(clicked()), this, SLOT(slotSelectItem()));
pUpDownLayout->addWidget(ground);
this->adjustSize();
}
int SortDialog::getSelectedItem() const{
return mSelectedItem;
}
void SortDialog::slotAccept(){
int count = mpListWidget->count();
for(int index = 0; index < count; index++){
QListWidgetItem * item = mpListWidget->item(index);
mpList->push_back(item->text());
}
this->close();
}
void SortDialog::slotItemUp(){
int row = mpListWidget->currentRow();
if(row>0){
QListWidgetItem* pTemp = mpListWidget->takeItem(row);
mpListWidget->insertItem(row-1,pTemp);
mpListWidget->setCurrentRow(row-1);
}
}
void SortDialog::slotItemDown(){
int row = mpListWidget->currentRow();
if(row<mpListWidget->count()-1){
QListWidgetItem* pTemp = mpListWidget->takeItem(row);
mpListWidget->insertItem(row+1,pTemp);
mpListWidget->setCurrentRow(row+1);
}
}
void SortDialog::slotSelectItem(){
int count = mpListWidget->count();
for(int index = 0; index < count; index++){
QListWidgetItem * item = mpListWidget->item(index);
QFont font = item->font();
font.setBold(false);
item->setFont(font);
}
mSelectedItem =mpListWidget->currentRow();
qDebug() << mSelectedItem;
QListWidgetItem* pTemp = mpListWidget->currentItem();
QFont font = pTemp->font();
font.setBold(true);
pTemp->setFont(font);
}
来源:https://stackoverflow.com/questions/11216600/is-there-a-qt-dialog-or-widget-to-interactively-sort-a-string-list