走马灯是编程学习中常用到的示例代码。在这里把从中学到的知识进行一个汇总。如有不对之处,请各位指正。
一:思路
走马灯首先要考虑是在特定时间点将显示内容向一个方向移动,当显示最后有空位时,循环填写显示内容。
要有一个定时器;处理定时器的事件;显示的文本内容;当显示内容在控件中移动时,需要重绘控件。
当控件隐藏后,停止走马灯。
处理控件隐藏事件。
当控件显示时,开始走马灯。
处理控件显示事件。
二:头文件
#ifndef MAINWIDGET_H#define MAINWIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QTimerEvent;
class QShowEvent;
class QHideEvent;
class QPaintEvent;
QT_END_NAMESPACE
namespace Ui {
class MainWidget;
}
class MainWidget : public QWidget
{
Q_OBJECT
//属性
Q_PROPERTY(QString text READ text WRITE setText)
public:
explicit MainWidget(QWidget *parent = 0);
~MainWidget();
//接收文本
void setText(const QString &newText);
//返回保存文本
QString text() const;
//返回最合适的控件尺寸大小
virtual QSize sizeHint() const;
//重绘控件
virtual void paintEvent(QPaintEvent* e);
protected:
//处理定时器事件
virtual void timerEvent(QTimerEvent* e);
//处理控件显示事件
virtual void showEvent(QShowEvent* e);
//处理控件隐藏事件
virtual void hideEvent(QHideEvent* e);
private:
Ui::MainWidget *ui;
//保存文本变量
QString myText;
//保存显示文本偏移量
int offset;
//保存定时器id
int myTimerId;
};
#endif // MAINWIDGET_H
下面是对方法的具体实现及注释。
当控件显示时,每隔30minsec调用定时器。将定时器id赋给myTimerId。
void MainWidget::showEvent(QShowEvent *e){
myTimerId = startTimer(30);
}
当定时器被激活时,调用控件的定时器处理事件。
触发定时器事件时,首先判断触发此事件的定时器是否是走马灯定时器,如果是则对offset变量自加1,同时对控件面板上的内容左移1pixel。这样相当于控件面板左上角坐标为(0,0);但是面板最左边坐标为(-1,0)。当在paintEvent事件中重绘面板时,总是从最左端开始绘制内容,这样看就好像内容是不断向左边移动的。形成跑马灯效果。在其他情况下,调用父类的定时器事件进行处理。
void MainWidget::timerEvent(QTimerEvent *e){
if (e->timerId() == myTimerId) {
++offset;
/**
如果是则对offset变量自加1,同时对控件面板上的内容左移1pixel。这样相当于控件面板左上
角坐标为(0,0);但是面板最左边坐标为(-1,0)。当在paintEvent事件中重绘面板时,总是
从最左端开始绘制内容,这样看就好像内容是不断向左边移动的。形成跑马灯效果。
*/
if (offset >= fontMetrics().width(text())) {
offset = 0;
}
scroll(-1, 0);
} else {
//调用父类定时器事件处理。
QWidget::timerEvent(e);
}
}
当控件隐藏时,kill定时器。并将定时器id变量置0。
void MainWidget::hideEvent(QHideEvent *e){
Q_UNUSED(e);
killTimer(myTimerId);
myTimerId = 0;
}
当控件变化时(控件挪动,尺寸变化等),对控件面板进行重绘。
void MainWidget::paintEvent(QPaintEvent *e){
Q_UNUSED(e);
QPainter painter(this);
//set the text width and height.
const int textWidth(fontMetrics().width(text()));
const int textHeight(fontMetrics().height());
//no text show.
if (1 > textWidth) {
return;
}
//set the text begin in (-offset, 0).
int x(-offset);
while (width() > x) {
painter.drawText(x,
0,
textWidth,
textHeight,
Qt::AlignLeft | Qt::AlignVCenter,
text());
//
x += textWidth;
}
}