【问题标题】:Refresh the content of a page in stacklayout在stacklayout中刷新页面的内容
【发布时间】:2021-07-05 12:07:18
【问题描述】:

我在一个 qt5-python 程序中有一个堆栈布局,有 3 个页面。 我通过单击三个图标来更改页面,并且效果很好。

import sys

from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtWidgets import (
    QAction,
    QApplication,
    QHBoxLayout,
    QLabel,
    QMainWindow,
    QPushButton,
    QStackedLayout,
    QVBoxLayout,
    QWidget,
    QStatusBar,
    QToolBar,
)



### TESTING CLASS ###
from PyQt5.QtGui import QColor, QPalette
from PyQt5.QtWidgets import QWidget
class Color(QWidget):
    def __init__(self, color):
        super().__init__()
        self.setAutoFillBackground(True)

        palette = self.palette()
        palette.setColor(QPalette.Window, QColor(color))
        self.setPalette(palette)
### TESTING CLASS ###


I_INDEX_PAGE_DISC = 0
I_INDEX_PAGE_SONG = 1
I_INDEX_PAGE_INSTRUMENT = 2

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Studio Diary")
        self.setWindowIcon(QIcon("img/icon/icone_main_window.png"))        
        
        ### IMPOSTA DIMENSIONE INTERFACCIA ###
        self.resize(900, 300)
        
        
        ### CREA LA BARRA DEGLI STRUMENTI ###
        tbMainToolBar = QToolBar("Studio Diary Toolbar")
        tbMainToolBar.setIconSize(QSize(64, 64))
        tbMainToolBar.setMovable(False)
        self.addToolBar(tbMainToolBar)
        
        
        lstButtonIcon = []
        
        ### CREA ICONA DISCO ###
        icoDisc = QIcon()
        icoDisc.addPixmap(QPixmap("img/icon/toolbar/icon_disc_on.png"))
        icoDisc.addPixmap(QPixmap("img/icon/toolbar/icon_disc_sel.png"), QIcon.Disabled)
        ### CREA BOTTONE DISCO ###
        bticDisc = QAction(icoDisc, "Dischi", self)
        bticDisc.setStatusTip("Gestisci i dischi")
        
        lstButtonIcon.append(bticDisc)
        
        ### CREA ICONA CANZONE ###
        icoSong= QIcon()
        icoSong.addPixmap(QPixmap("img/icon/toolbar/icon_song_on.png"))
        icoSong.addPixmap(QPixmap("img/icon/toolbar/icon_song_sel.png"), QIcon.Disabled)
        ### CREA BOTTONE DISCO ###
        bticSong = QAction(icoSong, "Canzoni", self)
        bticSong.setStatusTip("Gestisci le canzoni")
        
        lstButtonIcon.append(bticSong)
        
        ### CREA ICONA STRUMENTO ###
        icoInstrument = QIcon()
        icoInstrument.addPixmap(QPixmap("img/icon/toolbar/icon_instrument_on.png"))
        icoInstrument.addPixmap(QPixmap("img/icon/toolbar/icon_instrument_sel.png"), QIcon.Disabled)
        ### CREA BOTTONE STRUMENTO ###
        bticInstrument = QAction(icoInstrument, "Strumenti", self)
        bticInstrument.setStatusTip("Gestisci gli strumenthi")
        
        lstButtonIcon.append(bticInstrument)

        ### AGGIUNGI BOTTONE DISCO ###
        bticDisc.triggered.connect(lambda lam_pageDisc: self.activateDiscPage(lstButtonIcon))
        tbMainToolBar.addAction(bticDisc)
        ### AGGIUNGI BOTTONE CANZONE ###
        bticSong.triggered.connect(lambda lam_pageSong: self.activateSongPage(lstButtonIcon))
        tbMainToolBar.addAction(bticSong)
        ### AGGIUNGI BOTTONE CANZONE ###
        bticInstrument.triggered.connect(lambda lam_pageInstrument: self.activateInstrumentPage(lstButtonIcon))
        tbMainToolBar.addAction(bticInstrument)

        
        ### CREA IL LAYOUT GENERALE ###
        bvloMainPageLayout = QVBoxLayout()
        self.stacklayout = QStackedLayout()

        bvloMainPageLayout.addLayout(self.stacklayout)

        self.stacklayout.addWidget(Color("red"))
        self.stacklayout.addWidget(Color("green"))
        self.stacklayout.addWidget(Color("yellow"))

        wgtBodyApp = QWidget()
        wgtBodyApp.setLayout(bvloMainPageLayout)
        self.setCentralWidget(wgtBodyApp)
        self.setStatusBar(QStatusBar(self))
        
 
    def buildDiscPage(self, strColor="red"):
        
        bhloDiscPage = QVBoxLayout()
        tvAlbumSong = TreeView()
        bhloDiscPage.addWidget(tvAlbumSong)
        bhloDiscPage.addWidget(QLabel("Song"))
        
    def buildSongPage(self):
        
        bhloSongPage = QHBoxLayout()
        self.stacklayout.addWidget(QLabel("cyan"))
      
        
    def buildInstrumentPage(self):
        
        bhloSongPage = QHBoxLayout()
        self.stacklayout.addWidget(QLabel("yellow"))       
        

  
    def activateDiscPage(self,mLstButtonIcon):
        
        ### IMPEDISCI CHE LA PAGINA VENGA RICHIAMATA SE E' GIA' STATA SELEZIONATA ###
        bticCurrentButton = mLstButtonIcon[I_INDEX_PAGE_DISC]
        blnIsEnabled = bticCurrentButton.isEnabled()
        if blnIsEnabled == True:
            self.buildDiscPage("green")
            self.stacklayout.setCurrentIndex(I_INDEX_PAGE_DISC)
            bticCurrentButton.setDisabled(True)
            self.resetIconButtonActivationStatus(mLstButtonIcon,I_INDEX_PAGE_DISC)
        
            
    def activateSongPage(self,mLstButtonIcon):
        
        ### IMPEDISCI CHE LA PAGINA VENGA RICHIAMATA SE E' GIA' STATA SELEZIONATA ###
        bticCurrentButton = mLstButtonIcon[I_INDEX_PAGE_SONG]
        blnIsEnabled = bticCurrentButton.isEnabled()
        if blnIsEnabled == True:
            self.buildSongPage()
            self.stacklayout.setCurrentIndex(I_INDEX_PAGE_SONG)
            bticCurrentButton.setDisabled(True)
            self.resetIconButtonActivationStatus(mLstButtonIcon,I_INDEX_PAGE_SONG)


    def activateInstrumentPage(self,mLstButtonIcon):
        
        ### IMPEDISCI CHE LA PAGINA VENGA RICHIAMATA SE E' GIA' STATA SELEZIONATA ###
        bticCurrentButton = mLstButtonIcon[I_INDEX_PAGE_INSTRUMENT]
        blnIsEnabled = bticCurrentButton.isEnabled()
        if blnIsEnabled == True:
            self.buildInstrumentPage()
            self.stacklayout.setCurrentIndex(I_INDEX_PAGE_INSTRUMENT)
            mLstButtonIcon[I_INDEX_PAGE_INSTRUMENT].setDisabled(True)
            self.resetIconButtonActivationStatus(mLstButtonIcon,I_INDEX_PAGE_INSTRUMENT)
        
        
    ### RESETTA LO STATUS DI ATTIVAZIONE DEI BOTTONI
    # === riattiva tutti i bottoni tranne quello corrente ===
    def resetIconButtonActivationStatus(self,mLstButtonIcon,mIntCurrent):
        
        for iButton in range (len(mLstButtonIcon)):
            
            btIcSingleButton = mLstButtonIcon [iButton]
            
            if  iButton != mIntCurrent:
                btIcSingleButton.setEnabled(True)


appMain = QApplication(sys.argv)

winMain = MainWindow()
winMain.show()

appMain.exec_()

当我点击图标时,我将打开相关页面,使用调用 buildPage() 的方法 activatePage()

我希望页面内容会更新。

例如:在一个页面中,我将查询数据库,或者在另一个页面中,我将一些参数传递给 buildPage() 函数以更改页面中的某些元素或样式。

我应该如何修改这些函数?

[编辑]

0

这段代码完美运行,但我想知道另一件事。

我的布局类似于屏幕截图中的布局。

树视图由通过查询数据库构建树的类创建。

我想在添加新专辑时更新它。我可以只更新树视图而不是所有页面(可能分成两种布局)吗?我需要在应用程序的其他页面中执行此操作,以便学习如何执行此操作。

每次单击工具栏上的图标/按钮时,我应该查询数据库以更新视图吗?在其他页面中,我可以添加一些信息。

(见答案中的图片)

【问题讨论】:

    标签: python qt user-interface pyqt5


    【解决方案1】:

    QStackedLayout 适用于可重用的“页面”,就像“选项卡式”界面一样(事实上,QTabWidget 使用基于 QStackedLayout 的私有 QStackedWidget)。

    考虑到页面是可重复使用的,您的问题是您实际上并没有切换到页面,而是每次都在不断地添加一个页面。

    虽然动态创建页面显然是可能的,即使出于优化目的,在您的情况下您不需要这样做,因为您只有 3 个页面。

    由于这 3 个页面可能会有自己的“静态”布局,更好的解决方案是为每个页面创建单独的子类,这样可以创建特定的函数来在需要时更新数据。这比创建在创建/切换页面时执行几乎相同操作的单个函数要好得多,并且您可以使用单个界面来访问/设置每个页面的数据。

    这是一个可能的实现:

    from PyQt5 import QtCore, QtWidgets
    
    class Disco(QtWidgets.QFrame):
        def __init__(self):
            super().__init__()
            self.artista = QtWidgets.QLineEdit()
            self.titolo = QtWidgets.QLineEdit()
            layout = QtWidgets.QFormLayout(self)
            layout.addRow('Artista', self.artista)
            layout.addRow('Titolo', self.titolo)
    
        def setData(self, data):
            self.artista.setText(data.get('artista', ''))
            self.titolo.setText(data.get('titolo', ''))
    
        def getData(self):
            return {'artista': self.artista.text(), 'titolo': self.titolo.text()}
    
    
    class Canzoni(QtWidgets.QFrame):
        def __init__(self):
            super().__init__()
            layout = QtWidgets.QVBoxLayout(self)
            self.table = QtWidgets.QTableWidget(0, 2)
            self.table.setHorizontalHeaderLabels(('Titolo', 'Durata'))
            layout.addWidget(self.table)
            self.addButton = QtWidgets.QPushButton('Aggiungi')
            layout.addWidget(self.addButton)
            self.addButton.clicked.connect(lambda: 
                self.table.insertRow(self.table.rowCount()))
    
        def setData(self, data):
            self.table.clearContents()
            canzoni = data.get('canzoni', [])
            self.table.setRowCount(len(canzoni))
            for row, (titolo, durata) in enumerate(canzoni):
                self.table.setItem(row, 0, QtWidgets.QTableWidgetItem(titolo))
                durataItem = QtWidgets.QTableWidgetItem()
                durataItem.setData(QtCore.Qt.DisplayRole, int(durata))
                self.table.setItem(row, 1, durataItem)
    
        def getData(self):
            canzoni = []
            for row in range(self.table.rowCount()):
                canzoni.append([
                    self.table.item(row, 0).text(), 
                    self.table.item(row, 1).data(QtCore.Qt.DisplayRole), 
                ])
            return {'canzoni': canzoni}
    
    
    class Strumenti(QtWidgets.QFrame):
        def __init__(self):
            super().__init__()
            layout = QtWidgets.QVBoxLayout(self)
            self.table = QtWidgets.QTableWidget(0, 2)
            layout.addWidget(self.table)
            self.table.setHorizontalHeaderLabels(('Artista', 'Strumenti'))
            self.table.verticalHeader().hide()
            self.addButton = QtWidgets.QPushButton('Aggiungi')
            layout.addWidget(self.addButton)
            self.addButton.clicked.connect(lambda: 
                self.table.insertRow(self.table.rowCount()))
    
        def setData(self, data):
            self.table.clearContents()
            strumenti = data.get('strumenti', [])
            self.table.setRowCount(len(strumenti))
            for row, (artista, strumento) in enumerate(strumenti):
                self.table.setItem(row, 0, QtWidgets.QTableWidgetItem(artista))
                self.table.setItem(row, 1, QtWidgets.QTableWidgetItem(strumento))
    
        def getData(self):
            strumenti = []
            for row in range(self.table.rowCount()):
                strumenti.append([
                    self.table.item(row, 0).text(), 
                    self.table.item(row, 1).text(), 
                ])
            return {'strumenti': strumenti}
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
            self.stackWidget = QtWidgets.QStackedWidget()
            self.setCentralWidget(self.stackWidget)
    
            self.disco = Disco()
            self.stackWidget.addWidget(self.disco)
    
            self.canzoni = Canzoni()
            self.stackWidget.addWidget(self.canzoni)
    
            self.strumenti = Strumenti()
            self.stackWidget.addWidget(self.strumenti)
    
            self.pages = self.disco, self.canzoni, self.strumenti
    
            self.loadAction = self.menuBar().addAction('Load')
            self.loadAction.triggered.connect(self.loadData)
            self.saveAction = self.menuBar().addAction('Save')
            self.saveAction.triggered.connect(self.saveData)
    
            for i, actionName in enumerate(('Disco', 'Canzoni', 'Strumenti')):
                action = self.menuBar().addAction(actionName)
                action.setData(i)
    
            self.menuBar().triggered.connect(self.switchPageAction)
    
            self.setStyleSheet('''
                Disco {
                    background: red;
                }
                Canzoni {
                    background: green;
                }
                Strumenti {
                    background: yellow;
                }
            ''')
            self.switchPage(0)
    
        def loadData(self):
            data = {
                'artista': 'Elio e le Storie Tese', 
                'titolo': 'Elio Samaga Hukapan Kariyana Turu', 
                'canzoni': [
                    ['John Holmes', 206], 
                    ['Nubi di ieri sul nostro domani odierno', 253], 
                ], 
                'strumenti': [
                    ['Elio', 'Voci'], 
                    ['Rocco', 'Tastiere'], 
                ]
            }
            for page in self.pages:
                page.setData(data)
    
        def saveData(self):
            data = {}
            for page in self.pages:
                data.update(page.getData())
            print(data)
    
        def switchPageAction(self, action):
            index = action.data()
            if index is not None:
                self.switchPage(index)
    
        def switchPage(self, index):
            self.stackWidget.setCurrentIndex(index)
            for action in self.menuBar().actions():
                action.setEnabled(action.data() != index)
    

    注意QTableWidget中新创建的行如果还没有设置值,总是返回item()None,所以上面的saveFunction()可能会抛出异常,我显然没有添加所有必需的检查;添加适当的数据类型检查由您决定。
    还要考虑在父小部件上设置调色板也会将调色板传播到其所有子组件,包括子子组件,这就是我改用样式表的原因,它允许为需要特定属性的类使用适当的 selector;另请注意,我选择使用 QFrame 来简化事情,因为 QWidget 不直接支持样式表绘制。或者,您可以使用self.setAttribute(QtCore.Qt.WA_StyledBackground)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-04
      • 2012-09-17
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 2020-07-09
      • 1970-01-01
      • 2020-07-28
      相关资源
      最近更新 更多