如何创建带起止时间的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
相关产品推荐
相关产品推荐

