• QT学习8:准备战斗


     cannon.h:
    #ifndef CANNONFIELD_H_
    #define CANNONFIELD_H_
    
    #include <QWidget.h>
    
    class CannonField : public QWidget
    {
    	Q_OBJECT
    public:
    	CannonField(QWidget *parent=NULL, const char *name=NULL);
    
    	int angle() const {return ang;}
    	QSizePolicy sizePolicy() const;
    
    	public slots:
    		void setAngle(int degrees);
    
    signals:
    		void angleChanged(int);
    
    protected:
    	//-------------------------------------
    	// 虚函数,在update() repaint()时,界面从隐藏到显示,尺寸改变,内容改变等都会被自动
    	// 调用,它本身已自动开启双缓冲,所以不会引起闪烁
    	//-------------------------------------
    	void paintEvent(QPaintEvent *);
    
    private:
    	int ang;
    };
    
    #endif

    cannon.cpp:

    #include "CannonField.h"
    #include <QPainter.h>
    
    CannonField::CannonField(QWidget *parent, const char *name)
    :QWidget(parent, name)
    {
    	ang = 45;
    	//所有Qt窗口部件都拥有一个调色板并使用它绘制自己.
    	setPalette(QPalette(QColor(250, 0, 0)));
    }
    
    void CannonField::setAngle(int degrees)
    {
    	if (degrees<5)
    	{
    		degrees = 5;
    	}
    
    	if (degrees>70)
    	{
    		degrees = 70;
    	}
    
    	if (ang == degrees)
    	{
    		return;
    	}
    
    	ang = degrees;
    
        //--------------------------------------
    	// 被调用后,立即执行重绘,因此repaint是最快的
    	// 但不能放在paintEvent中调用,不然会死循环.
        // update()跟repaint()比较,update则更加有优越性。
    	// update()调用之后并不是立即重绘,而是将重绘事件放入主消息循环中,
    	// 由main的event loop来统一调度的(其实也是比较快的)。
    	// update在调用paintEvent之前,还做了很多优化,如果update被调用了很多次,
    	// 最后这些update会合并到一个大的重绘事件加入到消息队列,
    	// 最后只有这个大的update被执行一次。同时也避免了repaint()中所提到的死循环
    	// --  hgy notes.
    	//--------------------------------------
    	repaint();
    
    	emit angleChanged(ang);
    }
    
    void CannonField::paintEvent(QPaintEvent *)
    {
    	// -------------------------------------
    	// QPaintEvent包含一个必须被刷新的窗口部件的区域
        // QPainter默认只能在paintEvent里面调用
    	// -------------------------------------
    	QString s = "Angle = " + QString::number(ang);
    	QPainter p(this);
    	p.drawText(200, 200, s);
    
    }
    
    QSizePolicy CannonField::sizePolicy() const
    {
    	return QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    }


    LCDRange.h :

    #ifndef LCDRANGE_H_
    #define LCDRANGE_H_
    
    #include <QWidget.h>
    
    class QSlider;
    
    class LCDRange:public QWidget
    {
    	Q_OBJECT
    public:
    	LCDRange(QWidget* parent=NULL, const char *name=NULL);
    	int value() 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.h>
    #include <QLCDNumber.h>
    #include <QVBoxLayout>
    
    LCDRange::LCDRange(QWidget* parent, const char *name)
    :QWidget(parent, name)
    {
    	QLCDNumber *lcd = new QLCDNumber(2, this);
    	slider = new QSlider(Qt::Orientation::Horizontal, this);
    	slider->setRange(0, 99);
    	slider->setValue(0);
    
    
    	//别把display(int)写成Display(int)了,不然不会响应的,而且你就算写成display1,
    	//编译器也不会报错,只是不响应
    	//
    	connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
    
    	//信号-->类的信号-->
    	connect(slider, SIGNAL(valueChanged(int)), SIGNAL(valueChanged(int)));
    
    	QVBoxLayout *vlayout = new QVBoxLayout;
    	vlayout->addWidget(lcd);
    	vlayout->addWidget(slider);
    
    	setLayout(vlayout);
    }
    
    int LCDRange::value() const
    {
    	return slider->value();
    }
    
    void LCDRange::setValue(int value)
    {
    	//qWarning("setValue\n");
    	slider->setValue(value);
    }
    
    void LCDRange::setRange(int minVal, int maxVal)
    {
    	if (minVal<0
    		|| maxVal>99
    		|| minVal>maxVal)
    	{
    		//和TRACE相似.
    		qWarning("LCDRange::setRange(%d, %d)\n\t"
    			"Range must be 0...99\n\t"
    			"and minVal must not be greater than maxVal",
    			minVal, maxVal);
    
    		return;
    	}
    
        slider->setRange(minVal, maxVal);
       
    }
    


    main:

    #include "qtlesson.h"
    #include <QtGui/QApplication>
    #include <QPushButton.h>
    #include <QFont.h>
    #include <QVBoxLayout>
    #include <QGridLayout>
    #include "LCDRange.h"
    #include "CannonField.h"
    
    class MyWidget : public QWidget
    {
    public:
    	MyWidget(QWidget *parent=NULL, const char *name=NULL);
    };
    
    MyWidget::MyWidget(QWidget* parent, const char *name)
    {
    	QPushButton *quit = new QPushButton("Quit", this);
    	quit->setFont(QFont(("Times"), 18, QFont::Bold));
    
    	connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
    
    	LCDRange *angle = new LCDRange(this);
    	angle->setRange(5, 70);
    
    	CannonField *cannonField = new CannonField(this);
    
    	connect(angle, SIGNAL(valueChanged(int)), cannonField, SLOT(setAngle(int)));
    	//connect(cannonField, SIGNAL(angleChanged(int)), angle, SLOT(setValue(int)));
    
    	//2X2, 10 pixel border
    	QGridLayout *grid = new QGridLayout(this, 2, 2, 10);
    
    	grid->addWidget(quit, 0, 0);
    	grid->addWidget(angle, 1, 0, Qt::AlignTop);
    	grid->addWidget(cannonField, 1, 1);
    	grid->setColStretch(1, 10);
    
    	angle->setValue(60);
    
    	//设置angle获得键盘焦点,这样默认情况下键盘输入会到达LCDRange窗口部件
    	angle->setFocus();
    }
    
    
    int main(int argc, char *argv[])
    {
    	QApplication a(argc, argv);
    	MyWidget w;
    	w.setGeometry(100, 100, 500, 355);
    	a.setMainWidget(&w);
    	w.show();
    	
    	return a.exec();
    }
    


    1.paintEvent()是一个虚函数,子类可以对父类的paintEvent进行重写。当调用update(),repaint()的时候,paintEvent()会被调用,另外,当界面有任何改变的时候,paintEvent()也会被调用,这种界面的改变包括界面从隐藏到显示,界面尺寸改变,当然还包括界面内容改变的时候会被调用。paintEvent()是已经被高度优化过的函数,它本身已经自动开启并实现了双缓冲(X11系统需要手动去开启双缓冲),因此Qt中重绘不会引起任何闪烁

    2.QPainter默认只能在paintEvent里面调用

  • 相关阅读:
    微服务架构最佳实践 基础设施篇
    深入理解微服务架构:银弹 or 焦油坑?
    uniapp canvasToTempFilePath
    uniapp easycom
    前端302通常不处理,通常使用链接
    linux性能监控命令dstat详解【杭州多测师_王sir】【杭州多测师】
    杭州市民卡面试题【杭州多测师】【杭州多测师_王sir】
    Java创建多线程的3种方式和Java当中的线程池【杭州多测师】【杭州多测师_王sir】
    Python笔试题:给定一个整数数组和一个目标值、找出数组中为2个俩个数、若无返回1【杭州多测师】【杭州多测师_王sir】
    GR/IR差异价格
  • 原文地址:https://www.cnblogs.com/hgy413/p/3693569.html
Copyright © 2020-2023  润新知