Refresh Layout and update data

johnashu

I have the following pyqt code that displays a grid of data.

I am able to click on a letter, open a text input box and successfully save the data to the grid and print the updated data in the terminal.

I have tried update() and repaint() but they do nothing aand calling the createLayout() method throws an error of QLayout: Attempting to add QLayout "" to Widget "", which already has a layout

How can I refresh the grid/widget/layout to display the new data?

from PyQt5 import QtWidgets, QtCore, QtGui
import string

grid = [[["text", "GREEN"], 0, ["text", "RED"], 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]]

BTN = """QPushButton{{font-weight: bold; color: {};
        font-size: 14px; background-color: {}; 
        border-width: 2px; border-radius: 100px}}"""


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

        self.letter_count = dict(zip(string.ascii_uppercase, [x for x in range(26)]))

        self.initUI()
        self.createLayout()
        self.center_widget()

    def initUI(self):
        p = self.palette()
        gradient = QtGui.QLinearGradient(0, 0, 0, 400)
        gradient.setColorAt(0.0, QtGui.QColor('#f1f1f1'))
        gradient.setColorAt(1.0, QtGui.QColor('#00a1de'))
        p.setBrush(QtGui.QPalette.Window, QtGui.QBrush(gradient))
        self.setPalette(p)

    def createLayout(self):
        hlay = QtWidgets.QHBoxLayout(self)
        frameL = QtWidgets.QFrame()

        vlay = QtWidgets.QVBoxLayout(frameL)
        frame = QtWidgets.QFrame()
        frame.setObjectName("principal")
        frame.setStyleSheet("#principal{border: 2px solid white;}")
        hlay.addWidget(frameL)
        hlay.addWidget(frame)

        gridLayout = QtWidgets.QGridLayout(frame)

        h = 60  # height

        for i, row in enumerate(grid):
            letter = "{}".format(string.ascii_uppercase[i])
            frameButton = QtWidgets.QFrame()
            frameButton.setFixedHeight(h)
            frameButton.setContentsMargins(0, 0, 0, 0)
            lay = QtWidgets.QVBoxLayout(frameButton)
            button = QtWidgets.QPushButton(letter)
            button.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
            button.clicked.connect(lambda x, letter=letter: self.populate_row(letter)) # Every button click returns 'J'
            lay.addWidget(button)
            vlay.addWidget(frameButton)
            for j, val in enumerate(row):
                gridButton = QtWidgets.QPushButton()
                gridButton.setFixedSize(h, h)
                if isinstance(val, list):
                    gridButton.setText(val[0])
                    if val[1] == "GREEN":
                        gridButton.setStyleSheet(BTN.format('white', 'green'))
                    elif val[1] == "RED":
                        gridButton.setStyleSheet(BTN.format('white', 'red'))
                else:
                    gridButton.setStyleSheet(BTN.format('black', 'white'))
                    gridButton.setText("{}".format(val))
                gridLayout.addWidget(gridButton, i, j)

        for ix in range(j + 1):
            label = QtWidgets.QLabel("{}".format(ix + 1))
            label.setAlignment(QtCore.Qt.AlignCenter)
            gridLayout.addWidget(label, i + 1, ix)
        vlay.addWidget(QtWidgets.QLabel())

    def center_widget(self):
        self.window().setGeometry(
            QtWidgets.QStyle.alignedRect(
                QtCore.Qt.LeftToRight,
                QtCore.Qt.AlignCenter,
                self.window().size(),
                QtWidgets.QApplication.desktop().availableGeometry())
        )

    def populate_row(self, letter):
        """ Populate the row from index 0 - end """
        print(letter)
        self.wi = QtWidgets.QWidget()
        self.wi.resize(660, 360)
        textBox = QtWidgets.QPlainTextEdit(self.wi)
        Rbtn = QtWidgets.QPushButton('Add To Row')
        Rbtn.clicked.connect(lambda: self.input_to_grid(textBox.toPlainText(), letter))       

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(textBox)
        layout.addWidget(Rbtn)

        Rbtn.move(600, 300)

        self.wi.setLayout(layout)

        self.wi.show()
        return self.wi

    def input_to_grid(self, text, letter):
        print(text, letter)
        lst = text.split(' ')
        for i, x in enumerate(lst):
            self.add_to_grid((letter, i + 1), x)
            print((letter, i + 1), x)
        self.print_grid()


    def add_to_grid(self, loc, item):
        x, y = self.translate(loc)
        grid[x][y] = [item] 

    def translate(self, loc):
        for k, v in self.letter_count.items():
            if loc[0].upper() == k:
                x = v
        y = int(loc[1]) - 1
        return x, y

    def print_grid(self):
        """ Print the grid prettier than normal.. """
        print('\n'.join(['\t'.join([str(c) for c in r]) for r in grid]))


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())
eyllanesc

It is a bad idea to replace the layouts or widgets since time and memory are wasted, the correct thing is to reuse, in this case I will create a list of lists that maps the buttons, so when you want to update some data in the grid the data will be updated in the buttons.

from PyQt5 import QtWidgets, QtCore, QtGui
import string

grid = [[["text", "GREEN"], 0, ["text", "RED"], 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]]

BTN = """QPushButton{{font-weight: bold; color: {};
        font-size: 14px; background-color: {}; 
        border-width: 2px; border-radius: 100px}}"""


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

        self.letter_count = dict(zip(string.ascii_uppercase, [x for x in range(26)]))

        self.initUI()
        self.buttons = []
        self.createLayout()
        self.center_widget()

    def initUI(self):
        p = self.palette()
        gradient = QtGui.QLinearGradient(0, 0, 0, 400)
        gradient.setColorAt(0.0, QtGui.QColor('#f1f1f1'))
        gradient.setColorAt(1.0, QtGui.QColor('#00a1de'))
        p.setBrush(QtGui.QPalette.Window, QtGui.QBrush(gradient))
        self.setPalette(p)

    def createLayout(self):
        hlay = QtWidgets.QHBoxLayout(self)
        frameL = QtWidgets.QFrame()

        vlay = QtWidgets.QVBoxLayout(frameL)
        frame = QtWidgets.QFrame()
        frame.setObjectName("principal")
        frame.setStyleSheet("#principal{border: 2px solid white;}")
        hlay.addWidget(frameL)
        hlay.addWidget(frame)

        self.gridLayout = QtWidgets.QGridLayout(frame)

        h = 60  # height

        for i, row in enumerate(grid):
            letter = "{}".format(string.ascii_uppercase[i])
            frameButton = QtWidgets.QFrame()
            frameButton.setFixedHeight(h)
            frameButton.setContentsMargins(0, 0, 0, 0)
            lay = QtWidgets.QVBoxLayout(frameButton)
            button = QtWidgets.QPushButton(letter)
            button.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
            button.clicked.connect(lambda x, letter=letter: self.populate_row(letter)) # Every button click returns 'J'
            lay.addWidget(button)
            vlay.addWidget(frameButton)
            self.buttons.append([])
            for j, val in enumerate(row):
                gridButton = QtWidgets.QPushButton()
                gridButton.setFixedSize(h, h)
                self.buttons[i].append(gridButton)
                self.gridLayout.addWidget(gridButton, i, j)
        for ix in range(j + 1):
            label = QtWidgets.QLabel("{}".format(ix + 1))
            label.setAlignment(QtCore.Qt.AlignCenter)
            self.gridLayout.addWidget(label, i + 1, ix)
        vlay.addWidget(QtWidgets.QLabel())
        self.update_data()


    def update_data(self):
        for i, row in enumerate(grid):
            for j, val in enumerate(row):
                btn = self.buttons[i][j]
                if isinstance(val, list):
                    btn.setText(val[0])
                    if val[1] == "GREEN":
                        btn.setStyleSheet(BTN.format('white', 'green'))
                    elif val[1] == "RED":
                        btn.setStyleSheet(BTN.format('white', 'red'))
                else:
                    btn.setStyleSheet(BTN.format('black', 'white'))
                    btn.setText("{}".format(val))


    def center_widget(self):
        self.window().setGeometry(
            QtWidgets.QStyle.alignedRect(
                QtCore.Qt.LeftToRight,
                QtCore.Qt.AlignCenter,
                self.window().size(),
                QtWidgets.QApplication.desktop().availableGeometry())
        )

    def populate_row(self, letter):
        dialog = QtWidgets.QDialog()
        dialog.resize(660, 360)
        textBox = QtWidgets.QPlainTextEdit(dialog)
        Rbtn = QtWidgets.QPushButton('Add To Row')
        Rbtn.clicked.connect(lambda: self.input_to_grid(textBox.toPlainText(), letter))       

        layout = QtWidgets.QVBoxLayout(dialog)
        layout.addWidget(textBox)
        layout.addWidget(Rbtn)
        dialog.exec_()

    def input_to_grid(self, text, letter):
        print(text, letter)
        lst = text.split(' ')
        for i, x in enumerate(lst):
            self.add_to_grid((letter, i + 1), x)
            print((letter, i + 1), x)
        self.print_grid()
        self.update_data()

    def add_to_grid(self, loc, item):
        x, y = self.translate(loc)
        grid[x][y] = item

    def translate(self, loc):
        for k, v in self.letter_count.items():
            if loc[0].upper() == k:
                x = v
        y = int(loc[1]) - 1
        return x, y

    def print_grid(self):
        """ Print the grid prettier than normal.. """
        print('\n'.join(['\t'.join([str(c) for c in r]) for r in grid]))


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Force refresh/update on data reading

From Dev

Messy data on update pack layout

From Dev

Messy data on update pack layout

From Dev

Refresh Auth user data after update

From Dev

Dynamic data update, no refresh or reload required

From Dev

Refresh datagridview after update data in another form

From Dev

How to refresh a method in Rails model on data update?

From Dev

Refresh datagridview after update data in another form

From Dev

how to refresh tabs data when update table?

From Dev

How refresh data in app after update some data?

From Dev

Material UI table data refresh after redux update data

From Dev

Refresh "root" data inside a UINavigationController and update data in navigation stack

From Dev

android listview update/refresh data without closing the app

From Dev

How invoke angular datatable pagination refresh callback after data update?

From Dev

Windows Phone 8.1 LongListSelector does not automatically update on data refresh

From Dev

Spring Boot Data JPA - Modifying update query - Refresh persistence context

From Dev

How to Refresh data in ng-Repeat after Delete Or Update Records

From Dev

Update Child Component Data on Parent Refresh React Native

From Dev

android listview update/refresh data without closing the app

From Dev

How to update data in gridview without manual refresh in asp.net?

From Dev

Windows Phone 8.1 LongListSelector does not automatically update on data refresh

From Dev

Wpf, how to update/refresh ui after adding data to database

From Dev

React, update DOM elements on submit on posted data without refresh

From Dev

laravel doesn't update data until I refresh the set page

From Dev

Animating a layout refresh crossfade

From Dev

Android Swipe Refresh Layout scroll up to refresh

From Dev

how to refresh layout in on swipe to refresh android

From Dev

how to refresh layout in on swipe to refresh android

From Dev

Using data(...) in D3 force layout to update the graph

Related Related

  1. 1

    Force refresh/update on data reading

  2. 2

    Messy data on update pack layout

  3. 3

    Messy data on update pack layout

  4. 4

    Refresh Auth user data after update

  5. 5

    Dynamic data update, no refresh or reload required

  6. 6

    Refresh datagridview after update data in another form

  7. 7

    How to refresh a method in Rails model on data update?

  8. 8

    Refresh datagridview after update data in another form

  9. 9

    how to refresh tabs data when update table?

  10. 10

    How refresh data in app after update some data?

  11. 11

    Material UI table data refresh after redux update data

  12. 12

    Refresh "root" data inside a UINavigationController and update data in navigation stack

  13. 13

    android listview update/refresh data without closing the app

  14. 14

    How invoke angular datatable pagination refresh callback after data update?

  15. 15

    Windows Phone 8.1 LongListSelector does not automatically update on data refresh

  16. 16

    Spring Boot Data JPA - Modifying update query - Refresh persistence context

  17. 17

    How to Refresh data in ng-Repeat after Delete Or Update Records

  18. 18

    Update Child Component Data on Parent Refresh React Native

  19. 19

    android listview update/refresh data without closing the app

  20. 20

    How to update data in gridview without manual refresh in asp.net?

  21. 21

    Windows Phone 8.1 LongListSelector does not automatically update on data refresh

  22. 22

    Wpf, how to update/refresh ui after adding data to database

  23. 23

    React, update DOM elements on submit on posted data without refresh

  24. 24

    laravel doesn't update data until I refresh the set page

  25. 25

    Animating a layout refresh crossfade

  26. 26

    Android Swipe Refresh Layout scroll up to refresh

  27. 27

    how to refresh layout in on swipe to refresh android

  28. 28

    how to refresh layout in on swipe to refresh android

  29. 29

    Using data(...) in D3 force layout to update the graph

HotTag

Archive