feat(vqt6): QCheckBox 改自绘子类(矢量框+对勾,按QPalette配色)

This commit is contained in:
TermiNexus committed 2026-09-03 11:55:15 +08:00
1 parent ceb601a2d3
commit d9620ce43d
1 file changed
+62 -3
+62 -3
View File
@@ -16,6 +16,9 @@
#include <QPlainTextEdit>
#include <QCheckBox>
#include <QRadioButton>
#include <QPainter>
#include <QPainterPath>
#include <QStyleOptionButton>
#include <QComboBox>
#include <QListWidget>
#include <QProgressBar>
@@ -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<QString*>(text));
return new vqt6_CheckBox(*static_cast<QString*>(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<QString*>(text), static_cast<QWidget*>(parent));
return new vqt6_CheckBox(*static_cast<QString*>(text), static_cast<QWidget*>(parent));
}
extern "C" VQT6_API void vqt6_qcheckbox_set_checked(void* cb, int checked) {