2011-06-28 115 views
6

我嘗試繪製drawRoundedRect方法的圓角矩形直接在QPixmap(無渲染引擎涉及這裏exept純Qt的一個......),我仔細檢查了矩形與我的像素圖的大小尺寸:Qt圓角矩形,爲什麼角落不同?

Pixmap : QSize(50, 73) 
Rectangle: QRect(0,0 48x11) 

看到大量的空間...

編輯:一些代碼

pixmap = QPixmap(50,73); //example size that match my case 
QRectF rect(0,0,48,11); 

QPainter painter(&pixmap); 
painter.setRenderHint(QPainter::TextAntialiasing); 
painter.setWorldMatrixEnabled(false); 
painter.setPen(QPen()); //no pen 
painter.setBrush(QBrush(color)); 
painter.drawRoundedRect(rect, 2.0, 2.0); 
  • 我殘疾人世界變換...
  • I SET設置變換到統一...
  • 我嘗試了幾種半徑(1.0,2.0,3.0,4.0)...
  • 更改筆寬,刷色...

但它總是以4個不同角落的直腸結束!這樣的:

Radius = 3.0 in x and y

我直接ouptut像素圖的文件,以確保我的顯示器......相同的形狀期間沒有颳了。

任何人都知道Qt圓角矩形小半徑?我很久以前就看到過這種情況,但我不想回答這個問題!

回答

14

它看起來像你沒有使用抗鋸齒(即QPainter::Antialiasing渲染提示)。這是一個沒有它的Qt怪癖。從我看到/聽到的情況來看,Qt開發人員並不擔心解決這個問題(無論如何,大多數人都希望進行反鋸齒)。

解決方法(除了只使用反走樣)是用QPainter::drawLine()QPainter::drawArc()自己繪製矩形。你可能需要玩數字,直到它看起來是正確的 - 直接計算往往會出現一個或兩個像素點。此外,您可能會發現即使使用此方法,右下角也不會是,正如與其他角落一樣。

如果你感覺有點雄心勃勃,你可以嘗試解決這個問題並提交補丁給Qt。

更新: Qt 5中的繪圖結果發生了變化。根據我的經驗,這是一個很大的改進。

+2

我用antialising玩其他方式來繪製東西(drwa路徑,弧...)。用這種小東西進行抗鋸齒使其值得!而我最好的投籃是加入〜0.5每一個地方都可能會產生怪異的行爲......所以我會接受**數字**方法! – vrince

+2

有同樣的問題。使用'QPainter p(this); p.setRenderHint(QPainter的::抗鋸齒); p.setRenderHint(QPainter :: HighQualityAlliiasing);'爲我做了詭計。 –

+0

改變筆的寬度做魔術! – Ashish

0

嘗試玩渲染提示 1)禁用antiAliasing; 2)啓用SmoothPixmapTransform

但仍然不能保證它會有所幫助。

+0

正確的說,不保證!! – Ashish

3

嘗試加入半個像素偏移(例如:rect.translated(0.5,0.5)):

QRectF rect(0,0,48,11); 
painter.setRenderHint(QPainter::Antialiasing,false); 
painter.drawRoundedRect(rect.translated(0.5,0.5), 2.0, 2.0); 

我想這具有將整數值兩個像素之間的座標系的事情。

如果使用抗鋸齒繪製並使用1像素寬度的筆,則在精確的整數座標處繪製將導致2像素寬度的線條。 只有使用這個0.5像素的偏移量,您纔會得到恰好爲1像素寬的線條。

QRectF rect(0,0,48,11); 
painter.setRenderHint(QPainter::Antialiasing,true); 
painter.setBrush(Qt::NoBrush); 
painter.setPen(Qt::white); 
painter.drawRoundedRect(rect.translated(0.5,0.5), 2.0,2.0); 
2

我知道這是一個老問題,但對於Qt5用戶呼籲QPaintersetRenderHint(QPainter::Qt4CompatiblePainting);似乎解決了問題。

編輯:

我找到了解決與邊框顏色一起產生一個完美的圓角矩形,它看起來與由QPushButton的邊界例如使用的圓角矩形。這是我是如何實現的paintEvent實現這一目標:

void MyButtonGroup::paintEvent(QPaintEvent * e) 
{ 
    int borderSize = 5; 
    QColor borderColor = Qt::red; 
    QColor backgroundColor = Qt::blue; 
    int borderRadius = 3; 

    QPen pen; 
    pen.setWidth(borderSize); 
    pen.setColor(borderColor); 

    QPainter painter(this); 
    painter.setRenderHint(QPainter::Antialiasing); 
    painter.setPen(pen); 

    QRectF rect(rect().x() + borderSize/2, 
       rect().y() + borderSize/2, 
       rect().width() - borderSize, 
       rect().height() - borderSize); 


    if(borderSize % 2 == 0) 
    { 
     painter.drawRoundedRect(rect, 
           borderSize, 
           borderSize); 
    } 
    else 
    { 
     painter.drawRoundedRect(rect.translated(0.5, 0.5), 
           borderRadius, 
           borderRadius); 
    } 

    QBrush brush(backgroundColor); 
    pen.setBrush(brush); 
    painter.setBrush(brush); 

    if(borderSize % 2 == 0) 
    { 
     painter.drawRoundedRect(rect, 
           borderRadius, 
           borderRadius); 
    } 
    else 
    { 
     painter.drawRoundedRect(rect.translated(0.5, 0.5), 
           borderRadius, 
           borderRadius); 
    } 

    QWidget::paintEvent(e); 
} 

我張貼這一點,因爲我發現它有點難以實現這一結果:

enter image description here

1

做畫ROUNDRECT是最好的方法路徑。 http://developer.nokia.com/community/wiki/Qt_rounded_rect_widget

void fillRoundRect(QPainter& painter, QRect r, int radius) 
{ 
    painter.setRenderHint(QPainter::Antialiasing,true); 

    QPainterPath rounded_rect; 
    rounded_rect.addRoundRect(r, radius, radius); 
    painter.setClipPath(rounded_rect); 

    painter.fillPath(rounded_rect,painter.brush());  
    painter.drawPath(rounded_rect);  
} 
0

我在這裏試圖從答案的所有技巧,但沒有爲我工作。但基於這些代碼片段,我發現了以下解決方案:

默認設置爲m_pPainter->setRenderHint(QPainter::Qt4CompatiblePainting, true),僅適用於寬度爲%2的圓角矩形== 0禁用它。

QRect rect = ConvertRectangle(rectangle); 

int nPenWidth = m_pPainter->pen().width(); 
if (nPenWidth % 2 == 0) 
    m_pPainter->setRenderHint(QPainter::Qt4CompatiblePainting, false); 

m_pPainter->drawRoundedRect(rect, dbRadiusX, dbRadiusY); 

if (nPenWidth % 2 == 0) 
    m_pPainter->setRenderHint(QPainter::Qt4CompatiblePainting, true);