Как удалить пустое пространство (пустое) в виджете вкладки после удаления PlotWidget? - PullRequest
1 голос
/ 12 марта 2020

У меня есть небольшое приложение для панели инструментов, где я могу динамически добавлять и удалять графики. Проблема в том, что когда я нажимаю кнопку x (виджет уничтожения графа), график исчезает из вида, но оставляет пустоту над верхним оставшимся графиком (см. Прикрепленный скриншот).

Я в значительной степени полный новичок в этом, но я подозреваю, что я не имею дело с удалением виджетов и объектов правильно?

В моем упрощенном коде ниже у меня есть класс dashboard_tab, где через нажатие кнопки я создать объект add_new_graph, который создает новый виджет графика self.graphWidget = pg.PlotWidget().

При инициации закрытия (или уничтожения) виджета графика я вызываю следующий код:

def kill_widget(self):
        self.lay.removeWidget(self.graphWidget)
        self.graphWidget.deleteLater()
        self.graphWidget = None

Это как-то кажется работать, так как графический виджет исчезает из вида, а не нежелательной пустоты.

Тогда я также хотел убить объект add_new_graph ... если он как-то связан с моей проблемой ... возможно, создав сигнал от объекта add_new_graph обратно к dashboard_tab объект ... но он не может заставить это работать.

Итак, мои вопросы:

  • Какова наиболее вероятная причина нежелательной пустоты после удаления виджета?
  • Нужно ли также удалять объект, чтобы иметь правильное кодирование?

Любые точки в правильном направлении приветствуются!

class MainWindow(QtWidgets.QWidget):
    def __init__(self, parent):
        super(QtWidgets.QWidget, self).__init__(parent)
        self.layout = QtWidgets.QVBoxLayout(self)

        self.tab_holder = QtWidgets.QTabWidget()
        tab1 = dashboard_tab()

        self.tab_holder.addTab(tab1, "Dashboard")
        self.layout.addWidget(self.tab_holder)


class dashboard_tab(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.lay = QtWidgets.QVBoxLayout(self)

        self.numGraphs = 0

        addGraphBtn = QtWidgets.QToolButton()
        addGraphBtn.setText("  Add Graph")

        addGraphBtnMenu = QtWidgets.QMenu()
        addGraphBtnMenu.addAction('Add Temp Graph', self.add_graph)
        addGraphBtn.setMenu(addGraphBtnMenu)

        self.lay.addWidget(addGraphBtn)

    def add_graph(self):
        # Create a unique graph name
        self.name = ("graph" + str(self.numGraphs))

        self.graph = add_new_graph(self.name)
        self.lay.addWidget(self.graph)

        # Up graph name index every time a new graph is created
        self.numGraphs += 1


class add_new_graph(QtWidgets.QWidget):

    def __init__(self, name):
        super().__init__()
        self.name = name

        self.lay = QtWidgets.QHBoxLayout(self)

        self.graphWidget = pg.PlotWidget()
        self.killWidgetBtn = QtWidgets.QPushButton('')
        self.killWidgetBtn.clicked.connect(self.kill_widget)

        self.lay.addWidget(self.killWidgetBtn)
        self.lay.addWidget(self.graphWidget)

    def kill_widget(self):
        self.lay.removeWidget(self.killWidgetBtn)
        self.killWidgetBtn.deleteLater()
        self.killWidgetBtn = None

        self.lay.removeWidget(self.graphWidget)
        self.graphWidget.deleteLater()
        self.graphWidget = None


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

Снимок экрана приложения Dashboard

1 Ответ

1 голос
/ 12 марта 2020

Происходит то, что вы удаляете только дочерние виджеты (график и кнопку), но не виджет контейнера, который вы добавили в макет.

Даже после удаления этих объектов контейнер имеет минимальный размер, заданный полями содержимого макета (в зависимости от операционной системы и текущего стиля они обычно составляют от 5 до 10 пикселей), и это «пустота», которую вы можете видеть.

Вместо удаления дочерних виджетов вы можете удалить контейнер.


class add_new_graph(QtWidgets.QWidget):
    def __init__(self, name):
        # ...
        self.killWidgetBtn.clicked.connect(<b>self.deleteLater</b>)

В любом случае, вы можете предпочесть, чтобы вас предупреждали, когда такой виджет будет удален, поэтому я бы посоветовал взять на себя ответственность родителей. для этого:


class dashboard_tab(QtWidgets.QWidget):
    # ...
    def add_graph(self):
        # ...
        graph = add_new_graph(self.name)
        graph.deleteRequested.connect(self.deleteGraph)

    def deleteGraph(self, graph):
        # some warning message box, maybe?
        if QtWidgets.QMessageBox.warning(self, 'Close?', 
            'Delete the graph?', 
            QtWidgets.QMessageBox.Ok|QtWidgets.QMessageBox.Cancel
            ) != QtWidgets.QMessageBox.Ok:
                return
        graph.deleteLater()

class add_new_graph(QtWidgets.QWidget):
    deleteRequested = QtCore.pyqtSignal(object)

    def __init__(self, name):
        # ...
        self.killWidgetBtn.clicked.connect(
            lambda: <b>self.deleteRequested.emit(self)</b>)

Предложение, если можно: используйте имена классов в верхнем регистре (чтобы их можно было легко отличить от функций), и не используйте «описания действий» для их имен: классы обычно не «делают» вещи сами по себе, их методы делают.

...