【问题标题】:QTableView - Place pointer(highlight selection to the first row of listQTableView - 放置指针(突出显示选择到列表的第一行
【发布时间】:2013-06-11 22:57:51
【问题描述】:

我基于 QTableView 创建自己的小部件。它类似于文件对话框(列表)。我想凭直觉行事。

a) 使用整行

b) 指示器也适用于整行

c) 使用切换进入下层(子目录)

d) 运行程序后或移动到较低级别的光标必须在表格的第一行(第0行)

还有问题。我不能强制程序将光标放在第一行。 我尝试了几种方法,但都没有成功。设置当前索引。 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
}

提前感谢您的所有回复。

【问题讨论】:

    标签: c++ qt


    【解决方案1】:

    解决了! 问题是模型是异步的。所以在另一个线程中读取数据。当我尝试将索引设置为第一行时,仍然基本上不存在。解决方案当然是等待加载线程。此时发送信号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()));
    }
    

    【讨论】:

    • 解决方案就是这么简单!我怎么没想到?太明显了! directoryLoaded(QString) 在文档的 Signals 部分中。
    【解决方案2】:

    你不应该命名你的成员变量model。 QTableView 有函数 model(),编译器认为 this->model 是 this->model(),因此你得到你提到的错误。

    【讨论】:

    • 嗯...这是事实。我将模型重命名为 myModel。然而,即使是这种改变也无济于事。在我看来,模型与 QTableView 的连接不正确。但我找不到它在哪里。
    【解决方案3】:

    这是未经测试的代码,但我认为像这样应该工作:

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

    编辑:(2013-06-19 06: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.");
    }
    

    【讨论】:

    • 嗯.. 感谢您的回复,但这是我功​​能失调的测试之一 :-)。如果我使用 ->model()->index(0,0),程序会出错:'((mFileBoxWidget*)this)->mFileBoxWidget::model' 不能用作函数。当我使用不带 () 的 ->model->index(0, 0) 时,程序工作,但没有将光标放在第一行:-(。QT 5.0 中的 Next 不是 index(int row, int column) 的函数原型. 只有 index(int row, int column, const QModelIndex &parent = QModelIndex())const 尽管构建成功。
    • 我将尝试使用 QTableView 子类作为您的子类,看看是否可以复制问题。
    • 您是否尝试过使用QTableView::model() 获取模型实例?也就是说,你应该问超类...
    • 我需要制作我自己的元素(小部件),一个 FileList,它将被添加到各种对话框中。这样我就不必每次都定义它的属性。一切都在我的小部件中定义,然后在 X 个地方使用它。在这里,可能有问题。似乎 QTableView 比模型更早被激活。也许这是错?如果我在对话中直接使用 qtableview,一切都很好。当我使用我的小部件时,它的 Ko.
    • 我在查看您的代码后注意到了这一点。我理解你为什么想要一个 QTableView 子类。这就是为什么我删除了我制作的一些不相关的 cmets 并调整了我的示例。很抱歉一开始没有多注意。您是否尝试过在实例化 QTableView 子类(而不是构造函数中的那一行)之后分配模型?比如:yourQTableViewSubclass-&gt;setModel(new QFileSystemModel)
    猜你喜欢
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 1970-01-01
    • 2013-09-10
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多