Python 在stacklayout中刷新页面内容
我在一个有3页的qt5 python程序中有一个stacklayout。 我通过点击三个图标来改变页面,效果非常好Python 在stacklayout中刷新页面内容,python,qt,user-interface,pyqt5,Python,Qt,User Interface,Pyqt5,我在一个有3页的qt5 python程序中有一个stacklayout。 我通过点击三个图标来改变页面,效果非常好 import sys from PyQt5.QtCore import QSize, Qt from PyQt5.QtGui import QIcon, QPixmap from PyQt5.QtWidgets import ( QAction, QApplication, QHBoxLayout, QLabel, QMainWindow,
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
这段代码工作得很好,但我想知道另一件事
我的布局和截图中的一样
treeview由一个类创建,该类通过查询数据库来构建树
我想在添加新相册时更新它。我是否可以只更新树视图而不是所有页面(可能分为两个布局)?我需要在应用程序的另一个页面上做,这样我才能学会如何做
每次单击工具栏上的图标/按钮时,是否应查询数据库以更新视图?在其他页面中,我可以添加一些信息
(参见答案中的图片)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)
请注意,对于item()
,QTableWidget中新创建的行始终返回None
,如果尚未设置任何值,那么上面的saveFunction()
可能会抛出异常,我显然没有添加所有必需的检查;由您添加适当的数据类型检查。还可以考虑将调色板设置在父窗口小部件上,将调色板传播到所有它的子对象,包括子子,这就是为什么我使用样式表来代替,这允许使用需要特定属性的类的适当选择器;还要注意,我选择使用QFrame来简化事情,因为QWidget不直接支持样式表绘制。或者,您可以使用
self.setAttribute(QtCore.Qt.WA_StyledBackground)
谢谢!我很快就会学习这个代码!