准备战斗
第一次画自定义窗口部件
t8/lcdrange.h包含LCDRange类定义
• t8/lcdrange.cpp包含LCDRange类实现
• t8/cannon.h包含CannonField类定义
• t8/cannon.cpp包含CannonField类实现
• t8/main.cpp包含MyWidget和main
lcdrange.h
#ifndef LCDRANGE_H
#define LCDRANGE_H
#include <QVBoxLayout>
#include <QWidget>
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 <QWidget>
class CannonField:public QWidget
{
Q_OBJECT
public:
CannonField(QWidget *parent = 0);
int showAngle() const{return angle;}//显示角度值
public slots:
void setAngle(int degrees);//接受信号:设置角度值
signals:
void angleChanged(int);//发送信号:角度值变化
protected:
void paintEvent(QPaintEvent *);//窗口刷新/重绘
private:
int angle;//角度值
};
#endif // CANNON_H
cannon.cpp
#include "cannon.h"
#include <QPainter>
CannonField::CannonField(QWidget *parent):QWidget(parent)
{
angle = 45;
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;//若不同,将 angle设置为输入角度
repaint();//调用绘画函数
emit angleChanged(angle);//发送angle变化消息
}
void CannonField::paintEvent(QPaintEvent *)
{
QString s = "Angle = "+QString::number(angle);//创建文本
QPainter p(this);//创建操作窗口部件的QPaonter
p.drawText(200, 200, s);//在(200,200)处绘制文本s
}
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)));
QGridLayout *grid = new QGridLayout;
grid->addWidget(quit, 0, 0);
grid->addWidget(lcdRange, 1, 0, Qt::AlignTop);
grid->addWidget(cannonField, 1, 1);
grid->setColumnStretch(1,10);
lcdRange->setValue(60);
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.show();
return a.exec();
}
结果截图:
用鼠标改变左边滑块的值,lcd屏和右边的绘图界面文本值都会随之变化。按键盘的上下左右键也可控制左边滑块的值,lcd屏和绘图界面的值也随之变化。
1.设置重新定义窗口的大小。如果你把它变窄或者变矮会发生什么?左边一列的大小永远不变,右边一列随窗口增大而增大。
结果截图
小图:
全屏:
因为图片大小有限,全屏图被缩小了,但其实拖动窗口时左边一列的大小并没有发生任何变化。
2.去掉 AlignTop,左边的滑块和lcd屏窗口会占据整个左边,截图如下:
3.如果你给左面的列一个非零的拉伸因数,当你重新定义窗口大小时会发生什么?设置第0列拉伸因子为1,第1列拉伸因子为2,则在窗口大小改变时,它们的比例不变,永远为1:2。
grid->setColumnStretch(0, 1);
grid->setColumnStretch(1, 2);
结果截图
小图:
全屏:
由于边框截多截少不太一样,比例有一点偏差,但其实比例是完全没变的。
4.试着在QButton::setText()调用中把“Quit”改为“&Quit”。按钮看起来变成什么样子了?
加一个&没变,加两个&&会变成下图:
如果你在程序运行的时候按下Alt+Q会发生什么?(在少量键盘中时Meta+Q。)
退出程序
5.把CannonField的文本放到中间。
p.drawText(rect(), Qt::AlignCenter, s);
结果截图: