You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建带起止时间的PyQt5 QTimeEdit自定义组件?

实现支持起止时间的自定义QTimeEdit组件

可以通过继承QTimeEdit扩展出符合需求的组件,内部维护两个独立的时间对象,重写文本转换和交互逻辑,既保持原生QTimeEdit的操作体验,又支持起止时间的独立输入。

核心实现思路

  • 继承QTimeEdit,添加m_startTime和m_endTime两个私有变量分别存储起止时间
  • 重写textFromTime()和timeFromText()方法,实现自定义文本与时间的转换逻辑
  • 重写焦点和键盘事件,复刻原生QTimeEdit的光标选中、自动跳转行为

完整代码示例

#include <QTimeEdit>
#include <QTime>
#include <QKeyEvent>
#include <QFocusEvent>

class TimeRangeEdit : public QTimeEdit
{
    Q_OBJECT
public:
    explicit TimeRangeEdit(QWidget *parent = nullptr)
        : QTimeEdit(parent), m_startTime(QTime(0,0)), m_endTime(QTime(0,0))
    {
        setDisplayFormat("HH:mm - HH:mm");
        setReadOnly(false);
    }

    // 对外暴露起止时间的读写接口
    QTime startTime() const { return m_startTime; }
    QTime endTime() const { return m_endTime; }

    void setStartTime(const QTime &time) {
        m_startTime = time.isValid() ? time : m_startTime;
        updateDisplayText();
    }

    void setEndTime(const QTime &time) {
        m_endTime = time.isValid() ? time : m_endTime;
        updateDisplayText();
    }

protected:
    // 重写文本生成逻辑,拼接两个时间
    QString textFromTime(const QTime &) const override {
        return m_startTime.toString("HH:mm") + " - " + m_endTime.toString("HH:mm");
    }

    // 重写文本解析逻辑,拆分并校验两个时间
    QTime timeFromText(const QString &text) const override {
        QStringList parts = text.split(" - ");
        if (parts.size() == 2) {
            QTime start = QTime::fromString(parts[0], "HH:mm");
            QTime end = QTime::fromString(parts[1], "HH:mm");
            const_cast<TimeRangeEdit*>(this)->m_startTime = start.isValid() ? start : m_startTime;
            const_cast<TimeRangeEdit*>(this)->m_endTime = end.isValid() ? end : m_endTime;
        }
        return QTime(); // 原生time()方法不再使用,返回值无意义
    }

    // 焦点进入时自动选中第一个时间的小时位
    void focusInEvent(QFocusEvent *event) override {
        QTimeEdit::focusInEvent(event);
        setSelection(0, 2);
    }

    // 处理键盘输入的自动跳转与光标逻辑
    void keyPressEvent(QKeyEvent *event) override {
        int cursorPos = cursorPosition();
        bool isDigit = event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9;

        if (isDigit) {
            QTimeEdit::keyPressEvent(event);
            // 输入完成后自动跳转并选中对应区域
            if (cursorPos == 1) {
                setCursorPosition(3);
                setSelection(3, 2);
            } else if (cursorPos == 4) {
                setCursorPosition(7);
                setSelection(7, 2);
            } else if (cursorPos == 8) {
                setCursorPosition(10);
                setSelection(10, 2);
            }
            return;
        }

        // 左右箭头跳过分隔符区域
        if (event->key() == Qt::Key_Right) {
            if (cursorPos == 2 || cursorPos == 6) {
                setCursorPosition(cursorPos + 1);
            }
        } else if (event->key() == Qt::Key_Left) {
            if (cursorPos == 3 || cursorPos == 7) {
                setCursorPosition(cursorPos - 1);
            }
        }

        QTimeEdit::keyPressEvent(event);
    }

private:
    void updateDisplayText() {
        setText(textFromTime(QTime()));
    }

    QTime m_startTime;
    QTime m_endTime;
};

适配表格嵌入

该组件完全继承QTimeEdit的接口,可直接替换表格中的原生QTimeEdit:

  • 在QTableWidget中使用setCellWidget(row, col, new TimeRangeEdit(this))
  • 在QTableView的自定义委托中,将编辑器类型指定为TimeRangeEdit

关键特性说明

  • 时间有效性校验:解析输入文本时会校验时间格式,非法时间(如99:99)不会覆盖原有有效值
  • 原生交互体验:焦点进入选中第一个小时位,输入数字自动跳转选中对应部分,左右箭头跳过分隔符
  • 独立时间控制:起止时间完全独立,不会出现同步变更的问题

内容的提问来源于stack exchange,提问作者Zenn De Craene

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 19:30:10