(qt)【学习记录】绘制调色板

qt绘制调色板
我的博客原链接:http://www.hbzmlab.tech/index.php/2019/02/14/qt%E7%BB%98%E5%88%B6%E8%B0%83%E8%89%B2%E6%9D%BF/
最终效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2uMoFnPQ-1588349545864)(http://www.hbzmlab.tech/wp-content/uploads/2019/02/%E6%8D%95%E8%8E%B7.png)]
前面的步骤就是创建一个qt界面类,继承qwidget。然后以下绘制内容都在paintEvent里完成

首先是圆环,用到的是QConicalGradient扇形渐变;

QConicalGradient conicalGradient(0, 0, 0);
conicalGradient.setColorAt(0.0, Qt::red);
conicalGradient.setColorAt(60.0 / 360.0, Qt::yellow);
conicalGradient.setColorAt(120.0 / 360.0, Qt::green);
conicalGradient.setColorAt(180.0 / 360.0, Qt::cyan);
conicalGradient.setColorAt(240.0 / 360.0, Qt::blue);
conicalGradient.setColorAt(300.0 / 360.0, Qt::magenta);
conicalGradient.setColorAt(1.0, Qt::red);

painter.translate(r, r);//将painter坐标移到中间,r是控件一半大小
painter.rotate(90);//顺时针旋转画布90度
QBrush brush(conicalGradient);//填充渐变
painter.setPen(Qt::NoPen);//没有描边
painter.setBrush(brush);//设置填充
painter.drawEllipse(QPoint(0, 0), r, r);//绘制圆盘
这是目前的效果,

接下来要挖掉中间的部分

painter.setBrush(QBrush(Qt::white));
painter.drawEllipse(QPoint(0, 0), r-20, r-20);
绘制一个白的圆。半径比原来小20

然后先来绘制中间的方形面板,先来分析,横向是由白到选中颜色的渐变,纵向是黑色到透明的渐变,所以这里巧妙地使用两步绘制,

第一步:rgb是用来记录当前选中的圆环上的颜色的。

QLinearGradient Linear(-r / 2, 0, r/2, 0); //垂直渐变

Linear.setColorAt(0, Qt::white);
Linear.setColorAt(1, QColor(R, G, B));

painter.setBrush(Linear);
painter.setPen(Qt::transparent);
painter.drawRect(-r/2, -r/2, r, r);

第二步,绘制黑色到透明的渐变

QLinearGradient Liner(0, -r / 2,0 , r/2);

Liner.setColorAt(0, QColor(0,0,0,0));
Liner.setColorAt(1, QColor(0,0,0,255));

painter.setBrush(Liner);
painter.setPen(Qt::transparent);
painter.drawRect(-r / 2, -r / 2, r, r);

接下来是捕获鼠标坐标,绘制滑块以及计算对应rgb值,首先要给自己写的界面类加入两个函数

void mouseMoveEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *);

通过重写鼠标事件来监听鼠标的位置,鼠标坐标是相对于控件的左上角的

在press函数中写:

QPoint center = QPoint(r, r);
QPoint mouse = event->pos();
QPoint barpos2 = (mouse - center);
把鼠标转化为以人r,r为中心的坐标;

int length = sqrt(barpos2.x()*barpos2.x() + barpos2.y()*barpos2.y());
if (length > r - 20 && length < r)
{
}
计算距离来判断是否在圆环上

然后要做的工作就是把鼠标的坐标换算到角度,以方便后面的rgb计算,

用到c++的atan2函数:atan2(x,y)

cita = atan2(barpos.x(), barpos.y());

换算后的角度是这样的。然后分析颜色的对应得角度来设计rgb计算函数,大致就是插值,为了确保256的精度,角度用double来保存,并且不做换算处理;

void ColorWheel::setRGB()
{
if (cita > halfpi / 3 * 2)
{
R = 0; G = 255; B = 255 * (cita - halfpi / 3 * 2)/ halfpi * 3;
}
else if (cita > halfpi / 3) {
R = 255 ( 1-( cita -halfpi / 3 ) / halfpi * 3);G = 255; B = 0;
}
else if (cita > 0) {
R = 255; G = 255 * (cita) / halfpi * 3;B = 0;
}
else if (cita > -halfpi / 3) {
R = 255; G = 0;B = 255 * -(cita) / halfpi * 3;
}
else if (cita > -halfpi / 3
2) {
R = 255*(1+ (cita +halfpi / 3) / halfpi * 3); G = 0;B = 255;
}
else {
R = 0; G = 255 * -(cita + halfpi / 3 * 2) / halfpi * 3; B = 255;
}
}

(这里的halfpi是笔误,实际是pi的值);//今天就写到这了。明天科二模拟2019/2/14

然后是圆环上滑块的绘制,这个只要将鼠标相对中心的坐标放缩到圆环的半径长度就行了。(这部分运算我写在paintevent过程内,因为不止是鼠标拖动过程需要运算坐标。控件宽度改变,也需要改变滑块坐标。所以写在paintevent的话。mouseevent中调用update就能更新界面了)

r = this->width() / 2;
{
int length = sqrt(barpos.x()*barpos.x() + barpos.y()*barpos.y());
barpos *= r - 20;
barpos /= length;
}
然后绘制滑块到这个坐标

painter.setPen(QPen(QColor(245,245,245), 1));//白色边框
painter.setBrush(QBrush(QColor(R,G,B)));//对应rgb填充
painter.drawEllipse(barpos, 12, 12);//绘制

接下来就是内部明度和灰度与鼠标坐标的转换运算,以及绘制选点。

我们用bytemd来记录明度,bytehd来记录灰度,范围是0-255,然后在 做一个bool Panalchangeable来记录是否按下在方形范围内

if (mouse.x() >= r / 2&&mouse.x() <= r 3/ 2&&mouse.y() >= r / 2&&mouse.y() <= r * 3 / 2)
{
bytehd = (double)(r * 3 / 2 - mouse.x()) / r * 255;
bytemd = (double)(r
3/2-mouse.y()) / r * 255;
Panalchangeable = true; = true;
}
以上判断范围是写在pressevent里的,至于moveevent里只要判断标志位Panalchangeable就可以了

if (Panalchangeable) {
QPoint mouse = event->pos();
if (mouse.x() < r / 2)
{
bytehd = 255;

}
else if (mouse.x() > r * 3 / 2) {
	bytehd = 0;
}
else {
	bytehd = (double)(r * 3 / 2 - mouse.x()) / r * 255;
}
if (mouse.y() < r / 2)
{
	bytemd = 255;

}
else if (mouse.y() > r * 3 / 2) {
	bytemd = 0;
}
else {
	bytemd = (double)(r * 3 / 2 - mouse.y()) / r * 255;
}

在接下来是根据 明度,灰度,色值来确定最终rgb值 fr fg fb;

void ColorWheel::calFinalRGB()
{
fR = R + (255 - R)*bytehd / 255;//类似插值

fG = G + (255 - G)*bytehd / 255;

fB = B + (255 - B)*bytehd / 255;

fR = fR*bytemd / 255;//设置明度
fG = fG*bytemd / 255;
fB = fB*bytemd / 255;

}
到这里为止只剩下绘制选点了。

painter.setPen(QPen(QColor(245, 245, 245), 1));

painter.setBrush(QBrush(QColor(fR, fG, fB)));
QPoint po(r/2-bytehd/255.0r,r/2-bytemd/255.0r);
painter.drawEllipse(po, 5, 5);
到此为止就完成啦

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值