This commit is contained in:
codeboss 2025-10-12 20:21:45 +08:00
parent 6376ae1ed6
commit 03512aae5b
4 changed files with 82 additions and 39 deletions

View File

@ -8,6 +8,26 @@
#include <QMouseEvent> #include <QMouseEvent>
class OptionGroup {
private:
PresentOption _bind_opt;
std::shared_ptr<OptionGroup> _next_group;
public:
OptionGroup(const PresentOption& opt, std::shared_ptr<OptionGroup> next = nullptr)
:_bind_opt(opt), _next_group(next) {
}
std::shared_ptr<OptionGroup> nextGet() const {
return _next_group;
}
const PresentOption& optionGet() const {
return _bind_opt;
}
};
MapPresent::MapPresent(QWidget* parent /*= nullptr*/) MapPresent::MapPresent(QWidget* parent /*= nullptr*/)
:QWidget(parent) :QWidget(parent)
{ {
@ -18,17 +38,23 @@ MapPresent::MapPresent(QWidget* parent /*= nullptr*/)
_present_delegate[delegate->unitType()] = delegate; _present_delegate[delegate->unitType()] = delegate;
connect(this, &MapPresent::mouseOut, delegate, &BasicUnitDelegate::hotClear); connect(this, &MapPresent::mouseOut, delegate, &BasicUnitDelegate::hotClear);
connect(this, &MapPresent::mouseHover, delegate, &BasicUnitDelegate::hotIndexSet); connect(this, &MapPresent::mouseHover, delegate, &BasicUnitDelegate::hotIndexSet);
connect(delegate, &BasicUnitDelegate::updateRequest, [=](){ this->update(); }); connect(delegate, &BasicUnitDelegate::updateRequest, [=]() { this->update(); });
this->setMouseTracking(true); this->setMouseTracking(true);
} }
PresentIndex MapPresent::indexGet(const QPointF& pos) const PresentIndex MapPresent::indexGet(const QPointF& pos) const
{ {
decltype(_visible_units) templist; QList<PresentOption> templist;
for (auto& unit : _visible_units) { for (auto unit_g : _visible_units) {
if (unit.outline.contains(pos)) { while (unit_g) {
templist << unit; auto unit = unit_g->optionGet();
if (unit.outline.contains(pos)) {
templist << unit;
}
unit_g = unit_g->nextGet();
} }
} }
@ -69,31 +95,33 @@ QRectF MapPresent::outlineGet(const PresentIndex& idx) const
return QRectF(target_center.toPointF(), QSizeF(ap_len * 2, ap_len * 2)); return QRectF(target_center.toPointF(), QSizeF(ap_len * 2, ap_len * 2));
} }
#include <QElapsedTimer>
#include <QtDebug>
void MapPresent::paintEvent(QPaintEvent* ev) void MapPresent::paintEvent(QPaintEvent* ev)
{ {
QWidget::paintEvent(ev); QWidget::paintEvent(ev);
UnitPresentDelegate &t = *_present_delegate[0]; UnitPresentDelegate& t = *_present_delegate[0];
QPainter p(this); QPainter p(this);
for (auto opt : _visible_units) { for (auto opt_g : _visible_units) {
p.save(); while (opt_g) {
p.save();
auto rect = opt.outline; auto opt = opt_g->optionGet();
p.translate(rect.topLeft()); auto rect = opt.outline;
rect.moveTo(0, 0); p.translate(rect.topLeft());
rect.moveTo(0, 0);
auto end_pts = BasicUnitDelegate::endPointsGet(rect); auto clip_path = BasicUnitDelegate::clipPathGet(rect);
QPainterPath clicp_path; p.setClipPath(clip_path);
clicp_path.moveTo(end_pts.first());
for (auto idx = 0; idx < end_pts.size(); ++idx) { opt.outline = rect;
clicp_path.lineTo(end_pts[idx]); t.paint(&p, opt);
p.restore();
opt_g = opt_g->nextGet();
} }
p.setClipPath(clicp_path);
opt.outline = rect;
t.paint(&p, opt);
p.restore();
} }
} }
@ -140,20 +168,27 @@ void MapPresent::visibleUnitsTidy() {
_visible_units.clear(); _visible_units.clear();
QRectF curr_outline = this->rect(); QRectF curr_outline = this->rect();
_visible_units << AssumeOpt(_center_index, outlineGet(_center_index)); _visible_units << std::make_shared<OptionGroup>(
AssumeOpt(_center_index, outlineGet(_center_index))
);
int visible_count = 1, deduce_x = 1; int visible_count = 1, deduce_x = 1;
while (visible_count) { while (visible_count) {
visible_count = 0; visible_count = 0;
std::shared_ptr<OptionGroup> prev_g = nullptr;
auto siblings = siblingsGet(_center_index, deduce_x++); auto siblings = siblingsGet(_center_index, deduce_x++);
for (auto unit : siblings) { for (auto unit : siblings) {
auto visible_rect = outlineGet(unit); auto visible_rect = outlineGet(unit);
if (curr_outline.intersects(visible_rect)) { if (curr_outline.intersects(visible_rect)) {
_visible_units << AssumeOpt(unit, visible_rect); prev_g = std::make_shared<OptionGroup>(AssumeOpt(unit, visible_rect), prev_g);
visible_count++; visible_count++;
} }
} }
if (prev_g) {
_visible_units << prev_g;
}
} }
// TODO ¹¹½¨¿ìËÙ²âÊÔ×éÖ¯½á¹¹ // TODO ¹¹½¨¿ìËÙ²âÊÔ×éÖ¯½á¹¹
@ -219,3 +254,10 @@ bool PresentIndex::operator==(const PresentIndex& other) const
UnitPresentDelegate::UnitPresentDelegate(QObject* parent /*= nullptr*/) UnitPresentDelegate::UnitPresentDelegate(QObject* parent /*= nullptr*/)
:QObject(parent) { :QObject(parent) {
} }
PresentOption& PresentOption::operator=(const PresentOption& other)
{
index = other.index;
outline = other.outline;
return *this;
}

View File

@ -2,6 +2,8 @@
#include "mappresent_global.h" #include "mappresent_global.h"
#include <QWidget> #include <QWidget>
#include <memory>
/// <summary> /// <summary>
/// 餅秶坰竘 /// 餅秶坰竘
@ -36,8 +38,7 @@ struct PresentOption {
/// </summary> /// </summary>
QRectF outline; QRectF outline;
bool isMouseOver = false; PresentOption& operator=(const PresentOption& other);
bool isSelected = false;
}; };
/// <summary> /// <summary>
@ -68,6 +69,7 @@ signals:
void updateRequest(const PresentIndex &idx); void updateRequest(const PresentIndex &idx);
}; };
class OptionGroup;
/// <summary> /// <summary>
/// 價插華芞餅秶 /// 價插華芞餅秶
/// </summary> /// </summary>
@ -89,7 +91,7 @@ private:
PresentIndex _center_index; PresentIndex _center_index;
// =================================== // ===================================
QList<PresentOption> _visible_units; QList<std::shared_ptr<OptionGroup>> _visible_units;
void visibleUnitsTidy(); void visibleUnitsTidy();
QList<PresentIndex> siblingsGet(const PresentIndex& center, uint16_t dist = 1) const; QList<PresentIndex> siblingsGet(const PresentIndex& center, uint16_t dist = 1) const;

View File

@ -22,22 +22,16 @@ void BasicUnitDelegate::paint(QPainter* p, const PresentOption& option)
QRadialGradient brush(center, alen); QRadialGradient brush(center, alen);
brush.setColorAt(0, Qt::gray); brush.setColorAt(0, Qt::gray);
brush.setColorAt(1, Qt::white); brush.setColorAt(1, Qt::white);
p->fillRect(rect, brush); p->setBrush(brush);
QList<QPointF> points = endPointsGet(rect); auto pathx = clipPathGet(rect);
QVector<QLineF> lines;
for (auto idx = 0; idx < 6; ++idx) {
lines << QLineF(points[idx], points[idx + 1]);
}
if (_hot_index == option.index) { if (_hot_index == option.index) {
auto pen = p->pen(); auto pen = p->pen();
pen.setColor(Qt::red); pen.setColor(Qt::red);
pen.setWidth(10); pen.setWidth(10);
p->setPen(pen); p->setPen(pen);
} }
p->drawLines(lines); p->drawPath(pathx);
auto ft = p->font(); auto ft = p->font();
ft.setPixelSize(alen * 0.3); ft.setPixelSize(alen * 0.3);
@ -49,7 +43,7 @@ void BasicUnitDelegate::paint(QPainter* p, const PresentOption& option)
p->drawText(text_rect, Qt::AlignCenter, text_str); p->drawText(text_rect, Qt::AlignCenter, text_str);
} }
QList<QPointF> BasicUnitDelegate::endPointsGet(const QRectF& rect) QPainterPath BasicUnitDelegate::clipPathGet(const QRectF& rect)
{ {
auto center = rect.center(); auto center = rect.center();
auto alen = rect.width() / 2; auto alen = rect.width() / 2;
@ -64,7 +58,12 @@ QList<QPointF> BasicUnitDelegate::endPointsGet(const QRectF& rect)
points << QPointF(center.x() - xspan, center.y() + alen / 2); points << QPointF(center.x() - xspan, center.y() + alen / 2);
points << QPointF(center.x() - xspan, center.y() - alen / 2); points << QPointF(center.x() - xspan, center.y() - alen / 2);
return points; QPainterPath clicp_path;
clicp_path.moveTo(points.first());
for (auto idx = 0; idx < points.size(); ++idx) {
clicp_path.lineTo(points[idx]);
}
return clicp_path;
} }
void BasicUnitDelegate::hotClear() void BasicUnitDelegate::hotClear()

View File

@ -10,7 +10,7 @@ public:
int unitType() const override; int unitType() const override;
void paint(QPainter* p, const PresentOption& option) override; void paint(QPainter* p, const PresentOption& option) override;
static QList<QPointF> endPointsGet(const QRectF& rect); static QPainterPath clipPathGet(const QRectF& rect);
void hotClear(); void hotClear();
void hotIndexSet(const PresentIndex &idx); void hotIndexSet(const PresentIndex &idx);