2013-08-29 31 views
5

我想通過除行的長度來減少我的畫筆描邊(在QPixmap上)的間距。如果我乘上這條線,那麼間距就會增加,但間距不會減小。此外,它看起來線路可以有一個最小長度。顯然劃分它會減少 - 可能低於允許的數量?不知道這會不會影響pixmap的繪製。Qt中的線插值?

這裏是有問題的代碼:

QLineF line = QLineF(lastPoint, endPoint); 
float lineLength = line.length(); 
qDebug() << line.length(); 
line.setLength(lineLength/50.0f); 
qDebug() << line.length(); 

painter.drawPixmap(line.p1().x() - 16, line.p2().y() - 16, 32, 32, testPixmap); 

這裏是所有的代碼在這個特殊文件:

#include "inkspot.h" 
#include "inkpuppet.h" 
#include "ui_inkpuppet.h" 

#include "newdialog.h" 
#include "ui_newdialog.h" 

#include <QtCore> 
#include <QtGui> 
#include <QWidget> 
#include <QPainter> 
#include <QPaintEvent> 

InkSpot::InkSpot(QWidget *parent) : 
    QWidget(parent) 
{ 
    widget = this; 
    drawing = false; 
} 

void InkSpot::mousePressEvent(QMouseEvent *event) 
{ 
    if(event->button() == Qt::LeftButton) 
    { 
     lastPoint = event->pos(); 
     drawing = true; 
    } 
} 

void InkSpot::mouseMoveEvent(QMouseEvent *event) 
{ 
    if((event->buttons() & Qt::LeftButton) && drawing) 
    { 
     drawLineTo(event->pos()); 
    } 
} 

void InkSpot::mouseReleaseEvent(QMouseEvent *event) 
{ 
    if(event->button() == Qt::LeftButton && drawing) 
    { 
     drawLineTo(event->pos()); 
     drawing = false; 
    } 
} 

void InkSpot::drawLineTo(const QPoint &endPoint) 
{ 
    QPainter painter(&pixmap); 
    painter.setPen(Qt::NoPen); 
    painter.setBrush(Qt::NoBrush); 

    QFile *stencilInput; // file for input, assumes a SQUARE RAW 8 bit grayscale image, no JPG no GIF, no size/format header, just 8 bit values in the file 
    char *brushPrototype; // raw brush prototype 
    uchar *brushData; // raw brush data 

    stencilInput = new QFile("C:/brush3.raw"); // open raw file 
    stencilInput->open(QIODevice::ReadOnly); 
    QDataStream in; 
    in.setDevice(stencilInput); 
    int size = stencilInput->size(); // set size to the length of the raw file 

    brushPrototype = new char[size]; // create the brush prototype array 
    in.readRawData(brushPrototype, size); // read the file into the prototype 
    brushData = new uchar[size]; // create the uchar array you need to construct QImage 

    for (int i = 0; i < size; ++i) 
     brushData[i] = (uchar)brushPrototype[i]; // copy the char to the uchar array 

    QImage test(brushData, 128, 128, QImage::Format_Indexed8); // create QImage from the brush data array 
    // 128x128 was my raw file, for any file size just use the square root of the size variable provided it is SQUARE 
    QImage test2(128, 128, QImage::Format_ARGB32); 


    QVector<QRgb> vectorColors(256); // create a color table for the image 
    for (int c = 0; c < 256; c++) 
     vectorColors[c] = qRgb(c, c, c); 

    test.setColorTable(vectorColors); // set the color table to the image 

    for (int iX = 0; iX < 128; ++iX) // fill all pixels with 255 0 0 (red) with random variations for OIL PAINT effect 
    // use your color of choice and remove random stuff for solid color 
    // the fourth parameter of setPixel is the ALPHA, use that to make your brush transparent by multiplying by opacity 0 to 1 
    { 
     for (int iY = 0; iY < 128; ++iY) 
     { 
      test2.setPixel(iX, iY, qRgba(255, 100, 100, (255-qGray(test.pixel(iX, iY)))*0.5)); 
     } 
    } 
    // final convertions of the stencil and color brush 
    QPixmap testPixmap = QPixmap::fromImage(test2); 
    QPixmap testPixmap2 = QPixmap::fromImage(test); 

    painter.setBrush(Qt::NoBrush); 
    painter.setPen(Qt::NoPen); 
    // in a paint event you can test out both pixmaps 
    QLineF line = QLineF(lastPoint, endPoint); 
    float lineLength = line.length(); 
    qDebug() << line.length(); 
    line.setLength(lineLength/50.0f); 
    qDebug() << line.length(); 

    painter.drawPixmap(line.p1().x() - 16, line.p2().y() - 16, 32, 32, testPixmap); 

    //delete all dynamically allocated objects with no parents 
    delete [] brushPrototype; 
    delete [] brushData; 
    delete stencilInput; 


    lastPoint = endPoint; 

} 


void InkSpot::paintEvent(QPaintEvent *event) 
{ 
    QPainter painter(this); 
    painter.setPen(Qt::NoPen); 
    painter.setBrush(Qt::NoBrush); 
    QRect rect = event->rect(); 
    painter.drawPixmap(rect, pixmap, rect); 
    update(); 

} 
+0

順便說一句,你真的應該將創建刷像素映射到一個單獨的方法的代碼,畫筆只需要在更改時創建,每次繪製線條時都沒有必要創建它。重新使用畫筆直到需要更新。 – dtech

回答

5

不要使用QLineF,使用QPainterPath - 它有幾個很便利的方法:

qreal QPainterPath::percentAtLength (qreal len) const 
QPointF QPainterPath::pointAtPercent (qreal t) const 
qreal length() const 

因此,而不是使用QLineF您創建一個畫家路徑,其中只包含從舊到新繪圖光標位置的單一行,獲取該行的長度,然後迭代以間距遞增的長度以獲取百分比值,您可以從中獲取該值一個QPointF必須繪製畫筆像素圖的每個位置。這很簡單。

編輯:好的,這,沒有測試過,大腦終端,但這樣的事情:

QPointF lastPosition, currentPosition; 
qreal spacing; 

void draw() { 
    QPainterPath path; 
    path.moveTo(lastPosition); 
    path.lineTo(currentPosition); 
    qreal length = path.length(); 
    qreal pos = 0; 

    while (pos < length) { 
     qreal percent = path.percentAtLength(pos); 
     drawYourPixmapAt(path.pointAtPercent(percent)); // pseudo method, use QPainter and your brush pixmap instead 
     pos += spacing; 
    } 
} 
+0

我不知道如何構建循環來做到這一點。你能舉個例子嗎? – Vii

+0

@ user1090427 - 確定,檢查答案編輯。 – dtech