(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);
到此爲止就完成啦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章