2012-02-23 17 views
6

Tôi có một QListView, nơi tôi hiển thị các mục bằng cách sử dụng đại biểu tùy chỉnh có sơn tùy chỉnh. Trong mỗi mục (nghĩa là mỗi hàng trong danh sách), tôi muốn có thể hiển thị một vài "siêu liên kết" mà người dùng có thể nhấp vào và sau đó sẽ gọi một số chức năng.Phần tử có thể nhấp hoặc tiện ích con bên trong đại biểu được sơn tùy chỉnh

Tôi đã cố gắng kiểm tra tài liệu chính thức (ví dụ: Model/View Programming) cũng như khá nhiều googling, nhưng không thể tìm ra cách để thực hiện việc này.

Tôi có hai ý tưởng, đều có những vấn đề riêng của họ:

  • tôi có thể vẽ chúng bằng các widget con, giống như một QPushButton phẳng. Làm cách nào để tôi định vị và hiển thị các tiện ích này?
  • Tôi cũng có thể vẽ chúng dưới dạng chuỗi văn bản. Làm thế nào để tôi làm cho họ có thể nhấp? Hoặc tôi có thể nắm bắt các sự kiện bấm trên QListView cha mẹ và bằng cách nào đó xác định tọa độ từ những người? Sau đó tôi có thể đối sánh tọa độ với các yếu tố có thể nhấp này và hành động tương ứng.

Cách tiếp cận ban đầu của tôi là sử dụng QListWidget với .setItemWidget(), nơi tôi có một tiện ích thích hợp với bố cục và tiện ích con. Thật không may, điều này quá chậm khi danh sách của tôi tăng lên đến hàng trăm hoặc hàng nghìn mục. Đó là lý do tại sao tôi đã thay đổi thành QListView với một đại biểu.

Trả lời

1

Tôi dường như đang kết thúc giải pháp.

Tôi có thể nhận được nhấp chuột vào các phần tử bằng cách ghi đè số .editorEvent(event, model, option, index) của đại biểu. Sau đó tôi có thể tìm ra số event.type(), hàng được nhấp từ index.row() và tọa độ thực tế từ event.x()event.y() (vì, nếu loại sự kiện là MouseButtonRelease, sự kiện này là QMouseEvent).

Từ đó, tôi nghĩ rằng tôi có thể tương quan các tọa độ với các phần tử của tôi trên màn hình và hành động tương ứng.

Tôi sẽ cập nhật câu trả lời này sau khi tôi có mã làm việc.

EDIT

Một ví dụ đơn giản làm việc, sử dụng PySide:

class MyModel(QtGui.QStandardItemModel): 
    def __init__(self): 
    super(MyModel, self).__init__() 
    for i in range(10): self.appendRow(QtGui.QStandardItem("Row %d" % i)) 

class MyDelegate(QtGui.QStyledItemDelegate): 
    def __init__(self, parent=None): 
    super(MyDelegate, self).__init__(parent) 
    self.links = {} 

    def makeLinkFunc(self, row, text): 
    def linkFunc(): print("Clicked on %s in row %d" % (text, row)) 
    return linkFunc 

    def paint(self, painter, option, index): 
    painter.save() 
    textHeight = QtGui.QFontMetrics(painter.font()).height() 

    painter.drawText(option.rect.x()+2, option.rect.y()+2+textHeight, index.data()) 

    rowLinks = {} 
    for i in range(3): 
     text = "Link %d" % (3-i) 
     linkWidth = QtGui.QFontMetrics(font).width(text) 
     x = option.rect.right() - (i+1) * (linkWidth + 10) 
     painter.drawText(x, y, text) 
     rect = QtCore.QRect(x, y - textHeight, linkWidth, textHeight) 
     rowLinks[rect] = self.makeLinkFunc(index.row(), text) 

    self.links[index.row()] = rowLinks 
    painter.restore() 

    def sizeHint(self, option, index): 
    hint = super().sizeHint(option, index) 
    hint.setHeight(30) 
    return hint 

    def editorEvent(self, event, model, option, index): 
    if event.type() == QtCore.QEvent.MouseButtonRelease: 
     for rect, link in self.links[index.row()].items(): 
     if rect.contains(event.pos()): 
      link() 
      return True 
    return False 

listmodel = MyModel() 
listview = QtGui.QListView() 
listview.setModel(listmodel) 
listview.setItemDelegate(MyDelegate(parent=listview)) 
listview.setSelectionMode(QtGui.QAbstractItemView.NoSelection) 
Các vấn đề liên quan