Qt-像丝一样滑

来源:互联网 发布:南京大学作家班 知乎 编辑:程序博客网 时间:2024/04/28 12:28

像丝一样滑

在这个例子中,我们介绍画一个pixmap来除去闪烁。我们也会加入一个力量控制。

lcdrange.h包含LCDRange类定义。
lcdrange.cpp包含LCDRange类实现。
cannon.h包含CannonField类定义。
cannon.cpp包含CannonField类实现。
main.cpp包含MyWidget和main。

lcdrange.h

#ifndef LCDRANGE_H#define LCDRANGE_H#include <QVBoxLayout>#include <QWidget>class QSlider;class LCDRange:public QWidget{    Q_OBJECTpublic:    LCDRange(QWidget *parent = 0);    int showValue() const;//查询滑块的值public slots:    void setValue(int);//设置滑块的值    void setRange(int minVal, int maxVal);//设置滑块的范围signals:    void valueChanged(int);private:    QSlider *slider;};#endif // LCDRANGE_H

lcdrange.cpp

#include "lcdrange.h"#include <QSlider>#include <QLCDNumber>LCDRange::LCDRange(QWidget *parent):QWidget(parent){    QLCDNumber *lcd = new QLCDNumber(2);    slider = new QSlider(Qt::Horizontal);    slider->setRange(0,99);    slider->setValue(0);    connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));    connect(slider, SIGNAL(valueChanged(int)), SIGNAL(valueChanged(int)));    setFocusProxy(slider);//设置这个窗口部件的焦点为slider    QVBoxLayout *part = new QVBoxLayout;    part->addWidget(lcd);    part->addWidget(slider);    setLayout(part);}int LCDRange::showValue() const{    return slider->value();}void LCDRange::setValue(int value){    slider->setValue(value);}void LCDRange::setRange(int minVal, int maxVal){    if(minVal<0||maxVal>99||minVal>maxVal)    {        qWarning("LCDRange::setRange(%d,%d)\n"                 "\tRange must be 0..99\n"                 "\tand minVal must not be greater than maxVal", minVal, maxVal);        return;    }    slider->setRange(minVal, maxVal);}

cannon.h

#ifndef CANNON_H#define CANNON_H#include <QWidget>class CannonField:public QWidget{    Q_OBJECTpublic:    CannonField(QWidget *parent = 0);    QSizePolicy sizePolicy() const;    int showAngle() const{return angle;} //显示角度值    int showForce() const{return f;}  //显示力量值public slots:    void setAngle(int degrees); //接受信号:设置角度值    void setForce(int newton);  //接受信号:设置力量值signals:    void angleChanged(int); //发送信号:角度值变化    void forceChanged(int); //发送信号:力量值变化protected:    void paintEvent(QPaintEvent *); //窗口刷新/重绘private:    QRect cannonRect() const; //封装加农炮的矩形    int angle; //角度值    int f; //力量值};#endif // CANNON_H

cannon.cpp

#include "cannon.h"#include "qpaintevent"#include <QPainter>#include <QPixmap>CannonField::CannonField(QWidget *parent):QWidget(parent){    angle = 45;    f = 0;    setAutoFillBackground(true);    setPalette(QPalette(QColor(250,250,200)));}void CannonField::setAngle(int degrees){    if(degrees<5)        degrees = 5;    if(degrees>70)        degrees = 70;    if(angle == degrees)        return; //如果角度与初始angle相同,返回    angle = degrees;    repaint(cannonRect()); //仅重绘加农炮矩形部分    emit angleChanged(angle); //发送angle变化消息}void CannonField::setForce( int newton ){    if(newton < 0)        newton = 0;    if(f == newton)        return;    f = newton;    emit forceChanged( f );}void CannonField::paintEvent(QPaintEvent *e){    if(!e->rect().intersects(cannonRect())) //判断需要更新的矩形区域和cannonRece()是否相交        return;    QRect cr = cannonRect(); //矩形更新    QPixmap pix(cr.size()); //位图双缓冲    pix.fill(this, cr.topLeft()); //fill(widget, ofs:在widget中的偏移):fill the pixmap with the widget's background color or pixmap.    QPainter p(&pix); //&pix,在pixmap上画    p.setBrush(Qt::darkGray);    p.setPen(Qt::NoPen);    p.translate(0, pix.height()-1); //将原点(0,0)变化为(0, pix.height()-1)    p.drawPie(QRect(-35, -35, 70, 70), 0, 90*16); //绘制由(x,y,w,h)确定的饼图,开始角度为0,弧长为90*16(四分之一圆),加农炮炮身    p.rotate(-angle);    p.drawRect(QRect(33, -4, 15, 8)); //加农炮炮筒    p.end();    p.begin(this);//在屏幕上画    p.drawPixmap(cr.topLeft(), pix); //把pixmap的一部分绘制到屏幕上。像素映射pix,原点就放在cr.topLeft()处。}QRect CannonField::cannonRect() const{//在窗口部件中封装加农炮的矩形,以加农炮圆心为圆心,以(50,50)为(w,h)的矩形    QRect r(0, 0, 50, 50); //(left, top, width, height)    r.moveBottomLeft(rect().bottomLeft()); //设置r的左下角为窗口部件自己的左下角    return r;}

main.cpp

#include "mainwindow.h"#include <QApplication>#include <QPushButton>#include <QFont>#include <QSlider>#include <QLCDNumber>#include <QVBoxLayout>#include <QGridLayout>#include "lcdrange.h"#include "cannon.h"class MyWidget:public QWidget{public:    MyWidget(QWidget *parent = 0);};MyWidget::MyWidget(QWidget *parent):QWidget(parent){    QPushButton *quit = new QPushButton("&Quit");    quit->setFont(QFont("Times",18,QFont::Bold));    connect(quit,SIGNAL(clicked()),qApp,SLOT(quit()));    LCDRange *lcdRange = new LCDRange;    lcdRange->setRange(5,70);    CannonField *cannonField = new CannonField;    connect(lcdRange, SIGNAL(valueChanged(int)), cannonField, SLOT(setAngle(int)));    connect(cannonField, SIGNAL(angleChanged(int)), lcdRange, SLOT(setValue(int)));    LCDRange *lcdForce = new LCDRange;    lcdForce->setRange(10, 50);    connect(lcdForce, SIGNAL(valueChanged(int)), cannonField, SLOT(setForce(int)));    connect(cannonField, SIGNAL(forceChanged(int)), lcdForce, SLOT(setValue(int)));    QGridLayout *grid = new QGridLayout;    grid->addWidget(quit, 0, 0);    grid->addWidget(cannonField, 1, 1);    grid->setColumnStretch(1, 10);    QVBoxLayout *leftBox = new QVBoxLayout;    grid->addLayout(leftBox, 1, 0);    leftBox->addWidget(lcdRange);    leftBox->addWidget(lcdForce);    lcdRange->setValue(60);    lcdForce->setValue(25);    lcdRange->setFocus(); //对lcdRange窗口设置键盘焦点    QVBoxLayout *layout = new QVBoxLayout;    layout->addLayout(grid);    setLayout(layout);}int main(int argc, char *argv[]){    QApplication a(argc, argv);    MyWidget w;    w.setGeometry( 100, 100, 500, 355 );    w.show();    return a.exec();}

结果截图:

这里写图片描述


存在问题:
1.为什么有黑色矩形?
2.为什么调节角度时之前的印子没有清除?
与代码 repaint(cannonRect()); 有关吗?教程给的是 repaint(cannonRect(), false);
但是运行有问题:
error: no matching function for call to ‘CannonField::repaint(QRect, bool)’
repaint(cannonRect(),false);

这里写图片描述

原创粉丝点击