2013-06-11 3 views
0

я создаю собственный виджет, основанный на QTableView Это что-то вроде диалога файлов (список) Я хочу действовать интуитивноQTableView - место указатель (. Выбор выделить в первой строке списка

а..) Работают с целыми рядами

б индикатор) также работал с целыми рядами

с) с использованием переключилось ввести нижний уровень (подкаталог)

д) после того, как программа запуска или переход на более низкий курсор уровня должен быть на первую строке таблица (строка 0)

И есть проблема. Я не могу заставить программу поместить курсор в первую строку. Я пробовал несколько методов, но ни один не удалось. setCurrentIndex. selectRow и т. д. Курсор всегда где-то в другом месте. Не выделено, а не на первой строке, но как только оно находится на 10 позиции в секунду на 4 позиции и т. Д. Это ведет себя непредсказуемо.

Как я могу это сделать?

Вот мой код:

mFileBoxWidget::mFileBoxWidget(QWidget *parent) : 
    QTableView(parent) 
    ,model(new QFileSystemModel()) 
{ 
    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
    this->setShowGrid(false); 
    this->verticalHeader()->setVisible(false); 
    this->installEventFilter(this); 
    model->setReadOnly(true); 
    this->setModel(model); 
    this->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); 
    this->setColumnWidth(1,70); 
    this->setColumnWidth(2,70); 
    this->setColumnWidth(3,110); 
    this->setRootIndex(model->setRootPath("C://")); 
    this->setSelectionMode(QAbstractItemView::SingleSelection); 
    this->setSelectionBehavior(QAbstractItemView::SelectRows); 
    //this->selectRow(0); //Does not work - goto first row 
    //this->setCurrentIndes(Index); //Does not work - goto index x=0 y=0 
} 

Спасибо Вам заранее за все ваши ответы.

ответ

2

Решенный! Проблема в том, что модель асинхронна. Так читает данные в другом потоке. Когда я попытался установить индекс в первую строку, по-прежнему в принципе не существовало. Решение, конечно же, ждет загрузки потока. В этот момент посылается сигнал directoryLoaded(QString). В результате необходимо дождаться сигнала, а затем установить индекс.

connect(myModel, SIGNAL(directoryLoaded(QString)), this, SLOT(onLoaded())); 

void mFileBoxWidget::onLoaded() 
{ 

    QModelIndex index = myModel->index(myModel->rootPath()); 

    this->setCurrentIndex(index.child(0, index.column())); 
} 
+0

Решение так просто! Как я об этом не думал? Это было так очевидно! 'directoryLoaded (QString)' находится в разделе [Сигналы] (http://qt-project.org/doc/qt-5.0/qtwidgets/qfilesystemmodel.html#directoryLoaded) в документации. – dschulz

0

Это непроверенный код, но я думаю, что-то вроде этого должны работы:

QModelIndex firstRow = QTableView::model()->index(0, 0); 
QTableView::selectionModel()->select(firstRow, 
           QItemSelectionModel::ClearAndSelect | 
           QItemSelectionModel::Rows); 

EDIT: (2013-06-19 6:12:58 UTC)

Простой (и уродливый) обходной путь, который работал до сих пор для меня, вызывает вызов m_tableView->selectRow(0); от QTimer.

Вот пример кода:

Заголовок:

#ifndef MAINWIDGET_H 
#define MAINWIDGET_H 

#include <QWidget> 

class QTableView; 
class QFileSystemModel; 

class MainWidget : public QWidget 
{ 
    Q_OBJECT 

public: 
    MainWidget(QWidget *parent = 0); 
    ~MainWidget(); 

private: 

    void layoutWidgets(); 

    QFileSystemModel *m_model; 
    QTableView *m_tableView; 

private slots: 

    void selectFirstRow(); 

    // for debugging only 
    void selectionChanged(); 
}; 

#endif // MAINWIDGET_H 

Реализация:

#include "mainwidget.h" 
#include <QTableView> 
#include <QHBoxLayout> 
#include <QFileSystemModel> 
#include <QHeaderView> 
#include <QTimer> 

MainWidget::MainWidget(QWidget *parent) 
: QWidget(parent) 
{ 

    m_tableView = new QTableView(this); 
    m_model = new QFileSystemModel(this); 
    m_model->setReadOnly(true); 

    m_tableView->setModel(m_model); 

    m_tableView->setRootIndex(m_model->setRootPath(QDir::homePath())); 
    m_tableView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
    m_tableView->setShowGrid(false); 
    m_tableView->verticalHeader()->setVisible(false); 
    m_tableView->setColumnWidth(1,70); 
    m_tableView->setColumnWidth(2,70); 
    m_tableView-> setColumnWidth(3,110); 
    m_tableView->setSelectionMode(QAbstractItemView::SingleSelection); 
    m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows); 
    //m_tableView->->setSectionResizeMode(0, QHeaderView::Stretch); // Qt 5? 

    layoutWidgets(); 

    connect(m_tableView->selectionModel(),  SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged())); 

    // This works 
    QTimer::singleShot(1000, this, SLOT(selectFirstRow())); 

    // Direct invocation - doesn't works 
    // selectFirstRow(); 
} 

void MainWidget::layoutWidgets() 
{ 
    QHBoxLayout *mainLayout = new QHBoxLayout; 
    mainLayout->addWidget(m_tableView); 
    setLayout(mainLayout); 
    setFixedSize(500,500); 
} 

void MainWidget::selectFirstRow() 
{  
    m_tableView->selectRow(0); 
} 

void MainWidget::selectionChanged() 
{ 
    qDebug("Selection changed"); 
} 

MainWidget::~MainWidget() 
{} 

Странная вещь, если QTimer::singleShot() потребности в срабатывать с задержкой по меньшей мере ~ 25 мс., иначе это не сработало бы в моей системе.

Вот альтернатива, подклассы QTableView:

#include "mytableview.h" 
#include <QFileSystemModel> 
#include <QHeaderView> 
#include <QTimer> 


MyTableView::MyTableView(QWidget *parent) : QTableView(parent) 
{ 

    QFileSystemModel *myModel = new QFileSystemModel; 

    setModel(myModel); 
    setRootIndex(myModel->setRootPath(QDir::homePath())); 


    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
    setShowGrid(false); 
    verticalHeader()->setVisible(false); 
    //installEventFilter(this); 
    myModel->setReadOnly(true); 

    //setSectionResizeMode(0, QHeaderView::Stretch); // Qt 5 

    setColumnWidth(1,70); 
    setColumnWidth(2,70); 
    setColumnWidth(3,110); 

    setSelectionMode(QAbstractItemView::SingleSelection); 
    setSelectionBehavior(QAbstractItemView::SelectRows); 



    QTimer::singleShot(100, this, SLOT(selectFirstRow())); 

    connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged())); 

} 

void MyTableView::selectFirstRow() 
{ 
// qDebug("Selecting first row"); 
// QModelIndex firstRow = QTableView::model()->index(0,0); 

// if(firstRow.isValid()){ 

//  selectionModel()->select(firstRow, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows ); 
// }else{ 
//  qDebug("Invalid index"); 
// } 

    selectRow(0); 
} 

void MyTableView::selectionChanged() 
{ 
    qDebug("Selection changed."); 
} 
+0

Хм .. спасибо за ответ, но это один из моих дисфункциональных тестов :-). Если я использую -> model() -> index (0,0), программа get error: '((mFileBoxWidget *) this) -> mFileBoxWidget :: model' не может использоваться как функция. Когда я использую -> model-> index (0, 0) без(), работает программа, но не помещает курсор в первую строку :-(. Далее в QT 5.0 не работает прототип функции для индекса (int row , int column) .Есть только индекс (int row, int column, const QModelIndex & parent = QModelIndex()) const Несмотря на успешную сборку. – exo

+0

- это 'mFileBoxWidget' экземпляр' QTableView', правильно? – dschulz

+0

Я попробую с подклассом 'QTableView' как ваш, чтобы увидеть, могу ли я реплицировать проблему. – dschulz

0

Вы не должны назвать переменной член модели. QTableView имеет функцию model(), компилятор считает, что this-> модель должна быть this-> model(), поэтому вы получаете указанную вами ошибку.

+0

Хм ... Это правда. Я переименовал модель в myModel. Однако даже это изменение не помогло. Мне кажется, что модель неправильно связана с QTableView. Но я не могу найти, где это. – exo

Смежные вопросы