問題描述
首先,我想說我已經閱讀了有關 Qt 和 MVC 的所有其他問題,但是我找不到我要找的內容.因此,除非您在舊問題中找到了實際回答我的問題的內容,否則請不要將它們與我聯系起來.我也在 qt.dgia.com 和 qt.project.com 中搜索過,但還是沒有運氣.
First of all I would like to say that I' ve already read all the other questions about Qt and MVC, but I couldn't find what I'm looking for. So please, unless you find something in the old questions that actually answer my question, don't link them to me. I also searched in qt.digia.com and qt.project.com but again, no luck.
現在來解決我的問題.我必須實現一個簡單的圖像比較器,它可以并排顯示圖像,以便可以比較它們.我必須使用 MVC 來做到這一點.我的問題是我從未使用過 Qt,我對如何將它與 MVC 一起使用感到有些困惑.
So now to my problem. I have to implement a simple image comparator that shows to image side by side so that they can be compared. I have to use MVC to do this. My problem is that I've never used Qt and I'm a bit confused on how to use it with MVC.
特別是,我想知道 MainWindow 應該從哪個子類化.是視圖還是模型,還是兩者兼而有之?這是我的想法. MainWindow 是我的類圖中的一個視圖,但我不確定,因為它也有模型的元素,因為它實際上存儲了數據信息.你有什么建議?那么如何設計其他類呢?謝謝.
In particular, I am wondering what MainWindow should be subclassed from. It is the View or the Model, or both? This is what I thought. MainWindow is a View in my class diagram, but I'm not sure of that, because it also has elements of a model, since it actually stores data information. What do you suggest? Then how would design the other classes? Thank you.
推薦答案
Qt 并未整體實現標準"MVC 模式 - 您需要從頭開始重新實現這樣的框架.Qt 提供了一個模型視圖框架,為 MVVM 提供了足夠的功能,但這不是 MVC 的書本.
Qt does not implement the "standard" MVC pattern as a whole - you would need to reimplement such a framework from scratch. Qt offers a model-view framework that offers enough functionality for MVVM, but that's not MVC-by-the-book.
在 Qt 的實現中,視圖和控制器混合在一起.視圖是向用戶顯示模型以及用戶在代理的幫助下與模型交互的內容.
In Qt's implementation, the view and the controller are mingled together. The view is what shows the model to the user and what the user uses to interact with the model, with help of delegates.
因此,單獨控制器的問題基本上沒有實際意義,因為沒有.在 Qt 中,具體視圖是您通常不會從中派生的獨立小部件.相反,您將視圖集成(has-a)到一個包含其他控件的更大的小部件中.
Thus, the question of a separate controller is essentially moot, as there isn't one. In Qt, a concrete view is a stand-alone widget that you normally don't derive from. Instead, you integrate (has-a) the view into a larger widget that holds other controls.
Qt 提供了一些標準視圖(列表視圖、表格視圖和樹視圖).還有 QDataWidgetMapper
可以讓您將模型中的一個索引映射到任何小部件的用戶屬性.還有多種型號可供選擇.抽象模型是您自己實現的基礎.然后是 QStandardItemModel
,它提供了靈活的數據樹/表存儲.最后,QSqlQueryModel
和 QSqlRelationalTableModel
將 SQL 數據庫作為模型公開.
Qt provides some standard views (a list view, a table view and a tree view). There's also the QDataWidgetMapper
that lets you map one index from a model onto the user property of any widget. There are also several models to choose from. The abstract models are bases for your own implementations. Then there's the QStandardItemModel
that provides a flexible tree/table storage of data. Finally, QSqlQueryModel
and QSqlRelationalTableModel
expose SQL databases as models.
在下面的示例中,比較器被實現為一個視圖模型 - 一個代理,用比較的結果修改底層圖像提供模型.對于要顯示的圖像,需要在 Qt::DecorationRole
下提供它們.主窗口只是視圖(is-a),不需要子類化.
In the example below, the comparator is implemented as a viewmodel - a proxy that amends the underlying image-providing model with results of the comparison. For the images to be displayed, they need to be provided under the Qt::DecorationRole
. The main window is simply the view (is-a), and no subclassing is necessary.
#include <QApplication>
#include <QTableView>
#include <QIdentityProxyModel>
#include <QStandardItemModel>
#include <QPainter>
/** Adds image comparison results to a table/tree with pairs of images in each row.
*
* This is a viewmodel that expects a table or tree with row containing pairs of images in the
* first two columns. Comparison results are visualized as the added last column.
* A null result is provided for rows that don't have two images as their first two columns.
*/
class Comparator : public QIdentityProxyModel {
Q_OBJECT
bool isLastColumn(const QModelIndex & proxyIndex) const {
return proxyIndex.column() == columnCount(proxyIndex.parent()) - 1;
}
QModelIndex indexInColumn(int column, const QModelIndex & proxyIndex) const {
return index(proxyIndex.row(), column, proxyIndex.parent());
}
/** Compares the two images, returning their difference..
* Both images are expanded to the larger of their sizes. Missing data is filled with
* transparent pixels. The images can be in any format. The difference is in ARGB32. */
QImage compare(const QImage & left, const QImage & right) const {
QImage delta(left.size().expandedTo(right.size()), QImage::Format_ARGB32);
delta.fill(Qt::transparent);
QPainter p(&delta);
p.setRenderHint(QPainter::Antialiasing);
p.drawImage(0, 0, left);
p.setCompositionMode(QPainter::CompositionMode_Difference);
p.drawImage(0, 0, right);
return delta;
}
public:
Comparator(QObject * parent = 0) : QIdentityProxyModel(parent) {}
QModelIndex index(int row, int column, const QModelIndex &parent) const Q_DECL_OVERRIDE {
if (column != columnCount(parent) - 1)
return QIdentityProxyModel::index(row, column, parent);
return createIndex(row, column, parent.internalPointer());
}
int columnCount(const QModelIndex &parent) const Q_DECL_OVERRIDE {
return sourceModel()->columnCount(mapToSource(parent)) + 1;
}
QVariant data(const QModelIndex &proxyIndex, int role) const Q_DECL_OVERRIDE {
if (isLastColumn(proxyIndex)) {
QVariant left = data(indexInColumn(0, proxyIndex), role);
QVariant right = data(indexInColumn(1, proxyIndex), role);
if (!left.canConvert<QImage>() || !right.canConvert<QImage>()) return QVariant();
return QVariant::fromValue(compare(left.value<QImage>(), right.value<QImage>()));
}
return QAbstractProxyModel::data(proxyIndex, role);
}
};
QImage sector(qreal diameter, qreal size, qreal start, qreal end, const QColor & color)
{
QImage image(size, size, QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
QPainter p(&image);
p.setRenderHint(QPainter::Antialiasing);
p.setPen(Qt::NoPen);
p.setBrush(color);
p.drawPie(QRectF(size-diameter, size-diameter, diameter, diameter),
qRound(start*16), qRound((end-start)*16));
return image;
}
QStandardItem * imageItem(const QImage & image) {
QScopedPointer<QStandardItem> item(new QStandardItem);
item->setEditable(false);
item->setSelectable(false);
item->setData(QVariant::fromValue(image), Qt::DecorationRole);
item->setSizeHint(image.size());
return item.take();
}
typedef QList<QStandardItem*> QStandardItemList;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStandardItemModel images;
Comparator comparator;
QTableView view;
comparator.setSourceModel(&images);
view.setModel(&comparator);
images.appendRow(QStandardItemList()
<< imageItem(sector(150, 160, 30, 100, Qt::red))
<< imageItem(sector(150, 160, 60, 120, Qt::blue)));
images.appendRow(QStandardItemList()
<< imageItem(sector(40, 45, 0, 180, Qt::darkCyan))
<< imageItem(sector(40, 45, 180, 360, Qt::cyan)));
view.resizeColumnsToContents();
view.resizeRowsToContents();
view.adjustSize();
view.show();
return a.exec();
}
#include "main.moc"
這篇關于Qt 模型-視圖-控制器的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!