如何使用 QPainter 绘制指向箭头进度

How to draw a pointing arrow progress using QPainter

提问人:Jabu 提问时间:9/12/2023 更新时间:9/12/2023 访问量:81

问:

我试着画这样的东西:

enter image description here

到目前为止,我得到了:

![enter image description here

我没有弄清楚如何正确绘制“中间”小部件的左侧以适应“第一个”小部件,这同样适用于最后一个/中间。

当我调整箭头的大小时,我也在努力正确绘制箭头的“>”形状。

class ArrowWidget : public QWidget
{
    Q_OBJECT
public:
    QString text;
    enum Position { FIRST, MIDDLE, LAST };
    Position position;

    ArrowWidget(QWidget* parent, QString text, Position position)
        : QWidget(parent), text(text), position(position) 
    {
    }
    
    void paintEvent(QPaintEvent* event)
    {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        QPainterPath path;

        // Adjust to correctly draw the arrow point.
        int borderRadius = 12; 
        int arrowSize = 12;

        switch (position)
        {
            case FIRST:
            {
                path.moveTo(borderRadius, 0);
                path.lineTo(width() - arrowSize, 0);
                path.lineTo(width(), arrowSize);
                path.lineTo(width(), height() - arrowSize);
                path.lineTo(width() - arrowSize, height());
                path.lineTo(borderRadius, height());
                path.quadTo(0, height(), 0, height() - borderRadius);
                path.lineTo(0, borderRadius);
                path.quadTo(0, 0, borderRadius, 0);
                break;
            }
            case MIDDLE:
            {
                path.moveTo(borderRadius, 0);
                path.lineTo(width() - arrowSize, 0);
                path.lineTo(width(), arrowSize);
                path.lineTo(width(), height() - arrowSize);
                path.lineTo(width() - arrowSize, height());
                path.lineTo(borderRadius, height());
                path.quadTo(0, height(), 0, height() - borderRadius);
                path.lineTo(0, borderRadius);
                path.quadTo(0, 0, borderRadius, 0);
                break;
            }
            case LAST:
            {
                path.moveTo(width(), 0);
                path.lineTo(width() - borderRadius, 0);
                path.quadTo(width(), 0, width(), borderRadius);

                // Bottom right corner
                path.lineTo(width(), height() - borderRadius);
                path.quadTo(width(), height(), width() - borderRadius, height());

                path.lineTo(0, height());
                path.lineTo(0, 0);
                break;
            }
        }

        /*
        path.moveTo(arrowSize, 0);
        path.lineTo(0, arrowSize);
        path.lineTo(0, height() - arrowSize);
        path.lineTo(arrowSize, height());
        path.lineTo(width() - borderRadius, height());
        path.quadTo(width(), height(), width(), height() - borderRadius);
        path.lineTo(width(), borderRadius);
        path.quadTo(width(), 0, width() - borderRadius, 0);
        path.lineTo(arrowSize, 0);
        */
        painter.fillPath(path, QColor("#4699ea"));
        painter.setPen(QColor(255, 255, 255));
        painter.drawText(0, 0, width(), height(), Qt::AlignCenter, text);
        painter.end();
    }
};

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr) : QMainWindow(parent), ui(new Ui::MainWindowClass())
    {
        ui->setupUi(this);
        setStyleSheet("#centralWidget { background-color: rgba(80, 80, 80, 80); }");

        QWidget* widget = new QWidget(this);
        QHBoxLayout* layout = new QHBoxLayout(widget);
        layout->setContentsMargins(0, 0, 0, 0);
        layout->setSpacing(0);

        ArrowWidget* arrowWidget = new ArrowWidget(widget, "First", ArrowWidget::FIRST);    
        layout->addWidget(arrowWidget);
        arrowWidget = new ArrowWidget(widget, "Middle", ArrowWidget::MIDDLE);
        layout->addWidget(arrowWidget);
        arrowWidget = new ArrowWidget(widget, "Last", ArrowWidget::LAST);
        layout->addWidget(arrowWidget);

        setContentsMargins(32, 32, 32, 32);
        setCentralWidget(widget);
    }
private:
    Ui::MainWindowClass *ui;
};
C++ QT系列

评论

1赞 Jeremy Friesner 9/12/2023
如果您希望按比例调整大小,那么最好将值计算为小部件宽度和高度的百分比,而不是固定常量。(例如 或类似)ArrowWidgetarrowSizeborderRadiusconst int arrowSize = ((float)width()) * 0.05f;

答: 暂无答案