zoukankan      html  css  js  c++  java
  • 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里面调用

  • 相关阅读:
    List of the best open source software applications
    Owin对Asp.net Web的扩展
    NSwag给api加上说明
    'workspace' in VS Code
    unable to find valid certification path to requested target
    JMeter的下载以及安装使用
    exception disappear when forgot to await an async method
    Filter execute order in asp.net web api
    记录web api的request以及response(即写log)
    asp.net web api的源码
  • 原文地址:https://www.cnblogs.com/hgy413/p/3693569.html
Copyright © 2011-2022 走看看