Created
June 12, 2024 04:56
-
-
Save khurd21/f783bf70926846a3c79005bc4ff52f9a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <QApplication> | |
#include <QMainWindow> | |
#include <QLabel> | |
#include <QHBoxLayout> | |
#include <QPushButton> | |
#include <QScrollArea> | |
#include <QAbstractListModel> | |
#include <QAbstractItemDelegate> | |
#include <QListView> | |
#include <QPainter> | |
struct Item { | |
QString title; | |
QString description; | |
}; | |
Q_DECLARE_METATYPE(Item) | |
class WidgetModel : public QObject { | |
Q_OBJECT | |
public: | |
explicit WidgetModel(QObject* parent = nullptr) : QObject(parent) {} | |
void addItems(const int count) { | |
for (int i = 0; i < count; ++i) { | |
m_items.append({ | |
QString("Title %1").arg(m_items.size() + 1), | |
QString("Description %1").arg(m_items.size() + 1)}); | |
} | |
emit itemsChanged(m_items); | |
} | |
signals: | |
void itemsChanged(const QList<Item>& items); | |
private: | |
QList<Item> m_items; | |
}; | |
class ItemWidget : public QWidget { | |
public: | |
explicit ItemWidget(const Item& item, QWidget* parent = nullptr) : QWidget(parent) { | |
const auto layout = new QHBoxLayout(this); | |
layout->addWidget(new QLabel(item.title, this)); | |
layout->addWidget(new QLabel(item.description, this)); | |
} | |
}; | |
class PaintModel : public QAbstractListModel { | |
Q_OBJECT | |
public: | |
explicit PaintModel(QObject* parent = nullptr) : QAbstractListModel(parent) { | |
qRegisterMetaType<Item>("Item"); | |
} | |
int rowCount(const QModelIndex& parent = QModelIndex()) const override { | |
Q_UNUSED(parent); | |
return m_items.size(); | |
} | |
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override { | |
if (!index.isValid() || index.row() >= m_items.size()) | |
return {}; | |
const auto& item = m_items.at(index.row()); | |
if (role == Qt::DisplayRole) { | |
return QVariant::fromValue(item); | |
} | |
return {}; | |
} | |
void addItems(int count) { | |
beginInsertRows(QModelIndex(), m_items.size(), m_items.size() + count - 1); | |
for (int i = 0; i < count; ++i) { | |
m_items.append({ | |
QString("Title %1").arg(m_items.size() + 1), | |
QString("Description %1").arg(m_items.size() + 1)}); | |
} | |
endInsertRows(); | |
} | |
private: | |
QList<Item> m_items; | |
}; | |
class PaintDelegate : public QAbstractItemDelegate { | |
Q_OBJECT | |
public: | |
explicit PaintDelegate(QObject* parent = nullptr) : QAbstractItemDelegate(parent) {} | |
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override { | |
if (!index.isValid()) | |
return; | |
// Cast the QVariant back to an Item struct | |
Item item = index.data(Qt::DisplayRole).value<Item>(); | |
painter->save(); | |
// Draw background | |
if (option.state & QStyle::State_Selected) { | |
painter->fillRect(option.rect, option.palette.highlight()); | |
} else { | |
painter->fillRect(option.rect, option.palette.base()); | |
} | |
// Draw text | |
painter->setPen(option.palette.color(QPalette::Text)); | |
painter->drawText(option.rect.adjusted(10, 5, -10, -25), Qt::AlignLeft | Qt::AlignVCenter, item.title); | |
painter->drawText(option.rect.adjusted(10, 30, -10, -10), Qt::AlignLeft | Qt::AlignVCenter, item.description); | |
painter->restore(); | |
} | |
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override { | |
Q_UNUSED(option); | |
Q_UNUSED(index); | |
return QSize(300, 70); // Adjust the size of each item as needed | |
} | |
}; | |
class MyWindow : public QMainWindow { | |
Q_OBJECT | |
public: | |
MyWindow(QWidget *parent = nullptr) | |
: QMainWindow(parent) { | |
setWindowTitle("My Qt Application"); | |
resize(800, 600); | |
} | |
~MyWindow() = default; | |
}; | |
class WidgetView : public QWidget { | |
Q_OBJECT | |
public: | |
explicit WidgetView(WidgetModel* model, QWidget* parent = nullptr) | |
: QWidget(parent), m_model(model) { | |
m_layout = new QVBoxLayout(this); | |
setLayout(m_layout); | |
// Connect the model's signal to the view's update method | |
connect(model, &WidgetModel::itemsChanged, this, &WidgetView::updateView); | |
} | |
public slots: | |
void updateView(const QList<Item>& items) { | |
// Clear the current widgets | |
clearLayout(m_layout); | |
// Add new widgets based on the model's items | |
for (const auto& item : items) { | |
m_layout->addWidget(new ItemWidget(item)); | |
} | |
} | |
private: | |
void clearLayout(QLayout* layout) { | |
while (QLayoutItem* item = layout->takeAt(0)) { | |
delete item->widget(); | |
delete item; | |
} | |
} | |
QVBoxLayout* m_layout{}; | |
WidgetModel* m_model{}; | |
}; | |
int main(int argc, char* argv[]) { | |
QApplication app(argc, argv); | |
// Models | |
WidgetModel widgetModel; | |
PaintModel paintModel; | |
// Main widget and layout | |
QWidget mainWidget; | |
mainWidget.setWindowTitle("Qt Example: Widget vs Paint Delegate"); | |
mainWidget.resize(1000, 600); // Increased window size | |
QHBoxLayout* mainLayout = new QHBoxLayout(&mainWidget); | |
// Left: Widget-based view | |
QVBoxLayout* widgetLayout = new QVBoxLayout; | |
QPushButton* addWidgetButton = new QPushButton("Add Widget Items"); | |
QObject::connect(addWidgetButton, &QPushButton::clicked, [&widgetModel]() { | |
widgetModel.addItems(5000); | |
}); | |
QScrollArea* widgetScrollArea = new QScrollArea; | |
WidgetView* widgetView = new WidgetView(&widgetModel); | |
widgetScrollArea->setWidget(widgetView); | |
widgetScrollArea->setWidgetResizable(true); | |
widgetLayout->addWidget(addWidgetButton); | |
widgetLayout->addWidget(widgetScrollArea); | |
QWidget* widgetContainer = new QWidget; | |
widgetContainer->setLayout(widgetLayout); | |
// Right: Paint-based view | |
QVBoxLayout* paintLayout = new QVBoxLayout; | |
QPushButton* addPaintButton = new QPushButton("Add Paint Items"); | |
QObject::connect(addPaintButton, &QPushButton::clicked, [&paintModel]() { | |
paintModel.addItems(100'000); | |
}); | |
QListView* paintListView = new QListView; | |
paintListView->setModel(&paintModel); | |
paintListView->setItemDelegate(new PaintDelegate(paintListView)); | |
paintLayout->addWidget(addPaintButton); | |
paintLayout->addWidget(paintListView); | |
QWidget* paintContainer = new QWidget; | |
paintContainer->setLayout(paintLayout); | |
mainLayout->addWidget(widgetContainer); | |
mainLayout->addWidget(paintContainer); | |
mainWidget.show(); | |
return app.exec(); | |
} | |
#include "main.moc" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment