PyQT 中的简单分层列表

发布于 2024-12-06 06:30:59 字数 887 浏览 1 评论 0原文

我正在尝试创建一个包含 3 列的 UI - 当您在左列中选择一个项目时,所选项目将传递给一个函数,并返回中间列的项目(当然,与在左列中选择项目相同)中间列)

应该很简单,但我找不到任何简单的方法来做到这一点..

我首先尝试了 QColumnView,因为它看起来很完美..但是实现 QAbstractItemModel 似乎过于复杂,并且我找不到任何有用的示例这。

接下来,由于层级数是固定的,所以我制作了三个QListView,并修改了 这个示例 QAbstractListModel

..但是,似乎没有有用的信号可以用来触发层次结构其他级别的更新。根据 PyQT 文档, QListView 仅具有“索引已移动”信号。还有“单击”和“按下”,但是当使用键盘更改项目时,这些不会触发

最后一个选项是 QListWidget,它可以工作,因为它具有所需的信号(itemChanged 等),但是创建列表项的方式有点乏味(将 QListWidgetItem 的父级设置为 QListWidget 实例)

编辑:QListWidget 几乎满足了我的需要:

self.first_column = QListWidget()
self.first_column.itemSelectionChanged.connect(self.update_second_column)

I'm trying to create a UI with 3 columns - when you select an item in the left column, the select item is passed to a function, and it returns the items for the middle column (and of course same for selecting items in the middle column)

Should be simple, but I can't find any easy way to do this..

I first tried QColumnView, as it seemed perfect.. however implementing the QAbstractItemModel seems excessively complicated, and I couldn't find any useful examples of this.

Next, since there is a fixed number of levels, I made three QListView, and modified this example QAbstractListModel

..however there seemed to be no useful signal I could use to trigger the updating of the other levels of the hierarchy. According to the PyQT docs, QListView only has the "indexesMoved" signal. There is also "clicked" and "pressed", however these didn't trigger when changing items with the keyboard

The last options is QListWidget, which would work as it has the required signals (itemChanged etc), but the way list items are created is a bit tedious (making QListWidgetItem with the parent set to the QListWidget instance)

Edit: QListWidget does pretty much what I need:

self.first_column = QListWidget()
self.first_column.itemSelectionChanged.connect(self.update_second_column)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

九八野马 2024-12-13 06:30:59

任何 QAbastractItemView 都有一个 QItemSelectionModel 可通过 selectionModel 方法。
QItemSelectionModel 有可能对您有帮助的信号:

currentChanged ( const QModelIndex & current, const QModelIndex & previous )
currentColumnChanged ( const QModelIndex & current, const QModelIndex & previous )
currentRowChanged ( const QModelIndex & current, const QModelIndex & previous )
selectionChanged ( const QItemSelection & selected, const QItemSelection & deselected )

希望有帮助。

Any QAbastractItemView has a QItemSelectionModel accessible via the selectionModel method.
The QItemSelectionModel has signals that may help you:

currentChanged ( const QModelIndex & current, const QModelIndex & previous )
currentColumnChanged ( const QModelIndex & current, const QModelIndex & previous )
currentRowChanged ( const QModelIndex & current, const QModelIndex & previous )
selectionChanged ( const QItemSelection & selected, const QItemSelection & deselected )

Hope it helps.

叶落知秋 2024-12-13 06:30:59

QListView 继承自 QAbstractItemView (我想你知道这一点),所以它得到 一些信号,希望其中一个(或几个)适合您。

这对我有用(在初始化 QMainWindow 或主 QWidget 时连接信号,如 SaltyCrane 示例中所示):

connect(your_list_view, SIGNAL("clicked(const QModelIndex&)"), handler_slot)

...

def handler_slot(idx):
    #idx is a QModelIndex
    #QModelIndex.data() returns a QVariant, Qt4's generic data container
    celldata = idx.data()
    #Choose the proper datatype to ask the QVariant for (e.g. QVariant.toInt())
    actualvalue = celldata.toInt()
    #QVariant.toInt() happens to return a tuple
    print actualvalue[0]

根据模型中的数据类型,您需要选择正确的数据类型来询问QVariant

这里偷偷摸摸的部分是让 QListView 告诉您单击了哪个单元格(即使用 clicked(const QModelIndex&)clicked() ) 。我想我花了一些时间查看 Qt4 的 C++ 文档,然后才意识到您可以从信号中获得更多信息。

从这里,我会让 handler_slot() 在模型上为第二个 QListView 调用 setData() 方法(使用由您最初计划使用的功能)。

如果我没有完全回答你的问题,我很乐意详细说明。

编辑: 使用箭头键

嗯,没有用于箭头移动的默认 QListView 信号似乎很奇怪,但我们可以制作自己的信号。

(对于 Qt4 的信号和槽操作方式来说,这几乎显得不合时宜)

QListView 重新实现了一个方法 keyPressEvent(self, QKeyEvent),该方法在按下某些键时充当回调函数被压。 您可以阅读更多内容。我们可以用它来获取我们想要的键事件,并发出我们自己的信号。

class ArrowableListView(QListView):
    def keyPressEvent(self, keyevent):
        #Maintain original functionality by calling QListView's version
        QListView.keyPressEvent(self, keyevent)

        #QListView.selectedIndexes returns a list of selected cells, I'm just taking the first one here
        idx = self.selectedIndexes()[0]

        #We'll emit a signal that you can connect to your custom handler
        self.emit(SIGNAL("my_signal"), idx)

一旦发生按键,我们就会询问 QListView 所选索引 (!) 是什么。当然,您可以选择过滤掉某些键并选择是否处理多个选定的单元格(我认为您可以设置不可能的选择模式,请参阅QListView文档)。

现在我们已经选择了索引(QModelIndex 列表),我们将第一个索引(QModelIndex)与我们的信号一起传递。因为我们在 python 中定义这个信号,所以我们不必设置函数原型;我不知道这是否是一种糟糕的风格。

现在您所要做的就是将信号连接到处理程序:

self.connect(your_list_view, SIGNAL("my_signal"), handler_slot)

并编写您的处理程序。

我希望这不是一个太令人讨厌的解决方法。

QListView inherits from QAbstractItemView (I think you knew this), so it gets a few signals, hopefully one (or a few) of them works for you.

This is working for me (connect signals when initializing your QMainWindow or main QWidget, as in the SaltyCrane example):

connect(your_list_view, SIGNAL("clicked(const QModelIndex&)"), handler_slot)

...

def handler_slot(idx):
    #idx is a QModelIndex
    #QModelIndex.data() returns a QVariant, Qt4's generic data container
    celldata = idx.data()
    #Choose the proper datatype to ask the QVariant for (e.g. QVariant.toInt())
    actualvalue = celldata.toInt()
    #QVariant.toInt() happens to return a tuple
    print actualvalue[0]

Depending on the type of data in your model, you'll want to choose the right data type to ask QVariant for.

The sneaky part here is getting the QListView to tell you which cell was clicked (i.e. using clicked(const QModelIndex&) vs clicked()). I think I spent some time looking at the C++ documentation for Qt4 before I realized you could get more out of the signals.

From here, I would have the handler_slot() call a setData() method on the model for your second QListView (using data generated by the function you originally planned to use).

I'd be glad to elaborate if I haven't quite answered your question.

Edit: Working with arrow keys

Hmm, it seems weird that there isn't a default QListView signal for arrow movement, but we can make our own.

(This almost seems out-of-style for Qt4's signals and slots modus operandi)

QListView reimplements a method keyPressEvent(self, QKeyEvent) which acts as a callback function when certain keys are pressed. You can read more. We can use this to grab the keyevent(s) that we want, and emit our own signal.

class ArrowableListView(QListView):
    def keyPressEvent(self, keyevent):
        #Maintain original functionality by calling QListView's version
        QListView.keyPressEvent(self, keyevent)

        #QListView.selectedIndexes returns a list of selected cells, I'm just taking the first one here
        idx = self.selectedIndexes()[0]

        #We'll emit a signal that you can connect to your custom handler
        self.emit(SIGNAL("my_signal"), idx)

Once a keypress occurs, we ask the QListView what the selected indices (!) are. Of course, you can choose to filter out certain keys and choose whether to handle multiple selected cells (I think you can set a selection mode where this isn't possible, see QListView documentation).

Now that we have the selected indices (list of QModelIndex), we pass the first one (a QModelIndex) along with our signal. Because we're defining this signal in python, we don't have to set a function prototype; I have no idea if this is bad style.

Now all you have to do is connect the signal to a handler:

self.connect(your_list_view, SIGNAL("my_signal"), handler_slot)

and write your handler.

I hope this isn't too nasty of a workaround.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文