From d9620ce43db5adcc8d6246e7639a53a2608b88a5 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 3 Sep 2026 11:55:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(vqt6):=20QCheckBox=20=E6=94=B9=E8=87=AA?= =?UTF-8?q?=E7=BB=98=E5=AD=90=E7=B1=BB(=E7=9F=A2=E9=87=8F=E6=A1=86+?= =?UTF-8?q?=E5=AF=B9=E5=8B=BE,=E6=8C=89QPalette=E9=85=8D=E8=89=B2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vqt6/_bridge_widgets.cpp | 65 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/vqt6/_bridge_widgets.cpp b/vqt6/_bridge_widgets.cpp index 78a1d10..6a000a7 100644 --- a/vqt6/_bridge_widgets.cpp +++ b/vqt6/_bridge_widgets.cpp @@ -16,6 +16,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -847,18 +850,74 @@ extern "C" VQT6_API int vqt6_qplaintextedit_line_count(void* pte) { // ============================================================ // QCheckBox / QRadioButton // ============================================================ + +// 自绘 QCheckBox:边框+矢量对勾都按 QPalette 绘制, +// 避免浅色/深色主题切换时原生对勾或边框丢失 +class vqt6_CheckBox : public QCheckBox { +public: + vqt6_CheckBox(QWidget* parent = nullptr) : QCheckBox(parent) {} + vqt6_CheckBox(const QString& text, QWidget* parent = nullptr) : QCheckBox(text, parent) {} + +protected: + void paintEvent(QPaintEvent*) override { + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing, true); + const QPalette& pal = palette(); + QStyleOptionButton opt; + initStyleOption(&opt); + QRect r = style()->subElementRect(QStyle::SE_CheckBoxIndicator, &opt, this); + if (r.isEmpty() || r.isNull()) { + r = QRect(0, 0, 16, 16); + r.moveCenter(QPoint(rect().left() + 12, rect().center().y())); + } + QRectF box(r.left() + 1.0, r.top() + 1.0, r.width() - 2.0, r.height() - 2.0); + if (box.width() < 10.0 || box.height() < 10.0) { + box = QRectF(0, 0, 16, 16); + box.moveCenter(QPointF(r.center().x(), r.center().y())); + } + QPainterPath path; + path.addRoundedRect(box, 3.0, 3.0); + const bool on = isChecked(); + const bool en = isEnabled(); + QColor border = en ? pal.text().color() : pal.placeholderText().color(); + if (on) { + p.fillPath(path, en ? pal.highlight() : pal.button()); + border = en ? pal.highlight().color() : pal.buttonText().color(); + } else { + p.fillPath(path, en ? pal.base() : pal.window()); + } + QPen bpen(border, 1.4); + p.setPen(bpen); + p.drawPath(path); + if (on && en) { + QPen cpen(pal.highlightedText(), 2.2); + cpen.setCapStyle(Qt::RoundCap); + p.setPen(cpen); + const qreal x0 = box.left(), y0 = box.top(), w = box.width(), h = box.height(); + p.drawLine(QPointF(x0 + w * 0.24, y0 + h * 0.54), QPointF(x0 + w * 0.43, y0 + h * 0.73)); + p.drawLine(QPointF(x0 + w * 0.43, y0 + h * 0.73), QPointF(x0 + w * 0.78, y0 + h * 0.28)); + } + // 文本 + QRect lr = style()->subElementRect(QStyle::SE_CheckBoxContents, &opt, this); + if (!lr.isEmpty() && !lr.isNull()) { + p.setPen(QPen(en ? pal.text() : pal.placeholderText(), 1.0)); + p.drawText(lr, Qt::AlignLeft | Qt::AlignVCenter, text()); + } + } +}; + extern "C" VQT6_API void* vqt6_qcheckbox_create(void) { - return new QCheckBox(); + return new vqt6_CheckBox(); } extern "C" VQT6_API void* vqt6_qcheckbox_create_with_text(void* text) { if (text == nullptr) return nullptr; - return new QCheckBox(*static_cast(text)); + return new vqt6_CheckBox(*static_cast(text)); } extern "C" VQT6_API void* vqt6_qcheckbox_create_with_text_parent(void* text, void* parent) { if (text == nullptr || parent == nullptr) return nullptr; - return new QCheckBox(*static_cast(text), static_cast(parent)); + return new vqt6_CheckBox(*static_cast(text), static_cast(parent)); } extern "C" VQT6_API void vqt6_qcheckbox_set_checked(void* cb, int checked) {