Qt-像丝一样滑

像丝一样滑

在这个例子中,我们介绍画一个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 
#include 

class QSlider;

class LCDRange:public QWidget
{
    Q_OBJECT
public:
    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 

class CannonField:public QWidget
{
    Q_OBJECT
public:
    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 
#include 
#include 
#include 
#include 
#include 
#include 

#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();
}


结果截图:

Qt-像丝一样滑_第1张图片

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

Qt-像丝一样滑_第2张图片

你可能感兴趣的:(Qt)