Как правильно включить/выключить кнопку при выделении элемента QTreeWidget?

Рейтинг: 1Ответов: 2Опубликовано: 22.08.2023

Нарисовал в Qt Designer себе GUI, в нем есть простейший одноуровневый QTreeWidget и несколько не активных QPushButton (снял галочку enabled в Qt Designer).

Хочу, чтобы при выделении строки (когда один раз левой кнопкой мыши) в QTreeWidget, мои QPushButton становились активны, а при исчезновении фокуса (к примеру, если выделенную строку удалить) - обратно отключались.

Вроде бы, это надо делать через подключение какого то сигнала из QTreeWidget в ... куда?
Писать отдельную функцию про включение/выключение кнопок? Или есть более простые решения?

Т.к. ни у кого перед глазами готового QTreeWidget не нашлось, закидываю текст .py файлов:

ui_one_button.py:

from PyQt6 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(502, 180)
        MainWindow.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight)
        MainWindow.setStyleSheet("background-color: rgb(254, 214, 188);")
        self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.Baby_Groot = QtWidgets.QPushButton(parent=self.centralwidget)
        self.Baby_Groot.setEnabled(False)
        font = QtGui.QFont()
        font.setPointSize(11)
        self.Baby_Groot.setFont(font)
        self.Baby_Groot.setStyleSheet("background-color: rgb(85, 170, 255);")
        self.Baby_Groot.setObjectName("Baby_Groot")
        self.gridLayout.addWidget(self.Baby_Groot, 0, 0, 1, 1)
        self.Groot = QtWidgets.QTreeWidget(parent=self.centralwidget)
        self.Groot.setObjectName("Groot")
        item_0 = QtWidgets.QTreeWidgetItem(self.Groot)
        item_0 = QtWidgets.QTreeWidgetItem(self.Groot)
        item_0 = QtWidgets.QTreeWidgetItem(self.Groot)
        self.gridLayout.addWidget(self.Groot, 1, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 502, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.mf_Open = QtGui.QAction(parent=MainWindow)
        self.mf_Open.setObjectName("mf_Open")

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.Baby_Groot.setText(_translate("MainWindow", "Baby Groot"))
        self.Groot.headerItem().setText(0, _translate("MainWindow", "1"))
        self.Groot.headerItem().setText(1, _translate("MainWindow", "2"))
        self.Groot.headerItem().setText(2, _translate("MainWindow", "3"))
        __sortingEnabled = self.Groot.isSortingEnabled()
        self.Groot.setSortingEnabled(False)
        self.Groot.topLevelItem(0).setText(0, _translate("MainWindow", "New Item"))
        self.Groot.topLevelItem(0).setText(1, _translate("MainWindow", "1"))
        self.Groot.topLevelItem(0).setText(2, _translate("MainWindow", "1"))
        self.Groot.topLevelItem(1).setText(0, _translate("MainWindow", "New Item"))
        self.Groot.topLevelItem(2).setText(0, _translate("MainWindow", "New Item"))
        self.Groot.setSortingEnabled(__sortingEnabled)
        self.mf_Open.setText(_translate("MainWindow", "Open"))

main_one_button.py:

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow
from ui_one_button import Ui_MainWindow


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        # self.Groot.[что то?].connect(self.Baby_Groot.setEnabled())
        # self.Groot.[что то?].connect(self.Baby_Groot.setDisabled()) # хотя вот это и не обязательно, выключать кнопки можно и с того кто удаляет строку, да.


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

Собственно, что писать заместо [квадратных скобок]?

Ответы

▲ 1Принят

Я понял вашу задачу так:

import sys
#from PyQt6.QtWidgets import QApplication, QMainWindow
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *


#from ui_one_button import Ui_MainWindow
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(502, 180)
        MainWindow.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight)
        MainWindow.setStyleSheet("background-color: #F5DEB3;")
        self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.Baby_Groot = QtWidgets.QPushButton(parent=self.centralwidget)
        self.Baby_Groot.setEnabled(False)
        font = QtGui.QFont()
        font.setPointSize(18)
        self.Baby_Groot.setFont(font)
        self.Baby_Groot.setStyleSheet("background-color: #FF69B4; color: #7CFC00;")
        self.Baby_Groot.setObjectName("Baby_Groot")
        self.gridLayout.addWidget(self.Baby_Groot, 0, 0, 1, 1)
        
        self.Groot = QtWidgets.QTreeWidget(parent=self.centralwidget)
        self.Groot.setObjectName("Groot")
        item_0 = QtWidgets.QTreeWidgetItem(self.Groot)
        item_0 = QtWidgets.QTreeWidgetItem(self.Groot)
        item_0 = QtWidgets.QTreeWidgetItem(self.Groot)
        self.gridLayout.addWidget(self.Groot, 1, 0, 6, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 502, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
  
# ???        self.mf_Open = QAction(parent=MainWindow)      # ???
# ???        self.mf_Open.setObjectName("mf_Open")          # ???

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.Baby_Groot.setText(_translate("MainWindow", "Baby Groot"))
        self.Groot.headerItem().setText(0, _translate("MainWindow", "1"))
        self.Groot.headerItem().setText(1, _translate("MainWindow", "2"))
        self.Groot.headerItem().setText(2, _translate("MainWindow", "3"))
        __sortingEnabled = self.Groot.isSortingEnabled()
        self.Groot.setSortingEnabled(False)
        
        self.Groot.topLevelItem(0).setText(0, _translate("MainWindow", "New Item 0"))
        self.Groot.topLevelItem(0).setText(1, _translate("MainWindow", "1"))
        self.Groot.topLevelItem(0).setText(2, _translate("MainWindow", "2"))
        self.Groot.topLevelItem(1).setText(0, _translate("MainWindow", "New Item 1"))
        self.Groot.topLevelItem(2).setText(0, _translate("MainWindow", "New Item 2"))
        
        self.Groot.setSortingEnabled(__sortingEnabled)
# ???        self.mf_Open.setText(_translate("MainWindow", "Open"))    


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.Groot.itemSelectionChanged.connect(self.onSmthChanged)
        self.Baby_Groot.clicked.connect(self.onBabyClicked)

    def onSmthChanged(self, *args):
        if self.Groot.selectedItems():
            self.Baby_Groot.setEnabled(True)
            self.Baby_Groot.setStyleSheet(
                "background-color: rgb(127, 255, 0); color: #006400;")
        else:
            self.Baby_Groot.setEnabled(False)

    # Удаляем выбранный элемент из списка
    def onBabyClicked(self):
        QTreeWidget.invisibleRootItem(self.Groot).takeChild(
            self.Groot.currentIndex().row())

        items = self.Groot.selectedItems()       
        [it.setSelected(False) for it in items]
        self.Baby_Groot.setStyleSheet("background-color: #FF69B4; color: #7CFC00;")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

▲ 0

Ок, вроде как сам до чего то дотыкался. У меня вроде как работает.
Сверху добавил простенькую функцию, при нажатии кнопки удаляет выделенный элемент.

Изменения только в файле main_one_button.py:

import sys

# Добавился импорт QTreeWidget'а:
from PyQt6.QtWidgets import QApplication, QMainWindow, QTreeWidget

from ui_one_button import Ui_MainWindow


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

# два коннекта - первый обрабатывает изменение выбранного элемента в Груте, второй - клик на Бэйби Грута:
        self.Groot.itemSelectionChanged.connect(self.onSmthChanged)
        self.Baby_Groot.clicked.connect(self.onBabyClicked)

    def onSmthChanged(self):
# Если для Грута существует выбранный элемент - включаем кнопку, иначе - выключаем.
        if self.Groot.selectedItems():
            self.Baby_Groot.setEnabled(True)
        else:
            self.Baby_Groot.setEnabled(False)

# Удаляем выбранный элемент из списка
    def onBabyClicked(self):
        QTreeWidget.invisibleRootItem(self.Groot).takeChild(self.Groot.currentIndex().row())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())