#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include enum class Layout_Item_Type { Fixed, Expand }; enum class Layout_Item_Type2 { Fixed, Expand }; // 用于线性布局的元素 struct Layout_Info { Layout_Info() = default; Layout_Item_Type main_type{}; Layout_Item_Type2 second_type{}; Layout_Info(int key, Layout_Item_Type main_type, Layout_Item_Type2 second_type, int main_value, int second_value) : main_type(main_type), second_type(second_type) { this->key = key; if (main_type == Layout_Item_Type::Fixed) { len =main_value; } else { weight = main_value; } second_len = second_value; } int len{}; // 线性布局主要位置 int second_len{}; // 线性布局次要位置 int weight{}; // 主要位置权重布局 bool hide = false; int key{}; }; struct Layout { int prefix = 8, suffix = 8; int space = 8; int second_prefix = 8, second_suffix = 8; QVector infos; enum Type { Prefix_Space, Surfix_Space, Center_Space }; void set_margin(int margin){ prefix = margin; suffix = margin; second_prefix = margin; second_suffix = margin; } Type main_type = Prefix_Space; Type second_type = Prefix_Space; typedef QFlags Alignment; struct Pos { int start; int len; int second_start; int second_len; QRect h_rect() { return {start, second_start, len, second_len}; } QRect v_rect() { return {second_start, start, second_len, len}; } }; QMap cache; std::optional get(int key) { auto iter = cache.find(key); if (iter == cache.end()) { return std::nullopt; } return *iter; } void cacl(int len, int second_len) { QVector ret(infos.size()); int total_fixed_pixel_size = 0; int total_weight = 0; int show_size = 0; int n = infos.size(); for (int i = 0; i < n; ++i) { auto& info = infos[i]; if (info.hide) { continue; } if (info.main_type == Layout_Item_Type::Fixed) { total_fixed_pixel_size += info.len; } if (info.main_type == Layout_Item_Type::Expand) { total_weight += info.weight; } show_size++; } int show_width = total_fixed_pixel_size + (show_size - 1) * space; int remain = len - show_width - (prefix + suffix); int main_cur_pos = 0; if (main_type == Type::Prefix_Space) { main_cur_pos = prefix; } if (main_type == Type::Center_Space) { main_cur_pos = (len - show_width)/2; } if (main_type == Type::Surfix_Space) { main_cur_pos = len - show_width - suffix; } for (int i = 0; i < n; ++i) { auto& info = infos[i]; if (info.hide) continue; auto& pos = ret[i]; int cur_len = info.main_type == Layout_Item_Type::Fixed ? info.len : static_cast((double)remain * (double)info.weight/(double)total_weight); pos.start = main_cur_pos; pos.len = cur_len; int info_second_len{}; if (info.second_type == Layout_Item_Type2::Fixed) { info_second_len = info.second_len; } if (info.second_type == Layout_Item_Type2::Expand) { info_second_len = second_len - second_prefix - second_suffix; } if (second_type == Type::Prefix_Space) { pos.second_len = second_prefix; } if (second_type == Type::Center_Space) { pos.second_start = (second_len - info_second_len) /2; } if (second_type == Type::Surfix_Space) { pos.second_start = second_len - info_second_len- second_suffix; } pos.second_len = info_second_len; main_cur_pos += space + cur_len; } cache.clear(); for (int i = 0; i < n; ++i) { auto key = infos[i].key; cache[key] = ret[i]; } } }; enum class Event_Type { refresh, Nothing }; struct PaintAble { PaintAble() = default; virtual QSize sizeHint() const { return {24, 24}; } virtual ~PaintAble() = default; virtual void paint(QPainter* painter, QRect rect) = 0; // 鼠标操作 virtual Event_Type mouse_event(QEvent::Type t, QMouseEvent* e) { return Event_Type::Nothing; } virtual Event_Type resize_event(QResizeEvent* e) { return Event_Type::Nothing; } virtual Event_Type event(QEvent::Type t, QEvent* e) { if (t == QEvent::Resize) { return resize_event(dynamic_cast(e)); } if ( t == QEvent::MouseButtonPress || t == QEvent::MouseButtonRelease || t == QEvent::MouseMove || t == QEvent::MouseButtonDblClick ) { return mouse_event(t, dynamic_cast(e)); } return Event_Type::Nothing; } bool show = true; }; struct Base : QWidget { QVector paintAbles; void paintEvent(QPaintEvent* event) override { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); QRect rect = event->rect(); for (auto paintAble : paintAbles) { if (paintAble->show) { paintAble->paint(&painter, rect); } } painter.end(); } bool event(QEvent* e) override { auto t = e->type(); for(PaintAble* paintAble : paintAbles){ Event_Type r = paintAble->event(t, e); if (r == Event_Type::refresh) { update(); } } return QWidget::event(e); } };