// 鼠标点击屏幕自动生成点,已设置点的数量最大为10,
//点击绘制自动生成cardinal曲线,拖动滑动条修改张力参数t
//曲线随之变化,同时点也可以用鼠标点击拖动
#include "widget.h"
#include "ui_widget.h"
#include<QHBoxLayout>
#include<QToolTip>
#include<QPainter>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setFixedSize(1980,1080);
this->setWindowTitle(tr("Cardinal曲线"));
draw= new QPushButton(tr("绘制"), this);
clear= new QPushButton(tr("清空缓存"), this);
draw->setGeometry(0,0,100,28);
clear->setGeometry(120,0,100,28);
connect(draw, SIGNAL(clicked()), this, SLOT(ClickButton_paint()));
connect(clear, SIGNAL(clicked()), this, SLOT(ClickButton_clear()));
tensionlabel=new QLabel(this);
tensionlabel->setText("Tension:");
tensionlabel->setGeometry(10,50,200,25);
QFont ft;
ft.setPointSize(12);//设置字号
tensionlabel->setFont(ft);
tensionslider=new QSlider(this);
tensionslider->setOrientation(Qt::Horizontal);
tensionslider->setFixedSize(250,100);
tensionslider->setFixedHeight(20);
tensionslider->setGeometry(10,100,10,28);
tensionslider->setMaximum(50);
tensionslider->setMinimum(-50);
tensionslider->setValue(0);
line=new QLineEdit(this);
line->setText("0");
line->setGeometry(100,50,100,28);
QHBoxLayout *layout = new QHBoxLayout();
layout->addWidget(tensionslider);
layout->addWidget(tensionlabel);
layout->addWidget(line);
connect(tensionslider, SIGNAL(valueChanged(int)), this, SLOT(setValue(int)));
//connect(tensionbox, SIGNAL(valueChanged(double)), this, SLOT(setValue(int)));
}
Widget::~Widget()
{
delete ui;
}
void Widget::ClickButton_clear()
{
points.clear();
points_clear();
tensionslider->setValue(0);
line->setText("0");
tension=0;
flag=0;
}
void Widget::ClickButton_paint()
{
flag=1;//绘制标志
qDebug()<<"绘制"<<endl;
if(points.size()>=4)
{
cardianl_points();
}
}
void Widget::paintEvent(QPaintEvent*event)
{
QPainter painters(this);
QPen pen1;
pen1.setWidth(5);
pen1.setColor(Qt::red);
painters.setPen(pen1);
painters.drawPoints(points);
QPen pen2;
pen2.setWidth(2);
painters.setPen(pen2);
painters.drawPoints(line_points);
//flag=0;
update();
}
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
mouse_style=0;
setCursor(Qt::ArrowCursor);
update();
}
void Widget::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
if(event->pos().x()>300||event->pos().y()>150)
{
if(points.size()<10&&flag==0)
{
points.push_back(event->pos());
++i;
}
if(flag==1)
{
for(int j=0;j<points.size();++j)
{
if(abs(event->pos().x()-points[j].x())<=5&& abs(event->pos().y()-points[j].y())<=5)
{
//判断鼠标的位置
mouse_style=1;
setCursor(Qt::CrossCursor);
position=j;
update();
break;
}
}
}
}
}
update();
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
m=0; //还应该在这在给m 赋一次值 为了清空鼠标上一次在某个点上留下的值
QString zuo=QString("%1 %2").arg(event->pos().x()).arg(event->pos().y());
QToolTip::showText(QPoint(event->globalPos()),zuo,this);
if(points.size()>=4)
{
for(int i=0;i<points.size();i++)
{
if(abs(event->pos().x()-points[i].x())<=5&& abs(event->pos().y()-points[i].y())<=5)
{
m=m+1;
}
}
if(m!=0)
{
setCursor(Qt::CrossCursor); //改变鼠标的样式
update(); //刷新
}
if(mouse_style==1)
{
//改变点的位置
points[position]=event->pos();
points_clear();
cardianl_points();
update();
}
}
update();
}
void Widget::setValue(int value)
{
double pos = tensionslider->value();
pos=pos/10;
tension=pos;
qDebug()<<"tension:"<<tension<<endl;
QString str = QString("%1").arg(pos);
line->setText(str);
points_clear();
if(line_points.size()==points.size()*1000)
{
cardianl_points();
}
cardianl_points();
update();
}
QPointF Widget:: cardinal(QPointF p1,QPointF p2,QPointF p3,QPointF p4,double u)
{
double u2,u3,s;
QPointF result_point;
//qDebug()<<"tension:"<<tension<<endl;
s=(1.0-tension)/2.0;
u2=u*u;
u3=u2*u;
result_point=p1*(-s*u3+2*s*u2-s*u)+p2*((2-s)*u3+(s-3)*u2+1)
+p3*((s-2)*u3+(3-2*s)*u2+s*u)+p4*(s*u3-s*u2);
return result_point;
}
void Widget:: cardianl_points()
{
for(int j=1;j<points.size();++j)
{
if(j!=1)
{
if((j+1)!=points.size())
{
QPointF p0;
u=0;
for(int i=0;i<1000;++i)
{
p0=cardinal(points[j-2],points[j-1],points[j],points[j+1],u);
if(line_points.size()<(j+1)*1000)
{
line_points.push_back(p0);
u+=0.001;
}
}
}
else
{
QPointF p0;
u=0;
for(int i=0;i<1000;++i)
{
p0=cardinal(points[j-2],points[j-1],points[j],points[j],u);
if(line_points.size()<(j+1)*1000)
{
line_points.push_back(p0);
u+=0.001;
}
}
}
}
else
{
QPointF p0;
u=0;
for(int i=0;i<1000;++i)
{
p0=cardinal(points[0],points[0],points[1],points[2],u);
if(line_points.size()<1000)
{
line_points.push_back(p0);
u+=0.001;
}
else
break;
}
}
}
}
void Widget:: points_clear()
{
line_points.clear();
}