С Новым годом! Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
 Аватар для DjonyCooper
10 / 7 / 4
Регистрация: 28.05.2021
Сообщений: 136
PyQt5

Обновление содержимого в QGroupBox по клику кнопки

13.10.2023, 10:58. Показов 1206. Ответов 3

Студворк — интернет-сервис помощи студентам
Доброго, столкнулся с проблемой того, что не могу обновить содержимое внутри QGroupBox. Я хочу получать все картинки из стандартной папки Pictures в Windows и по нажатию кнопки, если картинок стало больше или меньше обновлять это во view, но при запуске updater функция showImg получает список с новыми изображениями и складывает их внутрь списка pix_dict, но не перерисовывает виджет. Вот минимально воспроизводимый пример на PyQT5:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import fnmatch
import os
import sys
 
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QVBoxLayout, QGridLayout, QGroupBox, QScrollArea, QPushButton
from win32comext.shell import shell, shellcon
 
 
class Main(QWidget):
    def __init__(self):
        super().__init__()
        self.setMinimumSize(300, 300)
        self.setWindowTitle('Test')
 
        grid = QGridLayout()
        grid.addWidget(self.update_photo(), 0, 0, Qt.AlignCenter)
        grid.addWidget(self.showImg(), 1, 0, Qt.AlignCenter)
        grid.addWidget(self.test_widget_2(), 2, 0, Qt.AlignCenter)
        self.setLayout(grid)
 
 
    def update_photo(self):
        but = QPushButton('Обновить')
        but.setFixedSize(200, 50)
        but.clicked.connect(self.updater)
        return but
 
    def test_widget_2(self):
        but = QPushButton('test_but_2')
        but.setFixedSize(200, 50)
        return but
 
    def updater(self):
        self.showImg().close()
        self.showImg()
 
    def find(self, pattern, path):
        result = []
        for root, dirs, files in os.walk(path):
            for name in files:
                if fnmatch.fnmatch(name, pattern):
                    result.append(os.path.join(root, name))
        return result
 
    def showImg(self):
        path = shell.SHGetKnownFolderPath(shellcon.FOLDERID_Pictures)
 
        all_image = self.find('*.jpg', f'{path}')
        pix_dict = []
        for image in all_image:
            pxm = QPixmap(image)
            pix_dict.append(pxm)
 
        box = QGroupBox()
        box.setStyleSheet("border:0;")
 
        scr = QScrollArea(self)
        scr.setStyleSheet('height:0px; width:0px;')
        pnl = QWidget(self)
 
        vbox = QVBoxLayout(self)
        for image in list(reversed(pix_dict)):
            photo_label = QLabel()
            photo_label.setAlignment(Qt.AlignCenter)
            photo_label.setMaximumSize(200, 120)
            photo_label.setPixmap(image.scaled(photo_label.width(), photo_label.height(), Qt.KeepAspectRatio))
 
            vbox.addWidget(photo_label)
 
        pnl.setLayout(vbox)
        scr.setWidget(pnl)
        scr.setWidgetResizable(True)
 
        group_box_layout = QVBoxLayout()
        group_box_layout.addWidget(scr)
        box.setLayout(group_box_layout)
        return box
 
if __name__ == "__main__":
    App = QApplication(sys.argv)
    w = Main()
    w.show()
    sys.exit(App.exec())
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
13.10.2023, 10:58
Ответы с готовыми решениями:

QML - изменение содержимого формы по клику кнопки и виджета
Доброго дня всем!!! стоит задача - на qml написать прогу, где есть возможность изменения содержимого формы на другое содержимое по клику по...

QGroupBox с функцией радио кнопки
Вопрос такой: можно ли создать QGroupBox с функцией радио кнопки. С функцией обычной кнопки я делаю так: qGB_ob1 = new QGroupBox(tr...

Изменение содержимого ячейки по клику
Доброго времени суток. Подскажите пожалуйста, как без jquery можно изменить содержимое ячейки. К примеру, есть таблица на две...

3
290 / 205 / 68
Регистрация: 18.09.2019
Сообщений: 407
Записей в блоге: 58
13.10.2023, 14:19
DjonyCooper, интересно, а почему Вы решили, что вызов метода self.updater() что-то куда-то там складывает?
Ведь по факту
Python
1
2
3
    def updater(self):
        self.showImg().close()
        self.showImg()
первый вызов self.showImg().close() создаст новый объект в области видимости этого метода и тут же его закроет, а второй вызов self.showImg() просто создаст новый объект в области видимости этого метода и никуда его не пристегнёт.
0
 Аватар для DjonyCooper
10 / 7 / 4
Регистрация: 28.05.2021
Сообщений: 136
13.10.2023, 15:44  [ТС]
Согласен с Вами полностью, но self.showImg().close() был написан скорее в приступе эпилепсии, я по не внимательности его не удалил, когда заливал код сюда.

а второй вызов self.showImg() просто создаст новый объект в области видимости этого метода и никуда его не пристегнёт.
а вот тут больше, я понимаю что это создает объект, но .. тут сложнее, по идее же он должен заменять им тот, что уже есть в QGridLayout - не понимаю пока как его туда поместить.

Добавлено через 15 минут
Решил вопрос, не знаю на сколько это верный подход, но он выполняет поставленную задачу:

Изменил функцию:
def updater(self):
self.grid.addWidget(self.showImg(), 1, 0, Qt.AlignCenter)


Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import fnmatch
import os
import sys
 
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QVBoxLayout, QGridLayout, QGroupBox, QScrollArea, QPushButton
from win32comext.shell import shell, shellcon
 
 
class Main(QWidget):
    def __init__(self):
        super().__init__()
        self.setMinimumSize(300, 300)
        self.setWindowTitle('Test')
 
        self.grid = QGridLayout()
        self.grid.addWidget(self.update_photo(), 0, 0, Qt.AlignCenter)
        self.grid.addWidget(self.showImg(), 1, 0, Qt.AlignCenter)
        self.grid.addWidget(self.test_widget_2(), 2, 0, Qt.AlignCenter)
        self.setLayout(self.grid)
 
    def update_photo(self):
        but = QPushButton('Обновить')
        but.setFixedSize(200, 50)
        but.clicked.connect(self.updater)
        return but
 
    def test_widget_2(self):
        but = QPushButton('test_but_2')
        but.setFixedSize(200, 50)
        return but
 
    def updater(self):
        self.grid.addWidget(self.showImg(), 1, 0, Qt.AlignCenter)
 
    def find(self, pattern, path):
        result = []
        for root, dirs, files in os.walk(path):
            for name in files:
                if fnmatch.fnmatch(name, pattern):
                    result.append(os.path.join(root, name))
        return result
 
    def loadImg(self):
        path = shell.SHGetKnownFolderPath(shellcon.FOLDERID_Pictures)
 
        all_image = self.find('*.jpg', f'{path}')
        pix_dict = []
        for image in list(reversed(all_image[5:])):
            pxm = QPixmap(image)
            pix_dict.append(pxm)
        return pix_dict
 
    def showImg(self):
        self.box = QGroupBox()
        self.box.setStyleSheet("border:0;")
 
        self.scr = QScrollArea(self)
        self.scr.setStyleSheet('height:0px; width:0px;')
        self.pnl = QWidget(self)
 
        self.vbox = QVBoxLayout(self)
        for image in (self.loadImg()):
            photo_label = QLabel()
            photo_label.setAlignment(Qt.AlignCenter)
            photo_label.setMaximumSize(200, 120)
            photo_label.setPixmap(image.scaled(photo_label.width(), photo_label.height(), Qt.KeepAspectRatio))
 
            self.vbox.addWidget(photo_label)
 
        self.pnl.setLayout(self.vbox)
        self.scr.setWidget(self.pnl)
        self.scr.setWidgetResizable(True)
 
        self.group_box_layout = QVBoxLayout()
        self.group_box_layout.addWidget(self.scr)
        self.box.setLayout(self.group_box_layout)
        return self.box
 
 
if __name__ == "__main__":
    App = QApplication(sys.argv)
    w = Main()
    w.show()
    sys.exit(App.exec())
0
290 / 205 / 68
Регистрация: 18.09.2019
Сообщений: 407
Записей в блоге: 58
14.10.2023, 18:47
Лучший ответ Сообщение было отмечено DjonyCooper как решение

Решение

Цитата Сообщение от DjonyCooper Посмотреть сообщение
Решил вопрос, не знаю на сколько это верный подход, но он выполняет поставленную задачу:
Единственное замечание, что такой подход небезопасен.
Ведь все эти
Python
1
2
3
4
5
6
7
8
9
10
11
        ...
        self.grid = QGridLayout()
        ...
        self.box = QGroupBox()
        ...
        self.scr = QScrollArea(self)
        ...
        self.pnl = QWidget(self)
        ...
        self.vbox = QVBoxLayout(self)
        ...
приводят к динамическому созданию соответствующих свойств класса Main. И ладно self.grid создаётся сразу при создании экземпляра класса, а остальные-то создаются по мере надобности после вызова других методов. Очень велика вероятность влететь... Пусть уж они томятся внутри методов, как было у Вас сделано в первоначальном варианте. Сама-то суть поставленной задачи сводится к тому, чтобы убрать из соответствующей раскладки устаревший элемент и заменить его новым. Все возможности для этого есть. Например, можно так:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import fnmatch
import os
import sys
 
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QVBoxLayout, QGridLayout, QGroupBox, QScrollArea, QPushButton
from win32comext.shell import shell, shellcon
 
class Main(QWidget):
    def __init__(self):
        super().__init__()
        self.setMinimumSize(300, 300)
        self.setWindowTitle('Test')
 
        grid = QGridLayout()
        grid.setObjectName('main_gridlayout')
        grid.addWidget(self.update_photo(), 0, 0, Qt.AlignCenter)
        grid.addWidget(self.showImg(), 1, 0, Qt.AlignCenter)
        grid.addWidget(self.test_widget_2(), 2, 0, Qt.AlignCenter)
        self.setLayout(grid)
 
    def update_photo(self):
        but = QPushButton('Обновить')
        but.setFixedSize(200, 50)
        but.clicked.connect(self.updater)
        return but
 
    def test_widget_2(self):
        but = QPushButton('test_but_2')
        but.setFixedSize(200, 50)
        return but
 
    def updater(self):
        grid = self.findChild(QGridLayout, 'main_gridlayout')
        box = self.findChild(QGroupBox, 'main_groupbox')
        if grid is None:
            print('Некуда вставить новый QGroupBox!')
        elif box is None:
            grid.addWidget(self.showImg(), 1, 0, Qt.AlignCenter)
        else:
            grid.removeWidget(box)
            box.deleteLater()
            grid.addWidget(self.showImg(), 1, 0, Qt.AlignCenter)
 
    def find(self, pattern, path):
        result = []
        for root, dirs, files in os.walk(path):
            for name in files:
                if fnmatch.fnmatch(name, pattern):
                    result.append(os.path.join(root, name))
        return result
 
    def showImg(self):
        path = shell.SHGetKnownFolderPath(shellcon.FOLDERID_Pictures)
        all_image = self.find('*.jpg', f'{path}')
#        all_image = self.find('*.jpg', './')
        pix_dict = []
        for image in all_image:
            pxm = QPixmap(image)
            pix_dict.append(pxm)
 
        box = QGroupBox()
        box.setObjectName('main_groupbox')
        box.setStyleSheet("border:0;")
 
        scr = QScrollArea(self)
#        scr.setStyleSheet('height:0px; width:0px;')
        pnl = QWidget(self)
 
#        vbox = QVBoxLayout(self)
#        # тут родитель не нужен; если его указать, то будет материться на консоли:
#        # QLayout: Attempting to add QLayout "" to Main "", which already has a layout
        vbox = QVBoxLayout()
        for image in list(reversed(pix_dict)):
            photo_label = QLabel()
            photo_label.setAlignment(Qt.AlignCenter)
            photo_label.setMaximumSize(200, 120)
            photo_label.setPixmap(image.scaled(
                photo_label.width(), photo_label.height(), Qt.KeepAspectRatio))
 
            vbox.addWidget(photo_label)
 
        pnl.setLayout(vbox)
        scr.setWidget(pnl)
        scr.setWidgetResizable(True)
 
        group_box_layout = QVBoxLayout()
        group_box_layout.addWidget(scr)
        box.setLayout(group_box_layout)
        return box
 
if __name__ == "__main__":
    App = QApplication(sys.argv)
    w = Main()
    w.show()
    sys.exit(App.exec_())
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
14.10.2023, 18:47
Помогаю со студенческими работами здесь

Смена содержимого div по клику
Есть тест (плагин wordpress), он отображается списком, хочу сделать его как слайдер. Как с помощью кнопки менять вопросы теста, не...

Отправка содержимого поля в файл при нажатии кнопки без потери этого содержимого с поля
Привет всем!) Я отправляю содержимое textarea в файл при нажатии кнопки, после нажатия на кнопку содержимое стирается с этого поля. Как...

Обновление div по клику
Привет, ломаю голову над задачей одной. Есть следующее: В этом блоке выводится результат <span...

Box: обновление контейнера по клику
Здравствуйте. Проблема такая: Есть фрэйм и контейнер Box. Есть кнопка. Если по ней нажать то контейнер должен обновиться(к нему добавляется...

Обновление Поля по клику по нему
Здравствуйте! Возник такой вопрос. можно ли обвить "Поле" на форме Access кликнув по нему. на форме есть дата начала и конца. конца...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru