A WTableView displays tabular data. The data is provided by a separate WAbstractItemModel. This is a variation of the classical MVC strategy, where the View displays data provided by a Model. The View delegates the rendering of each individual item (i.e. table cell) to an Item Delegate (WItemDelegate to render an item as a widget, allowing this aspect to be customized without needing to deal with the rest of the complexity of the view.
A more direct approach to showing a table of data is to use a
WTable which allows you to directly specify a widget
that renders each cell. Compared to this, a WTableView
support virtual scrolling (for both rows and columns !), column
sorting and resize handles, and the ability to define row
headers which allow you to scroll through many columns of
additional data while keeping the first header column(s) within
view. Its main restriction is that every item must have the same
height.
A tableview has the capability to display large datasets, by implementing virtual scrolling both horizontally and vertically.
The example below shows how one can scroll through data in a virtual model with 10000 rows and 50 columns.
Column 0 | Column 1 | Column 2 | Column 3 | Column 4 | Column 5 | Column 6 | Column 7 | Column 8 | Column 9 | Column 10 | Column 11 | Column 12 | Column 13 | Column 14 | Column 15 | Column 16 | Column 17 | Column 18 | Column 19 | Column 20 | Column 21 | Column 22 | Column 23 | Column 24 | Column 25 | Column 26 | Column 27 | Column 28 | Column 29 | Column 30 | Column 31 | Column 32 | Column 33 | Column 34 | Column 35 | Column 36 | Column 37 | Column 38 | Column 39 | Column 40 | Column 41 | Column 42 | Column 43 | Column 44 | Column 45 | Column 46 | Column 47 | Column 48 | Column 49 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Row 0 | Item row 0, col 1 | Item row 0, col 2 | Item row 0, col 3 | Item row 0, col 4 | Item row 0, col 5 | Item row 0, col 6 | Item row 0, col 7 | Item row 0, col 8 | Item row 0, col 9 | Item row 0, col 10 | Item row 0, col 11 | Item row 0, col 12 | Item row 0, col 13 | Item row 0, col 14 | Item row 0, col 15 | Item row 0, col 16 | Item row 0, col 17 | Item row 0, col 18 | Item row 0, col 19 | Item row 0, col 20 | Item row 0, col 21 | Item row 0, col 22 | Item row 0, col 23 | Item row 0, col 24 | Item row 0, col 25 | Item row 0, col 26 | Item row 0, col 27 | Item row 0, col 28 | Item row 0, col 29 | Item row 0, col 30 | Item row 0, col 31 | Item row 0, col 32 | Item row 0, col 33 | Item row 0, col 34 | Item row 0, col 35 | Item row 0, col 36 | Item row 0, col 37 | Item row 0, col 38 | Item row 0, col 39 | Item row 0, col 40 | Item row 0, col 41 | Item row 0, col 42 | Item row 0, col 43 | Item row 0, col 44 | Item row 0, col 45 | Item row 0, col 46 | Item row 0, col 47 | Item row 0, col 48 | Item row 0, col 49 |
Row 1 | Item row 1, col 1 | Item row 1, col 2 | Item row 1, col 3 | Item row 1, col 4 | Item row 1, col 5 | Item row 1, col 6 | Item row 1, col 7 | Item row 1, col 8 | Item row 1, col 9 | Item row 1, col 10 | Item row 1, col 11 | Item row 1, col 12 | Item row 1, col 13 | Item row 1, col 14 | Item row 1, col 15 | Item row 1, col 16 | Item row 1, col 17 | Item row 1, col 18 | Item row 1, col 19 | Item row 1, col 20 | Item row 1, col 21 | Item row 1, col 22 | Item row 1, col 23 | Item row 1, col 24 | Item row 1, col 25 | Item row 1, col 26 | Item row 1, col 27 | Item row 1, col 28 | Item row 1, col 29 | Item row 1, col 30 | Item row 1, col 31 | Item row 1, col 32 | Item row 1, col 33 | Item row 1, col 34 | Item row 1, col 35 | Item row 1, col 36 | Item row 1, col 37 | Item row 1, col 38 | Item row 1, col 39 | Item row 1, col 40 | Item row 1, col 41 | Item row 1, col 42 | Item row 1, col 43 | Item row 1, col 44 | Item row 1, col 45 | Item row 1, col 46 | Item row 1, col 47 | Item row 1, col 48 | Item row 1, col 49 |
Row 2 | Item row 2, col 1 | Item row 2, col 2 | Item row 2, col 3 | Item row 2, col 4 | Item row 2, col 5 | Item row 2, col 6 | Item row 2, col 7 | Item row 2, col 8 | Item row 2, col 9 | Item row 2, col 10 | Item row 2, col 11 | Item row 2, col 12 | Item row 2, col 13 | Item row 2, col 14 | Item row 2, col 15 | Item row 2, col 16 | Item row 2, col 17 | Item row 2, col 18 | Item row 2, col 19 | Item row 2, col 20 | Item row 2, col 21 | Item row 2, col 22 | Item row 2, col 23 | Item row 2, col 24 | Item row 2, col 25 | Item row 2, col 26 | Item row 2, col 27 | Item row 2, col 28 | Item row 2, col 29 | Item row 2, col 30 | Item row 2, col 31 | Item row 2, col 32 | Item row 2, col 33 | Item row 2, col 34 | Item row 2, col 35 | Item row 2, col 36 | Item row 2, col 37 | Item row 2, col 38 | Item row 2, col 39 | Item row 2, col 40 | Item row 2, col 41 | Item row 2, col 42 | Item row 2, col 43 | Item row 2, col 44 | Item row 2, col 45 | Item row 2, col 46 | Item row 2, col 47 | Item row 2, col 48 | Item row 2, col 49 |
Row 3 | Item row 3, col 1 | Item row 3, col 2 | Item row 3, col 3 | Item row 3, col 4 | Item row 3, col 5 | Item row 3, col 6 | Item row 3, col 7 | Item row 3, col 8 | Item row 3, col 9 | Item row 3, col 10 | Item row 3, col 11 | Item row 3, col 12 | Item row 3, col 13 | Item row 3, col 14 | Item row 3, col 15 | Item row 3, col 16 | Item row 3, col 17 | Item row 3, col 18 | Item row 3, col 19 | Item row 3, col 20 | Item row 3, col 21 | Item row 3, col 22 | Item row 3, col 23 | Item row 3, col 24 | Item row 3, col 25 | Item row 3, col 26 | Item row 3, col 27 | Item row 3, col 28 | Item row 3, col 29 | Item row 3, col 30 | Item row 3, col 31 | Item row 3, col 32 | Item row 3, col 33 | Item row 3, col 34 | Item row 3, col 35 | Item row 3, col 36 | Item row 3, col 37 | Item row 3, col 38 | Item row 3, col 39 | Item row 3, col 40 | Item row 3, col 41 | Item row 3, col 42 | Item row 3, col 43 | Item row 3, col 44 | Item row 3, col 45 | Item row 3, col 46 | Item row 3, col 47 | Item row 3, col 48 | Item row 3, col 49 |
Row 4 | Item row 4, col 1 | Item row 4, col 2 | Item row 4, col 3 | Item row 4, col 4 | Item row 4, col 5 | Item row 4, col 6 | Item row 4, col 7 | Item row 4, col 8 | Item row 4, col 9 | Item row 4, col 10 | Item row 4, col 11 | Item row 4, col 12 | Item row 4, col 13 | Item row 4, col 14 | Item row 4, col 15 | Item row 4, col 16 | Item row 4, col 17 | Item row 4, col 18 | Item row 4, col 19 | Item row 4, col 20 | Item row 4, col 21 | Item row 4, col 22 | Item row 4, col 23 | Item row 4, col 24 | Item row 4, col 25 | Item row 4, col 26 | Item row 4, col 27 | Item row 4, col 28 | Item row 4, col 29 | Item row 4, col 30 | Item row 4, col 31 | Item row 4, col 32 | Item row 4, col 33 | Item row 4, col 34 | Item row 4, col 35 | Item row 4, col 36 | Item row 4, col 37 | Item row 4, col 38 | Item row 4, col 39 | Item row 4, col 40 | Item row 4, col 41 | Item row 4, col 42 | Item row 4, col 43 | Item row 4, col 44 | Item row 4, col 45 | Item row 4, col 46 | Item row 4, col 47 | Item row 4, col 48 | Item row 4, col 49 |
Row 5 | Item row 5, col 1 | Item row 5, col 2 | Item row 5, col 3 | Item row 5, col 4 | Item row 5, col 5 | Item row 5, col 6 | Item row 5, col 7 | Item row 5, col 8 | Item row 5, col 9 | Item row 5, col 10 | Item row 5, col 11 | Item row 5, col 12 | Item row 5, col 13 | Item row 5, col 14 | Item row 5, col 15 | Item row 5, col 16 | Item row 5, col 17 | Item row 5, col 18 | Item row 5, col 19 | Item row 5, col 20 | Item row 5, col 21 | Item row 5, col 22 | Item row 5, col 23 | Item row 5, col 24 | Item row 5, col 25 | Item row 5, col 26 | Item row 5, col 27 | Item row 5, col 28 | Item row 5, col 29 | Item row 5, col 30 | Item row 5, col 31 | Item row 5, col 32 | Item row 5, col 33 | Item row 5, col 34 | Item row 5, col 35 | Item row 5, col 36 | Item row 5, col 37 | Item row 5, col 38 | Item row 5, col 39 | Item row 5, col 40 | Item row 5, col 41 | Item row 5, col 42 | Item row 5, col 43 | Item row 5, col 44 | Item row 5, col 45 | Item row 5, col 46 | Item row 5, col 47 | Item row 5, col 48 | Item row 5, col 49 |
Row 6 | Item row 6, col 1 | Item row 6, col 2 | Item row 6, col 3 | Item row 6, col 4 | Item row 6, col 5 | Item row 6, col 6 | Item row 6, col 7 | Item row 6, col 8 | Item row 6, col 9 | Item row 6, col 10 | Item row 6, col 11 | Item row 6, col 12 | Item row 6, col 13 | Item row 6, col 14 | Item row 6, col 15 | Item row 6, col 16 | Item row 6, col 17 | Item row 6, col 18 | Item row 6, col 19 | Item row 6, col 20 | Item row 6, col 21 | Item row 6, col 22 | Item row 6, col 23 | Item row 6, col 24 | Item row 6, col 25 | Item row 6, col 26 | Item row 6, col 27 | Item row 6, col 28 | Item row 6, col 29 | Item row 6, col 30 | Item row 6, col 31 | Item row 6, col 32 | Item row 6, col 33 | Item row 6, col 34 | Item row 6, col 35 | Item row 6, col 36 | Item row 6, col 37 | Item row 6, col 38 | Item row 6, col 39 | Item row 6, col 40 | Item row 6, col 41 | Item row 6, col 42 | Item row 6, col 43 | Item row 6, col 44 | Item row 6, col 45 | Item row 6, col 46 | Item row 6, col 47 | Item row 6, col 48 | Item row 6, col 49 |
Row 7 | Item row 7, col 1 | Item row 7, col 2 | Item row 7, col 3 | Item row 7, col 4 | Item row 7, col 5 | Item row 7, col 6 | Item row 7, col 7 | Item row 7, col 8 | Item row 7, col 9 | Item row 7, col 10 | Item row 7, col 11 | Item row 7, col 12 | Item row 7, col 13 | Item row 7, col 14 | Item row 7, col 15 | Item row 7, col 16 | Item row 7, col 17 | Item row 7, col 18 | Item row 7, col 19 | Item row 7, col 20 | Item row 7, col 21 | Item row 7, col 22 | Item row 7, col 23 | Item row 7, col 24 | Item row 7, col 25 | Item row 7, col 26 | Item row 7, col 27 | Item row 7, col 28 | Item row 7, col 29 | Item row 7, col 30 | Item row 7, col 31 | Item row 7, col 32 | Item row 7, col 33 | Item row 7, col 34 | Item row 7, col 35 | Item row 7, col 36 | Item row 7, col 37 | Item row 7, col 38 | Item row 7, col 39 | Item row 7, col 40 | Item row 7, col 41 | Item row 7, col 42 | Item row 7, col 43 | Item row 7, col 44 | Item row 7, col 45 | Item row 7, col 46 | Item row 7, col 47 | Item row 7, col 48 | Item row 7, col 49 |
Row 8 | Item row 8, col 1 | Item row 8, col 2 | Item row 8, col 3 | Item row 8, col 4 | Item row 8, col 5 | Item row 8, col 6 | Item row 8, col 7 | Item row 8, col 8 | Item row 8, col 9 | Item row 8, col 10 | Item row 8, col 11 | Item row 8, col 12 | Item row 8, col 13 | Item row 8, col 14 | Item row 8, col 15 | Item row 8, col 16 | Item row 8, col 17 | Item row 8, col 18 | Item row 8, col 19 | Item row 8, col 20 | Item row 8, col 21 | Item row 8, col 22 | Item row 8, col 23 | Item row 8, col 24 | Item row 8, col 25 | Item row 8, col 26 | Item row 8, col 27 | Item row 8, col 28 | Item row 8, col 29 | Item row 8, col 30 | Item row 8, col 31 | Item row 8, col 32 | Item row 8, col 33 | Item row 8, col 34 | Item row 8, col 35 | Item row 8, col 36 | Item row 8, col 37 | Item row 8, col 38 | Item row 8, col 39 | Item row 8, col 40 | Item row 8, col 41 | Item row 8, col 42 | Item row 8, col 43 | Item row 8, col 44 | Item row 8, col 45 | Item row 8, col 46 | Item row 8, col 47 | Item row 8, col 48 | Item row 8, col 49 |
Row 9 | Item row 9, col 1 | Item row 9, col 2 | Item row 9, col 3 | Item row 9, col 4 | Item row 9, col 5 | Item row 9, col 6 | Item row 9, col 7 | Item row 9, col 8 | Item row 9, col 9 | Item row 9, col 10 | Item row 9, col 11 | Item row 9, col 12 | Item row 9, col 13 | Item row 9, col 14 | Item row 9, col 15 | Item row 9, col 16 | Item row 9, col 17 | Item row 9, col 18 | Item row 9, col 19 | Item row 9, col 20 | Item row 9, col 21 | Item row 9, col 22 | Item row 9, col 23 | Item row 9, col 24 | Item row 9, col 25 | Item row 9, col 26 | Item row 9, col 27 | Item row 9, col 28 | Item row 9, col 29 | Item row 9, col 30 | Item row 9, col 31 | Item row 9, col 32 | Item row 9, col 33 | Item row 9, col 34 | Item row 9, col 35 | Item row 9, col 36 | Item row 9, col 37 | Item row 9, col 38 | Item row 9, col 39 | Item row 9, col 40 | Item row 9, col 41 | Item row 9, col 42 | Item row 9, col 43 | Item row 9, col 44 | Item row 9, col 45 | Item row 9, col 46 | Item row 9, col 47 | Item row 9, col 48 | Item row 9, col 49 |
Row 10 | Item row 10, col 1 | Item row 10, col 2 | Item row 10, col 3 | Item row 10, col 4 | Item row 10, col 5 | Item row 10, col 6 | Item row 10, col 7 | Item row 10, col 8 | Item row 10, col 9 | Item row 10, col 10 | Item row 10, col 11 | Item row 10, col 12 | Item row 10, col 13 | Item row 10, col 14 | Item row 10, col 15 | Item row 10, col 16 | Item row 10, col 17 | Item row 10, col 18 | Item row 10, col 19 | Item row 10, col 20 | Item row 10, col 21 | Item row 10, col 22 | Item row 10, col 23 | Item row 10, col 24 | Item row 10, col 25 | Item row 10, col 26 | Item row 10, col 27 | Item row 10, col 28 | Item row 10, col 29 | Item row 10, col 30 | Item row 10, col 31 | Item row 10, col 32 | Item row 10, col 33 | Item row 10, col 34 | Item row 10, col 35 | Item row 10, col 36 | Item row 10, col 37 | Item row 10, col 38 | Item row 10, col 39 | Item row 10, col 40 | Item row 10, col 41 | Item row 10, col 42 | Item row 10, col 43 | Item row 10, col 44 | Item row 10, col 45 | Item row 10, col 46 | Item row 10, col 47 | Item row 10, col 48 | Item row 10, col 49 |
Row 11 | Item row 11, col 1 | Item row 11, col 2 | Item row 11, col 3 | Item row 11, col 4 | Item row 11, col 5 | Item row 11, col 6 | Item row 11, col 7 | Item row 11, col 8 | Item row 11, col 9 | Item row 11, col 10 | Item row 11, col 11 | Item row 11, col 12 | Item row 11, col 13 | Item row 11, col 14 | Item row 11, col 15 | Item row 11, col 16 | Item row 11, col 17 | Item row 11, col 18 | Item row 11, col 19 | Item row 11, col 20 | Item row 11, col 21 | Item row 11, col 22 | Item row 11, col 23 | Item row 11, col 24 | Item row 11, col 25 | Item row 11, col 26 | Item row 11, col 27 | Item row 11, col 28 | Item row 11, col 29 | Item row 11, col 30 | Item row 11, col 31 | Item row 11, col 32 | Item row 11, col 33 | Item row 11, col 34 | Item row 11, col 35 | Item row 11, col 36 | Item row 11, col 37 | Item row 11, col 38 | Item row 11, col 39 | Item row 11, col 40 | Item row 11, col 41 | Item row 11, col 42 | Item row 11, col 43 | Item row 11, col 44 | Item row 11, col 45 | Item row 11, col 46 | Item row 11, col 47 | Item row 11, col 48 | Item row 11, col 49 |
#include <Wt/WTableView.h>
#include "VirtualModel.cpp"
using namespace Wt;
auto tableView = std::make_unique<WTableView>();
tableView->setModel(std::make_shared<VirtualModel>(10000, 50));
tableView->setRowHeaderCount(1); // treat first column as 'fixed' row headers
tableView->setSortingEnabled(false);
tableView->setAlternatingRowColors(true);
tableView->setRowHeight(28);
tableView->setHeaderHeight(28);
tableView->setSelectionMode(SelectionMode::Extended);
tableView->setEditTriggers(EditTrigger::None);
tableView->resize(650, 400);
VirtualModel
is shown
in the section on item
models
The rendering of each cell is handled by a WAbstractItemDelegate. An item delegate will typically query various properties of an item, which are provided by the model for different data roles (which one can consider pretty much like a 3rd dimension for what otherwise corresponds to two-dimensional model organized in rows and columns). The default implementation (WItemDelegate) will
DisplayRole
,DecorationRole
,CheckStateRole
,LinkRole
,ToolTipRole
,StyleClassRole
.MVC Views will automatically react to changes to the underlying model, be it in the form of data updates, or the insertion of new rows or columns.
But an MVC View may also actively participate in editing the
data. You can define editing triggers (such as a double click)
and the model can indicate to the view which data can be
edited. The default item delegate (WItemDelegate
) will
use a line edit for editing, but this can be customized by
providing your own item delegate implementation.
The example below illustrates how to override the editing behaviour of WItemDelegate. It uses a combo box to allow the user to edit the cell values.
apples | apples |
apples | apples |
#include <Wt/WStandardItem.h>
#include <Wt/WStandardItemModel.h>
#include <Wt/WStringListModel.h>
#include <Wt/WTableView.h>
#include <Wt/WItemDelegate.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WComboBox.h>
#include <Wt/WAny.h>
/*
* This delegate demonstrates how to override the editing behaviour of a
* table cell.
*
* It takes a list of possible items on construction and, when edited, saves
* the selected item from the list to the Wt::DisplayRole in the model for
* Wt::WItemDelegate to render.
* It also saves the items index for future editing (rather than each time
* searching the item in the list). This is done using the general purpose
* Wt::UserRole in the model.
*/
class ComboDelegate : public Wt::WItemDelegate {
public:
ComboDelegate(std::shared_ptr<Wt::WAbstractItemModel> items)
: items_(items)
{ }
virtual void setModelData(const Wt::cpp17::any &editState, Wt::WAbstractItemModel* model,
const Wt::WModelIndex &index) const override
{
int stringIdx = (int)Wt::asNumber(editState);
model->setData(index, stringIdx, Wt::ItemDataRole::User);
model->setData(index, items_->data(stringIdx, 0), Wt::ItemDataRole::Display);
}
virtual Wt::cpp17::any editState(Wt::WWidget *editor, const Wt::WModelIndex& index) const override
{
Wt::WComboBox* combo = dynamic_cast<Wt::WComboBox*>
(dynamic_cast<Wt::WContainerWidget*>(editor)->widget(0));
return combo->currentIndex();
}
virtual void setEditState(Wt::WWidget *editor, const Wt::WModelIndex& index,
const Wt::cpp17::any& value) const override
{
Wt::WComboBox* combo = dynamic_cast<Wt::WComboBox*>
(dynamic_cast<Wt::WContainerWidget*>(editor)->widget(0));
combo->setCurrentIndex((int)Wt::asNumber(value));
}
protected:
virtual std::unique_ptr<Wt::WWidget> createEditor(const Wt::WModelIndex &index,
Wt::WFlags<Wt::ViewItemRenderFlag> flags) const override
{
auto container = std::make_unique<Wt::WContainerWidget>();
auto combo = container->addNew<Wt::WComboBox>();
combo->setModel(items_);
combo->setCurrentIndex((int)Wt::asNumber(index.data(Wt::ItemDataRole::User)));
combo->changed().connect(std::bind(&ComboDelegate::doCloseEditor, this,
container.get(), true));
combo->enterPressed().connect(std::bind(&ComboDelegate::doCloseEditor,
this, container.get(), true));
combo->escapePressed().connect(std::bind(&ComboDelegate::doCloseEditor,
this, container.get(), false));
return std::move(container);
}
private:
std::shared_ptr<Wt::WAbstractItemModel> items_;
virtual void doCloseEditor(Wt::WWidget *editor, bool save) const
{
closeEditor().emit(editor, save);
}
};
auto table = std::make_unique<Wt::WTableView>();
// create model
std::vector<WString> options { "apples", "pears", "bananas", "cherries" };
auto model = std::make_shared<Wt::WStandardItemModel>();
for (unsigned i=0; i < 2; i++) {
for (unsigned j=0; j < 2; j++) {
auto item = std::make_unique<Wt::WStandardItem>();
item->setData(0, Wt::ItemDataRole::User);
item->setData(options[0], Wt::ItemDataRole::Display);
item->setFlags(Wt::ItemFlag::Editable);
model->setItem(i, j, std::move(item));
}
}
// create table
table->setModel(model);
table->setEditTriggers(Wt::EditTrigger::SingleClicked);
auto slModel = std::make_shared<Wt::WStringListModel>();
slModel->setStringList(options);
std::shared_ptr<ComboDelegate> customdelegate =
std::make_shared<ComboDelegate>(slModel);
table->setItemDelegate(customdelegate);
table->setSortingEnabled(false);
table->setColumnResizeEnabled(false);
table->setRowHeight(40);
table->setHeaderHeight(0);
const int WIDTH = 120;
for (int i = 0; i < table->model()->columnCount(); ++i)
table->setColumnWidth(i, WIDTH);
table->setWidth((WIDTH + 7) * table->model()->columnCount() + 2);
Especially when displaying datasets with many columns, it may be
convenient to define a number of columns as row headers (using
WAbstractItemView::setRowHeaderCount()
), which are kept
in view while scrolling to the columns.