2017-02-07 3 views
0

Я использую фреймворк Qt для создания графического интерфейса пользователя. Я использую QGridLayout, чтобы аккуратно разместить мои QWidgets.
Графический интерфейс выглядит следующим образом:Как вставить QWidgets в середине макета?

enter image description here

Мое приложение регулярно добавляет новые виджеты в графическом интерфейсе во время выполнения. Эти новые виджеты обычно не добавляются в конце QLayout, но где-то посередине.

Процедура для этого немного громоздка. Приведенный на рисунке выше, мне нужно будет вынуть widg_C, widg_D, ... из QGridLayout. Затем добавьте widg_x и widg_y, и, наконец, я снова вернул остальные виджеты.
Это, как я удалить виджеты из QGridLayout:

for i in reversed(range(myGridLayout.count())): 
    self.itemAt(i).widget().setParent(None) 
### 

До тех пор, как вы имеете дело с небольшим количеством виджетов, эта процедура не является катастрофой. Но в моем приложении я показываю много маленьких виджетах - возможно, 50 или больше! Приложение замораживает секунду, пока эта процедура продолжается, что очень раздражает пользователя.
Есть ли способ вставить виджеты где-нибудь в QLayout, без необходимости вынимать другие виджеты?


EDIT: Очевидно решение для QVBoxLayout очень просто. Просто используйте функцию insertWidget(..) вместо addWidget(..). Документы можно найти по этой ссылке: http://doc.qt.io/qt-5/qboxlayout.html#insertWidget
К сожалению, я не смог найти аналогичную функцию для QGridLayout.


EDIT: Многие люди справедливо отметили, что положить обратно много виджетов не должно вызывать проблемы с производительностью - это очень быстро на самом деле (спасибо @ekhumoro отметить, что выход). По-видимому, проблема производительности, с которой я столкнулся, связана с алгоритмом, который возвращает виджеты. Это довольно сложный рекурсивный алгоритм, который помещает каждый виджет в правильные координаты в QGridLayout. Это привело к «мерцанию» на моем дисплее. Виджеты вынимаются и возвращаются внутрь с некоторой задержкой (из-за алгоритма), вызывая мерцание.


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

+0

Что касается 'QVBoxLayout', есть' метод insertWidget', и некоторые подобные вопросы , – mbjoe

+0

Я думаю, что вы выбрали неправильную модель для своего графического интерфейса. Например, для такого динамического содержимого вы можете использовать 'QTableWidget'. Он позаботится обо всех вставках/удалениях предметов и т. Д. – vahancho

+0

Должно возникнуть проблема с кодом для вставки виджета, потому что 50 виджетов - это тривиальное число. Я провел некоторое тестирование и занимает менее половины секунды, чтобы вставить виджет в верхней части макета, содержащий 2000 виджетов, и переместить все остальные. – ekhumoro

ответ

0

Спасибо @ekhumoro, @Stuart Fisher, @vahancho и @mbjoe за вашу помощь. В конце концов я нашел способ решить проблему. Я больше не использую QGridLayout(). Вместо этого я построил обертку QVBoxLayout вести себя так, как будто это был GridLayout, с дополнительной функцией, чтобы вставить новые строки:

class CustomGridLayout(QVBoxLayout): 
    def __init__(self): 
     super(CustomGridLayout, self).__init__() 
     self.setAlignment(Qt.AlignTop) # !!! 
     self.setSpacing(20) 


    def addWidget(self, widget, row, col): 
     # 1. How many horizontal layouts (rows) are present? 
     horLaysNr = self.count() 

     # 2. Add rows if necessary 
     if row < horLaysNr: 
      pass 
     else: 
      while row >= horLaysNr: 
       lyt = QHBoxLayout() 
       lyt.setAlignment(Qt.AlignLeft) 
       self.addLayout(lyt) 
       horLaysNr = self.count() 
      ### 
     ### 

     # 3. Insert the widget at specified column 
     self.itemAt(row).insertWidget(col, widget) 

    '''''' 

    def insertRow(self, row): 
     lyt = QHBoxLayout() 
     lyt.setAlignment(Qt.AlignLeft) 
     self.insertLayout(row, lyt) 

    '''''' 

    def deleteRow(self, row): 
     for j in reversed(range(self.itemAt(row).count())): 
      self.itemAt(row).itemAt(j).widget().setParent(None) 
     ### 
     self.itemAt(row).setParent(None) 

    def clear(self): 
     for i in reversed(range(self.count())): 
      for j in reversed(range(self.itemAt(i).count())): 
       self.itemAt(i).itemAt(j).widget().setParent(None) 
      ### 
     ### 
     for i in reversed(range(self.count())): 
      self.itemAt(i).setParent(None) 
     ### 

    '''''' 
Смежные вопросы