2017-06-03 105 views
2

經過數小時的工作,我可以在QListView上繪製一個小部件。但是,這幅畫是通過QPixmap完成的。小部件出現了,我可以看到一個進度條。但是,它有點「像素化」(由於使用了QPixmap)。是否有可能直接作爲普通的小部件進行繪製?這是我的問題。直接在QListView上使用QStyledItemDelegate :: paint()繪製小部件()

下面是我做的:

void FileQueueItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    QPaintDevice* original_pdev_ptr = painter->device(); 

    FileQueueListItem* itemWidget = reinterpret_cast<FileQueueListItem*>(index.data(Qt::UserRole).value<void*>()); 

    itemWidget->setGeometry(option.rect); 
    painter->end(); 

    QPixmap pixmap(itemWidget->size()); 
    if (option.state & QStyle::State_Selected) 
     pixmap.fill(option.palette.highlight().color()); 
    else 
     pixmap.fill(option.palette.background().color()); 
    itemWidget->render(&pixmap,QPoint(),QRegion(),QWidget::RenderFlag::DrawChildren); 

    painter->begin(original_pdev_ptr); 
    painter->drawPixmap(option.rect, pixmap); 
} 

我學會了如何做我所做的與here的提示。在那裏,這幅畫直接在QListView上完成,這正是我期望實現的。我做錯了什麼,以下嘗試不工作:

void FileQueueItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    std::cout<<"Painting..."<<std::endl; 
    QPaintDevice* original_pdev_ptr = painter->device(); 

    FileQueueListItem* itemWidget = reinterpret_cast<FileQueueListItem*>(index.data(Qt::UserRole).value<void*>()); 

    itemWidget->setGeometry(option.rect); 
    painter->end(); 

    if (option.state & QStyle::State_Selected) 
     painter->fillRect(option.rect, option.palette.highlight()); 
    else 
     painter->fillRect(option.rect, option.palette.background()); 

    itemWidget->render(painter->device(), 
         QPoint(option.rect.x(), option.rect.y()), 
         QRegion(0, 0, option.rect.width(), option.rect.height()), 
         QWidget::RenderFlag::DrawChildren); 
    painter->begin(original_pdev_ptr); 
} 

列表只是空的,沒有任何反應。雖然可以看到選擇,但小部件不顯示。

+0

如果將'painter-> end();'移動到'itemWidget-> render(...)'之前的行,該怎麼辦? – putu

+0

@putu儘管如此,我仍然可以看到選擇,但看不到控件。 –

+0

您是否嘗試過類似示例中的方法,如[Star Delegate Example](http://doc.qt.io/qt-5/qtwidgets-itemviews-stardelegate-example.html)?也許你會錯過一些東西'sizeHint'。或者,最好使用'painter-> save()'和'painter-> restore()'而不是'begin,end'。我無法提供更多建議,因爲完整的代碼不可用。 – putu

回答

1

讓我們把一些事情說清楚:

  1. 你不應該創建插件,並把它們放在一個模型。這有一個很好的理由。小部件參與了Qt事件循環,這意味着擁有太多小部件會顯着減慢程序。

  2. 小工具不是簡單的一堆控件(這似乎是你如何看待它們)。他們參與事件循環,這就是爲什麼你不應該有一個小部件是數據模型的一部分。

  3. 如果您使用的是多線程程序,並且我們的模型與視圖分離,則內存管理將成爲一場噩夢。 Qt永遠不會容忍嘗試構建或刪除其他線程中的任何窗口小部件(這很有意義,因爲從事件循環中分離線程通常不是線程安全的)。

有了這些信息,有什麼正確的方法來做你想做的事情?可悲的是唯一正確的方法是自己繪製控件。如果你的小部件很簡單,那很容易。如果你的小部件很複雜,你將需要大量的數學來計算每個部件的位置。

Qt Torrent Example中,您將看到如何繪製進度條。所有你需要做的繪製你的控件,計算位置,並使用rect成員變量作爲控件的包含矩形,然後繪製它們(當然,在設置它們的值之後)。函數paint()中有一個參數option.rect,它是整個項目的矩形。你所要做的就是使用一些數學來計算每個部件的矩形內的位置。 PS:從不使用絕對值作爲位置。你永遠不會做對,特別是對於不同的DPI。

這將繪製沒有小部件的控件,並且將保證您甚至需要數千個元素的速度。

相關問題