سؤال

لقد قمت بإنشاء نموذج يسرد التكوينات الموجودة (دعنا نقول إنه يسرد "الملفات" ، لأن هذا لا يهم هنا حقًا). حتى الآن ، يعمل بشكل جيد عند إرفاقه بـ QListView.

مثال:

--- ListView ---
- file #1      -
- file #2      -
- file #3      -
- file #4      -
----------------

هل من الممكن استخدام نفس النموذج لتحديث ديناميكي QMenu ?

شيء مثل:

Menu
-> Submenu #1
-> Submenu #2
-> File-submenu
  -> file #1
  -> file #2
  -> file #3
  -> file #4
-> Submenu #3

باختصار: هل هناك أي طريقة لإنشاء قائمة بالديناميكية المحدثة QActionS (تم تجميعها في نفس الشيء QMenu) اعتمادا على أ نموذج (مستمدة من QAbstractListModel) ?

هل كانت مفيدة؟

المحلول

إذا كان هدفك هو مجرد تحديث قائمتك Actons مع نص العنصر المتاح في QAbstractListModel, ثم الجواب نعم.

هذه طريقة ..

يمكن الحصول على فهرس العنصر الفردي باستخدام الوظيفة التالية.

QModelIndex QAbstractListModel::index ( int row, int column = 0, 
const QModelIndex & parent = QModelIndex() ) const   [virtual]

مع الفهرس الذي تم الحصول عليه ، يمكن الحصول على البيانات بواسطة ،

 QVariant QModelIndex::data ( int role = Qt::DisplayRole ) const

ثم يمكن الحصول على النص المتاح في الفهرس باستخدام ،

QString QVariant::toString () const

الآن مع QString التي تم الحصول عليها يمكنك إضافة إجراء إلى القائمة.

QAction * QMenu::addAction ( const QString & text )

الشيء الذي عليك التأكد من أنه ، يجب أن تكون قادرًا على اجتياز جميع العناصر الموجودة في النموذج ، بحيث يمكنك الحصول على فهرس كل عنصر. أتمنى أن يساعد ..

نصائح أخرى

للأسف لا يوجد QMenuView الفصل لكنني وجدت هذا التنفيذ الواعد على الشبكة: QMenuView (Qmenuview.H, Qmenuview.cpp).

للإجابة على سؤالك القصير ، نعم ، هناك. ولكن عليك أن تكتبها بنفسك.

سيكون الجزء السهل هو إنشاء فئة فرعية من QabstractListModel.

سيكون الجزء الصعب عند إنشاء عرضك الخاص. ستسمح لك QT بإنشاء عرض خاص بك ، تمامًا كما لو كنت ستنشئ النموذج الخاص بك ، ولكنه سيصبح أكثر تعقيدًا كثيرًا ، حيث يجب عليك التعامل كل شىء نفسك.

إنه ممكن تمامًا لغرض محدد ، لكنه أيضًا عمل أكثر بكثير مما أعتقد. هكذا ، كما كان يقول جياني ، لا يُقصد باستخدام إطار عرض طراز QT من هذه الطريقة.

لا. لا يمكن استخدام النماذج إلا مع وجهات النظر ، وفقًا ل عرض النموذج الإطار الذي يستخدمه QT.

يمكنك إنشاء عنصر قائمة ووضعه QListView فيه باستخدام QWidgetAction. بالطبع لا يمكن أن تحتوي هذه القائمة على قوائم فرعية. المثال أدناه موجود في بيثون ، لكنني آمل ألا يهم في هذه الحالة.

enter image description here

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt


class QListViewMenu(QtWidgets.QMenu):
    """
    QMenu with QListView.
    Supports `activated`, `clicked`, `doubleClicked`. `setModel`.
    """
    max_visible_items = 16

    def __init__(self, parent=None):
        super().__init__(parent)
        self.listview = lv = QtWidgets.QListView()
        lv.setFrameShape(lv.NoFrame)
        lv.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        pal = lv.palette()
        pal.setColor(pal.Base, self.palette().color(pal.Window))
        lv.setPalette(pal)
        lv.setEditTriggers(lv.NoEditTriggers)  # disable edit on doubleclick

        act_wgt = QtWidgets.QWidgetAction(self)
        act_wgt.setDefaultWidget(lv)
        self.addAction(act_wgt)

        self.activated = lv.activated
        self.clicked = lv.clicked
        self.doubleClicked = lv.doubleClicked
        self.setModel = lv.setModel

        lv.sizeHint = self.size_hint
        lv.minimumSizeHint = self.size_hint
        lv.mousePressEvent = lambda event: None  # skip
        lv.mouseMoveEvent = lambda event: None  # skip
        lv.mouseReleaseEvent = self.mouse_release_event

    def size_hint(self):
        lv = self.listview
        width = lv.sizeHintForColumn(0)
        width += lv.verticalScrollBar().sizeHint().width()
        if isinstance(self.parent(), QtWidgets.QToolButton):
            width = max(width, self.parent().width())
        visible_rows = min(self.max_visible_items, lv.model().rowCount())
        return QtCore.QSize(width, visible_rows * lv.sizeHintForRow(0))

    def mouse_release_event(self, event):
        if event.button() == Qt.LeftButton:
            idx = self.listview.indexAt(event.pos())
            if idx.isValid():
                self.clicked.emit(idx)
            self.close()
        super(QtWidgets.QListView, self.listview).mouseReleaseEvent(event)


class Form(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        words = "ability able about above accept according account across"
        model = QtCore.QStringListModel(words.split())
        # fake icons to take space
        def data(index, role):
            if role == Qt.DecorationRole:
                pixm = QtGui.QPixmap(40, 40)
                pixm.fill(Qt.transparent)
                return QtGui.QIcon(pixm)
            return QtCore.QStringListModel.data(model, index, role)
        model.data = data

        self.btn = btn = QtWidgets.QToolButton(self)
        btn.setText("QListView menu")
        btn.setPopupMode(btn.MenuButtonPopup)
        root_menu = QtWidgets.QMenu(btn)
        menu = QListViewMenu(btn)
        menu.setTitle('submenu')
        menu.setModel(model)
        menu.clicked.connect(self.item_clicked)
        root_menu.addMenu(menu)
        btn.setMenu(root_menu)

    def item_clicked(self, index):
        self.btn.menu().hide()
        print(index.data())

app = QtWidgets.QApplication([])
f = Form()
f.show()
app.exec()
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top